• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.10/Security-57031.1.35/Security/libsecurity_apple_csp/open_ssl/opensslUtils/
1/*
2 * Copyright (c) 2003,2011-2012,2014 Apple Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19/*
20 * opensslAsn1.h - ANS1 encode/decode of openssl object, libssnasn1 version
21 */
22#include "opensslAsn1.h"
23#include "BinaryKey.h"
24#include "AppleCSPUtils.h"
25#include "opensshCoding.h"
26#include <Security/osKeyTemplates.h>
27#include <openssl/err.h>
28#include <openssl/bn.h>
29#include <openssl/crypto.h>
30
31#include <security_asn1/SecNssCoder.h>
32#include <security_asn1/secerr.h>
33#include <Security/keyTemplates.h>
34#include <security_utilities/debugging.h>
35#include <Security/oidsalg.h>
36#include <Security/SecAsn1Templates.h>
37
38#include <assert.h>
39
40#define sslAsn1Debug(args...)	secdebug("sslAsn1", ##args)
41
42#ifndef	NDEBUG
43/* set to 1 to see all ASN related errors */
44#define LOG_ASN_ERRORS  0
45#else
46#define LOG_ASN_ERRORS  0
47#endif
48
49#if		LOG_ASN_ERRORS
50#include <stdio.h>
51#include <security_asn1/secerr.h>
52
53static void logAsnErr(
54	const char *op,
55	PRErrorCode perr)
56{
57	printf("Error on %s: %s\n", op, SECErrorString(perr));
58}
59#else
60#define logAsnErr(op, perr)
61#endif  /* LOG_ASN_ERRORS */
62
63/* CSSM_DATA --> BIGNUM */
64BIGNUM *cssmDataToBn(
65	const CSSM_DATA &cdata)
66{
67	BIGNUM *bn = BN_new();
68	BIGNUM *rtn;
69
70	rtn = BN_bin2bn(cdata.Data, (int)cdata.Length, bn);
71	if(rtn == NULL) {
72		BN_free(bn);
73		CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
74	}
75	return bn;
76}
77
78/* BIGNUM --> CSSM_DATA, mallocing from a SecNssCoder's PL_ArenaPool */
79void bnToCssmData(
80	const BIGNUM *bn,
81	CSSM_DATA &cdata,
82	SecNssCoder &coder)
83{
84	assert(bn != NULL);
85	unsigned numBytes = BN_num_bytes(bn);
86	cdata.Data = (uint8 *)coder.malloc(numBytes);
87	if(cdata.Data == NULL) {
88		CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
89	}
90	cdata.Length = numBytes;
91	BN_bn2bin(bn, cdata.Data);
92}
93
94/*
95 * CSSM_DATA --> unsigned int
96 */
97unsigned cssmDataToInt(
98	const CSSM_DATA &cdata)
99{
100	if((cdata.Length == 0) || (cdata.Data == NULL)) {
101		return 0;
102	}
103	unsigned len = (unsigned)cdata.Length;
104	if(len > sizeof(int)) {
105		logAsnErr("cssmDataToInt: Length error (%u)", len);
106		CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
107	}
108
109	unsigned rtn = 0;
110	uint8 *cp = cdata.Data;
111	for(unsigned i=0; i<len; i++) {
112		rtn = (rtn << 8) | *cp++;
113	}
114	return rtn;
115}
116
117/*
118 * unsigned int --> CSSM_DATA, mallocing from an SecNssCoder
119 */
120void intToCssmData(
121	unsigned num,
122	CSSM_DATA &cdata,
123	SecNssCoder &coder)
124{
125	unsigned len = 0;
126
127	if(num < 0x100) {
128		len = 1;
129	}
130	else if(num < 0x10000) {
131		len = 2;
132	}
133	else if(num < 0x1000000) {
134		len = 3;
135	}
136	else {
137		len = 4;
138	}
139	cdata.Data = (uint8 *)coder.malloc(len);
140	cdata.Length = len;
141	uint8 *cp = &cdata.Data[len - 1];
142	for(unsigned i=0; i<len; i++) {
143		*cp-- = num & 0xff;
144		num >>= 8;
145	}
146}
147
148/*
149 * Set up a encoded NULL for AlgorithmIdentifier.parameters,
150 * required for RSA
151 */
152static void nullAlgParams(
153	CSSM_X509_ALGORITHM_IDENTIFIER	&algId)
154{
155	static const uint8 encNull[2] = { SEC_ASN1_NULL, 0 };
156	CSSM_DATA encNullData;
157	encNullData.Data = (uint8 *)encNull;
158	encNullData.Length = 2;
159
160	algId.parameters = encNullData;
161}
162
163#pragma mark -
164#pragma mark *** RSA key encode/decode ***
165
166/*
167 * DER encode/decode RSA keys in various formats.
168 *
169 * Public key, CSSM_KEYBLOB_RAW_FORMAT_PKCS1
170 *   -- compatible with BSAFE
171 *   -- used for CSSM_KEYBLOB_RAW_FORMAT_DIGEST on both keys
172 */
173static CSSM_RETURN RSAPublicKeyDecodePKCS1(
174	SecNssCoder 	&coder,
175	RSA 			*openKey,
176	void 			*p,
177	size_t			length)
178{
179	NSS_RSAPublicKeyPKCS1 nssPubKey;
180
181	memset(&nssPubKey, 0, sizeof(nssPubKey));
182	PRErrorCode perr = coder.decode(p, length,
183		kSecAsn1RSAPublicKeyPKCS1Template, &nssPubKey);
184	if(perr) {
185		logAsnErr("decode(RSAPublicKeyPKCS1)", perr);
186		return CSSMERR_CSP_INVALID_KEY;
187	}
188
189	try {
190		openKey->n = cssmDataToBn(nssPubKey.modulus);
191		openKey->e = cssmDataToBn(nssPubKey.publicExponent);
192	}
193	catch(...) {
194		return CSSMERR_CSP_MEMORY_ERROR;
195	}
196	return 0;
197}
198
199static CSSM_RETURN RSAPublicKeyEncodePKCS1(
200	SecNssCoder 	&coder,
201	RSA 			*openKey,
202	CssmOwnedData	&encodedKey)
203{
204	/* convert to NSS_RSAPublicKeyPKCS1 */
205	NSS_RSAPublicKeyPKCS1 nssPubKey;
206
207	try {
208		bnToCssmData(openKey->n, nssPubKey.modulus, coder);
209		bnToCssmData(openKey->e, nssPubKey.publicExponent, coder);
210	}
211	catch(...) {
212		return CSSMERR_CSP_MEMORY_ERROR;
213	}
214
215	PRErrorCode prtn;
216	prtn = SecNssEncodeItemOdata(&nssPubKey,
217		kSecAsn1RSAPublicKeyPKCS1Template, encodedKey);
218	if(prtn) {
219		return CSSMERR_CSP_MEMORY_ERROR;
220	}
221	return CSSM_OK;
222}
223
224/*
225 * SubjectPublicKeyInfo, as used by openssl.
226 * The subjectPublicKey component is a PKCS1-style RSAPublicKey.
227 */
228static CSSM_RETURN RSAPublicKeyDecodeX509(
229	SecNssCoder 	&coder,
230	RSA 			*openKey,
231	void 			*p,
232	CSSM_SIZE		length,
233	/* mallocd/returned encoded alg params for OAEP key */
234	uint8			**algParams,
235	CSSM_SIZE		*algParamLen)
236{
237	CSSM_X509_SUBJECT_PUBLIC_KEY_INFO nssPubKeyInfo;
238	PRErrorCode perr;
239
240	memset(&nssPubKeyInfo, 0, sizeof(nssPubKeyInfo));
241	perr = coder.decode(p, length, kSecAsn1SubjectPublicKeyInfoTemplate,
242		&nssPubKeyInfo);
243	if(perr) {
244		logAsnErr("decode(RSA SubjectPublicKeyInfo)", perr);
245		return CSSMERR_CSP_INVALID_KEY;
246	}
247
248	/* verify alg identifier */
249	const CSSM_OID *oid = &nssPubKeyInfo.algorithm.algorithm;
250	if(!cspCompareCssmData(oid, &CSSMOID_RSA)) {
251		if(!cspCompareCssmData(oid, &CSSMOID_RSAWithOAEP)) {
252			sslAsn1Debug("RSAPublicKeyDecodeX509: bad OID");
253			return CSSMERR_CSP_INVALID_KEY;
254		}
255		if(nssPubKeyInfo.algorithm.parameters.Data != NULL) {
256			CSSM_SIZE len = nssPubKeyInfo.algorithm.parameters.Length;
257			*algParams = (uint8 *)malloc(len);
258			memmove(*algParams, nssPubKeyInfo.algorithm.parameters.Data, len);
259			*algParamLen = len;
260		}
261	}
262
263	/* decode the raw bits */
264	CSSM_DATA *pubKey = &nssPubKeyInfo.subjectPublicKey;
265	/* decoded length was in bits */
266	pubKey->Length = (pubKey->Length + 7) / 8;
267	return RSAPublicKeyDecodePKCS1(coder, openKey, pubKey->Data,
268		pubKey->Length);
269}
270
271static CSSM_RETURN RSAPublicKeyEncodeX509(
272	SecNssCoder 	&coder,
273	RSA 			*openKey,
274	CssmOwnedData	&encodedKey,
275	/* encoded alg params for OAEP key */
276	uint8			*algParams,
277	uint32			algParamsLen)
278{
279	CssmAutoData aData(Allocator::standard());
280	CSSM_RETURN crtn;
281
282	/* First get an encoded PKCS1-style RSAPublicKey */
283	crtn = RSAPublicKeyEncodePKCS1(coder, openKey, aData);
284	if(crtn) {
285		return crtn;
286	}
287
288	/*
289	 * That's the AsnBits subjectPublicKey component of a
290	 * SubjectPublicKeyInfo
291	 */
292	CSSM_X509_SUBJECT_PUBLIC_KEY_INFO nssPubKeyInfo;
293	memset(&nssPubKeyInfo, 0, sizeof(nssPubKeyInfo));
294	nssPubKeyInfo.subjectPublicKey.Data = (uint8 *)aData.data();
295	nssPubKeyInfo.subjectPublicKey.Length = aData.length() * 8;
296
297	CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssPubKeyInfo.algorithm;
298	algId.algorithm = CSSMOID_RSA;
299
300	if(algParams) {
301		algId.parameters.Data = (uint8 *)algParams;
302		algId.parameters.Length = algParamsLen;
303	}
304	else {
305		/* NULL algorithm parameters */
306		nullAlgParams(algId);
307	}
308
309	/* DER encode */
310	PRErrorCode perr;
311	perr = SecNssEncodeItemOdata(&nssPubKeyInfo,
312		kSecAsn1SubjectPublicKeyInfoTemplate, encodedKey);
313
314	if(perr) {
315		logAsnErr("encode(RSA SubjectPublicKeyInfo)", perr);
316		return CSSMERR_CSP_MEMORY_ERROR;
317	}
318	return CSSM_OK;
319}
320
321/*
322 * RSA private key, PKCS1 format, used by openssl.
323 */
324static CSSM_RETURN RSAPrivateKeyDecodePKCS1(
325	SecNssCoder 	&coder,
326	RSA 			*openKey,
327	void 			*p,
328	size_t			length)
329{
330	NSS_RSAPrivateKeyPKCS1 nssPrivKey;
331	PRErrorCode perr;
332
333	memset(&nssPrivKey, 0, sizeof(nssPrivKey));
334	perr = coder.decode(p, length, kSecAsn1RSAPrivateKeyPKCS1Template, &nssPrivKey);
335	if(perr) {
336		logAsnErr("decode(RSAPrivateKeyPKCS)", perr);
337		return CSSMERR_CSP_INVALID_KEY;
338	}
339
340	/* convert nssPrivKey fields to RSA key fields */
341	try {
342		openKey->version = cssmDataToInt(nssPrivKey.version);
343		openKey->n	  = cssmDataToBn(nssPrivKey.modulus);
344		openKey->e	  = cssmDataToBn(nssPrivKey.publicExponent);
345		openKey->d 	  = cssmDataToBn(nssPrivKey.privateExponent);
346		openKey->p 	  = cssmDataToBn(nssPrivKey.prime1);
347		openKey->q 	  = cssmDataToBn(nssPrivKey.prime2);
348		openKey->dmp1 = cssmDataToBn(nssPrivKey.exponent1);
349		openKey->dmq1 = cssmDataToBn(nssPrivKey.exponent2);
350		openKey->iqmp = cssmDataToBn(nssPrivKey.coefficient);
351	}
352	catch(...) {
353		return CSSMERR_CSP_MEMORY_ERROR;
354	}
355	return 0;
356}
357
358static CSSM_RETURN RSAPrivateKeyEncodePKCS1(
359	SecNssCoder 	&coder,
360	RSA 			*openKey,
361	CssmOwnedData	&encodedKey)
362{
363	NSS_RSAPrivateKeyPKCS1 nssPrivKey;
364	PRErrorCode perr;
365
366	/* convert to NSS_RSAPrivateKeyPKCS1 */
367	try {
368		intToCssmData(openKey->version, nssPrivKey.version, coder);
369		bnToCssmData(openKey->n, 	nssPrivKey.modulus, coder);
370		bnToCssmData(openKey->e, 	nssPrivKey.publicExponent, coder);
371		bnToCssmData(openKey->d, 	nssPrivKey.privateExponent, coder);
372		bnToCssmData(openKey->p, 	nssPrivKey.prime1, coder);
373		bnToCssmData(openKey->q, 	nssPrivKey.prime2, coder);
374		bnToCssmData(openKey->dmp1, nssPrivKey.exponent1, coder);
375		bnToCssmData(openKey->dmq1, nssPrivKey.exponent2, coder);
376		bnToCssmData(openKey->iqmp, nssPrivKey.coefficient, coder);
377	}
378	catch(...) {
379		/* ? */
380		return CSSMERR_CSP_MEMORY_ERROR;
381	}
382
383	/* DER encode */
384	perr = SecNssEncodeItemOdata(&nssPrivKey, kSecAsn1RSAPrivateKeyPKCS1Template,
385		encodedKey);
386	if(perr) {
387		logAsnErr("encode(RSAPrivateKeyPKCS1)", perr);
388		return CSSMERR_CSP_MEMORY_ERROR;
389	}
390	return CSSM_OK;
391}
392
393/*
394 * RSA private key, PKCS8, compatible with BSAFE.
395 */
396static CSSM_RETURN RSAPrivateKeyDecodePKCS8(
397	SecNssCoder 	&coder,
398	RSA 			*openKey,
399	void 			*p,
400	CSSM_SIZE		length,
401	/* mallocd/returned encoded alg params for OAEP key */
402	uint8			**algParams,
403	CSSM_SIZE		*algParamLen)
404{
405	NSS_PrivateKeyInfo nssPrivKeyInfo;
406	PRErrorCode perr;
407
408	memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo));
409	perr = coder.decode(p, length, kSecAsn1PrivateKeyInfoTemplate, &nssPrivKeyInfo);
410	if(perr) {
411		logAsnErr("decode(PrivateKeyInfo)", perr);
412		return CSSMERR_CSP_INVALID_KEY;
413	}
414
415	/* verify alg identifier */
416	const CSSM_OID *oid = &nssPrivKeyInfo.algorithm.algorithm;
417	if(!cspCompareCssmData(oid, &CSSMOID_RSA)) {
418		if(!cspCompareCssmData(oid, &CSSMOID_RSAWithOAEP)) {
419			sslAsn1Debug("RSAPrivateKeyDecodePKCS8: bad OID");
420			return CSSMERR_CSP_INVALID_KEY;
421		}
422		if(nssPrivKeyInfo.algorithm.parameters.Data != NULL) {
423			CSSM_SIZE len = nssPrivKeyInfo.algorithm.parameters.Length;
424			*algParams = (uint8 *)malloc(len);
425			memmove(*algParams, nssPrivKeyInfo.algorithm.parameters.Data, len);
426			*algParamLen = len;
427		}
428	}
429
430	/*
431	 * nssPrivKeyInfo.privateKey is an octet string which needs
432	 * subsequent decoding
433	 */
434	CSSM_DATA *privKey = &nssPrivKeyInfo.privateKey;
435	return RSAPrivateKeyDecodePKCS1(coder, openKey,
436		privKey->Data, privKey->Length);
437}
438
439static CSSM_RETURN RSAPrivateKeyEncodePKCS8(
440	SecNssCoder 	&coder,
441	RSA 			*openKey,
442	CssmOwnedData	&encodedKey,
443	/* encoded alg params for OAEP key */
444	uint8			*algParams,
445	uint32			algParamsLen)
446{
447
448	/* First get PKCS1-style encoding */
449	CssmAutoData aData(Allocator::standard());
450	CSSM_RETURN crtn = RSAPrivateKeyEncodePKCS1(coder, openKey, aData);
451	if(crtn) {
452		return crtn;
453	}
454
455	/* that encoding is the privateKey field of a NSS_PrivateKeyInfo */
456	NSS_PrivateKeyInfo nssPrivKeyInfo;
457	memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo));
458	nssPrivKeyInfo.privateKey.Data = (uint8 *)aData.data();
459	nssPrivKeyInfo.privateKey.Length = aData.length();
460
461	CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssPrivKeyInfo.algorithm;
462	algId.algorithm = CSSMOID_RSA;
463
464	if(algParams) {
465		algId.parameters.Data = (uint8 *)algParams;
466		algId.parameters.Length = algParamsLen;
467	}
468	else {
469		/* NULL algorithm parameters */
470		nullAlgParams(algId);
471	}
472
473	/* FIXME : attributes? */
474
475	uint8 vers = 0;
476	nssPrivKeyInfo.version.Data = &vers;
477	nssPrivKeyInfo.version.Length = 1;
478
479	/* DER encode */
480	PRErrorCode perr;
481	perr = SecNssEncodeItemOdata(&nssPrivKeyInfo,
482		kSecAsn1PrivateKeyInfoTemplate, encodedKey);
483
484	if(perr) {
485		logAsnErr("encode(RSA PrivateKeyInfo)", perr);
486		return CSSMERR_CSP_MEMORY_ERROR;
487	}
488	return CSSM_OK;
489}
490
491CSSM_RETURN RSAPublicKeyDecode(
492	RSA 				*openKey,
493	CSSM_KEYBLOB_FORMAT	format,
494	void 				*p,
495	size_t				length)
496{
497	SecNssCoder coder;
498
499	switch(format) {
500		case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
501			return RSAPublicKeyDecodePKCS1(coder, openKey, p, length);
502		case CSSM_KEYBLOB_RAW_FORMAT_X509:
503			return RSAPublicKeyDecodeX509(coder, openKey, p, length, NULL, NULL);
504		case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH:
505			return RSAPublicKeyDecodeOpenSSH1(openKey, p, length);
506		case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2:
507			return RSAPublicKeyDecodeOpenSSH2(openKey, p, length);
508		default:
509			assert(0);
510			return CSSMERR_CSP_INTERNAL_ERROR;
511	}
512}
513
514CSSM_RETURN	RSAPublicKeyEncode(
515	RSA 				*openKey,
516	CSSM_KEYBLOB_FORMAT	format,
517	const CssmData		&descData,
518	CssmOwnedData		&encodedKey)
519{
520	SecNssCoder coder;
521
522	switch(format) {
523		case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
524			return RSAPublicKeyEncodePKCS1(coder, openKey, encodedKey);
525		case CSSM_KEYBLOB_RAW_FORMAT_X509:
526			return RSAPublicKeyEncodeX509(coder, openKey, encodedKey, NULL, 0);
527		case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH:
528			return RSAPublicKeyEncodeOpenSSH1(openKey, descData, encodedKey);
529		case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2:
530			return RSAPublicKeyEncodeOpenSSH2(openKey, descData, encodedKey);
531		default:
532			assert(0);
533			return CSSMERR_CSP_INTERNAL_ERROR;
534	}
535}
536
537CSSM_RETURN RSAPrivateKeyDecode(
538	RSA 				*openKey,
539	CSSM_KEYBLOB_FORMAT	format,
540	void 				*p,
541	size_t				length)
542{
543	SecNssCoder coder;
544
545	switch(format) {
546		case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
547			return RSAPrivateKeyDecodePKCS1(coder, openKey, p, length);
548		case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
549			return RSAPrivateKeyDecodePKCS8(coder, openKey, p, length, NULL, NULL);
550		case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH:
551			return RSAPrivateKeyDecodeOpenSSH1(openKey, p, length);
552		default:
553			assert(0);
554			return CSSMERR_CSP_INTERNAL_ERROR;
555	}
556}
557
558CSSM_RETURN	RSAPrivateKeyEncode(
559	RSA 				*openKey,
560	CSSM_KEYBLOB_FORMAT	format,
561	const CssmData		&descData,
562	CssmOwnedData		&encodedKey)
563{
564	SecNssCoder coder;
565
566	switch(format) {
567		case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
568			return RSAPrivateKeyEncodePKCS1(coder, openKey, encodedKey);
569		case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
570			return RSAPrivateKeyEncodePKCS8(coder, openKey, encodedKey, NULL, 0);
571		case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH:
572			return RSAPrivateKeyEncodeOpenSSH1(openKey, descData, encodedKey);
573		default:
574			assert(0);
575			return CSSMERR_CSP_INTERNAL_ERROR;
576	}
577}
578
579CSSM_RETURN	RSAOAEPPrivateKeyEncode(
580	RSA 				*openKey,
581	const CSSM_DATA		*label,
582	CssmOwnedData		&encodedKey)
583{
584	SecNssCoder coder;
585	CSSM_DATA encodedParams = {0, NULL};
586	/* TBD encode the label into a RSAES-OAEP-params */
587
588	return RSAPrivateKeyEncodePKCS8(coder, openKey, encodedKey, encodedParams.Data, (unsigned int)encodedParams.Length);
589}
590
591CSSM_RETURN	RSAOAEPPublicKeyEncode(
592	RSA 				*openKey,
593	const CSSM_DATA		*label,
594	CssmOwnedData		&encodedKey)
595{
596	SecNssCoder coder;
597	CSSM_DATA encodedParams = {0, NULL};
598	/* TBD encode the label into a RSAES-OAEP-params */
599
600	return RSAPublicKeyEncodeX509(coder, openKey, encodedKey, encodedParams.Data, (unsigned int)encodedParams.Length);
601}
602
603CSSM_RETURN RSAOAEPPublicKeyDecode(
604	RSA 				*openKey,
605	void 				*p,
606	size_t				length,
607	/* mallocd and returned label */
608	CSSM_DATA			*label)
609{
610	SecNssCoder coder;
611	CSSM_RETURN crtn;
612	CSSM_DATA encodedParams = {0, NULL};
613
614	crtn = RSAPublicKeyDecodeX509(coder, openKey, p, length, &encodedParams.Data,
615		&encodedParams.Length);
616	if(crtn) {
617		return crtn;
618	}
619
620	/* TBD - decode label from encoded alg params */
621	label->Data = NULL;
622	label->Length = 0;
623	return CSSM_OK;
624}
625
626CSSM_RETURN RSAOAEPPrivateKeyDecode(
627	RSA 				*openKey,
628	void 				*p,
629	size_t				length,
630	/* mallocd and returned label */
631	CSSM_DATA			*label)
632{
633	SecNssCoder coder;
634	CSSM_RETURN crtn;
635	CSSM_DATA encodedParams = {0, NULL};
636
637	crtn = RSAPrivateKeyDecodePKCS8(coder, openKey, p, length, &encodedParams.Data,
638		&encodedParams.Length);
639	if(crtn) {
640		return crtn;
641	}
642
643	/* TBD - decode label from encoded alg params */
644	label->Data = NULL;
645	label->Length = 0;
646	return CSSM_OK;
647}
648
649#pragma mark -
650#pragma mark *** DSA key encode/decode ***
651
652/***
653 *** DSA
654 ***/
655
656/* NSS_DSAAlgorithmIdBSAFE <--> DSA->{p,g,q} */
657static void dsaToNssAlgIdBSAFE(
658	const DSA *openKey,
659	NSS_DSAAlgorithmIdBSAFE &algId,
660	SecNssCoder &coder)
661{
662	/* non-standard, BSAFE-specific OID */
663	algId.algorithm = CSSMOID_DSA;	// not mallocd
664	unsigned numBits = BN_num_bits(openKey->p);
665	intToCssmData(numBits, algId.params.keySizeInBits, coder);
666	bnToCssmData(openKey->p, algId.params.p, coder);
667	bnToCssmData(openKey->q, algId.params.q, coder);
668	bnToCssmData(openKey->g, algId.params.g, coder);
669}
670
671static CSSM_RETURN nssAlgIdToDsaBSAFE(
672	NSS_DSAAlgorithmIdBSAFE &algId,
673	DSA *openKey)
674{
675	/* non-standard, BSAFE-specific OID */
676	if(!cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA)) {
677		sslAsn1Debug("nssAlgIdToDsaBSAFE: bad OID");
678		return CSSMERR_CSP_INVALID_KEY;
679	}
680	openKey->p = cssmDataToBn(algId.params.p);
681	openKey->q = cssmDataToBn(algId.params.q);
682	openKey->g = cssmDataToBn(algId.params.g);
683	return CSSM_OK;
684}
685
686/* NSS_DSAAlgorithmIdX509 <--> DSA->{p,g,q} */
687static void dsaToNssAlgIdX509(
688	const DSA *openKey,
689	NSS_DSAAlgorithmIdX509 &algId,
690	SecNssCoder &coder)
691{
692	algId.algorithm = CSSMOID_DSA_CMS;	// not mallocd
693	bnToCssmData(openKey->p, algId.params->p, coder);
694	bnToCssmData(openKey->q, algId.params->q, coder);
695	bnToCssmData(openKey->g, algId.params->g, coder);
696}
697
698static CSSM_RETURN nssAlgIdToDsaX509(
699	NSS_DSAAlgorithmIdX509 &algId,
700	DSA *openKey)
701{
702	if(!cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA_CMS) &&
703	   !cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA_JDK)) {
704		sslAsn1Debug("nssAlgIdToDsaX509: bad OID");
705		return CSSMERR_CSP_INVALID_KEY;
706	}
707	/* these might be absent per CMS */
708	if(algId.params == NULL) {
709		return CSSM_OK;
710	}
711	openKey->p = cssmDataToBn(algId.params->p);
712	openKey->q = cssmDataToBn(algId.params->q);
713	openKey->g = cssmDataToBn(algId.params->g);
714	return CSSM_OK;
715}
716
717/*
718 * DSA public keys, FIPS186 format.
719 * Compatible with BSAFE.
720 */
721static
722CSSM_RETURN DSAPublicKeyDecodeFIPS186(
723	SecNssCoder 	&coder,
724	DSA 			*openKey,
725	void 			*p,
726	size_t		length)
727{
728	NSS_DSAPublicKeyBSAFE nssPubKey;
729	PRErrorCode perr;
730	CSSM_RETURN crtn;
731
732	memset(&nssPubKey, 0, sizeof(nssPubKey));
733	perr = coder.decode(p, length, kSecAsn1DSAPublicKeyBSAFETemplate,
734		&nssPubKey);
735	if(perr) {
736		logAsnErr("decode(DSAPublicKeyBSAFE)", perr);
737		return CSSMERR_CSP_INVALID_KEY;
738	}
739
740	/* BSAFE style DSA-specific alg params */
741	NSS_DSAAlgorithmIdBSAFE &algId = nssPubKey.dsaAlg;
742	crtn = nssAlgIdToDsaBSAFE(algId, openKey);
743	if(crtn) {
744		return crtn;
745	}
746
747	/* inside of nssPubKey.publicKey is the DER-encoding of a
748	 * ASN Integer; decoded length was in bits */
749	nssPubKey.publicKey.Length = (nssPubKey.publicKey.Length + 7) / 8;
750	CSSM_DATA pubKeyBytes;
751	perr = coder.decodeItem(nssPubKey.publicKey,
752		kSecAsn1UnsignedIntegerTemplate,
753		&pubKeyBytes);
754	if(perr) {
755		logAsnErr("decode(NSS_DSAPublicKeyBSAFE.publicKey)", perr);
756		return CSSMERR_CSP_INVALID_KEY;
757	}
758	openKey->pub_key = cssmDataToBn(pubKeyBytes);
759
760	if(openKey->pub_key == NULL) {
761		return CSSMERR_CSP_INVALID_KEY;
762	}
763	return 0;
764}
765
766static
767CSSM_RETURN	DSAPublicKeyEncodeFIPS186(
768	SecNssCoder		&coder,
769	DSA 			*openKey,
770	CssmOwnedData	&encodedKey)
771{
772	try {
773		/* convert to NSS_DSAPublicKeyBSAFE */
774		NSS_DSAPublicKeyBSAFE nssPubKey;
775		memset(&nssPubKey, 0, sizeof(nssPubKey));
776		dsaToNssAlgIdBSAFE(openKey, nssPubKey.dsaAlg, coder);
777
778		/*
779		 * publicKey is the DER-encoding of a ASN INTEGER wrapped in
780		 * an AsnBits
781		 */
782		CSSM_DATA pubKeyRaw;
783		PRErrorCode perr;
784		bnToCssmData(openKey->pub_key, pubKeyRaw, coder);
785		perr = coder.encodeItem(&pubKeyRaw,	kSecAsn1UnsignedIntegerTemplate,
786			nssPubKey.publicKey);
787		if(perr) {
788			logAsnErr("encodeItem(DSAPublicKeyBSAFE.publicKey)", perr);
789			return CSSMERR_CSP_MEMORY_ERROR;
790		}
791		nssPubKey.publicKey.Length *= 8;
792
793		/* DER encode */
794		SecNssEncodeItemOdata(&nssPubKey, kSecAsn1DSAPublicKeyBSAFETemplate,
795			encodedKey);
796		return CSSM_OK;
797	}
798	catch(...) {
799		/* ? */
800		return CSSMERR_CSP_MEMORY_ERROR;
801	}
802}
803
804/*
805 * DSA private keys, FIPS186 format.
806 * Compatible with BSAFE.
807 */
808static
809CSSM_RETURN DSAPrivateKeyDecodeFIPS186(
810	SecNssCoder 	&coder,
811	DSA 			*openKey,
812	void 			*p,
813	unsigned		length)
814{
815	NSS_DSAPrivateKeyBSAFE nssPrivKeyInfo;
816	PRErrorCode perr;
817
818	memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo));
819	perr = coder.decode(p, length, kSecAsn1DSAPrivateKeyBSAFETemplate,
820		&nssPrivKeyInfo);
821	if(perr) {
822		logAsnErr("decode(DSA PrivateKeyInfo)", perr);
823		return CSSMERR_CSP_INVALID_KEY;
824	}
825
826	CSSM_RETURN crtn = nssAlgIdToDsaBSAFE(nssPrivKeyInfo.dsaAlg, openKey);
827	if(crtn) {
828		return crtn;
829	}
830
831	/* nssPrivKeyInfo.privateKey is the DER-encoding of a
832	 * DSAPrivateKeyOcts... */
833	 try {
834		PRErrorCode perr;
835		NSS_DSAPrivateKeyOcts keyOcts;
836
837		perr = coder.decodeItem(nssPrivKeyInfo.privateKey,
838			kSecAsn1DSAPrivateKeyOctsTemplate, &keyOcts);
839		if(perr) {
840			logAsnErr("decode(DSA PrivateKeyInfoOcts)", perr);
841			return CSSMERR_CSP_INVALID_KEY;
842		}
843
844		openKey->priv_key = cssmDataToBn(keyOcts.privateKey);
845		if(openKey->priv_key == NULL) {
846			return CSSMERR_CSP_INVALID_KEY;
847		}
848		return 0;
849	}
850	catch(...) {
851		return CSSMERR_CSP_INVALID_KEY;
852	}
853}
854
855static
856CSSM_RETURN	DSAPrivateKeyEncodeFIPS186(
857	SecNssCoder 	&coder,
858	DSA 			*openKey,
859	CssmOwnedData	&encodedKey)
860{
861	try {
862		/* First convert into a NSS_DSAPrivateKeyBSAFE */
863		NSS_DSAPrivateKeyBSAFE nssPrivKey;
864		intToCssmData(openKey->version, nssPrivKey.version, coder);
865		dsaToNssAlgIdBSAFE(openKey, nssPrivKey.dsaAlg, coder);
866
867		/* nssPrivKey.privateKey is the DER-encoding of one of these... */
868		NSS_DSAPrivateKeyOcts privKeyOcts;
869		bnToCssmData(openKey->priv_key, privKeyOcts.privateKey, coder);
870
871		/* DER encode the privateKey portion into arena pool memory
872		 * into NSS_DSAPrivateKeyPKCS8.privateKey */
873		coder.encodeItem(&privKeyOcts, kSecAsn1DSAPrivateKeyOctsTemplate,
874			nssPrivKey.privateKey);
875
876		/* DER encode the whole thing */
877		PRErrorCode perr;
878		perr = SecNssEncodeItemOdata(&nssPrivKey,
879			kSecAsn1DSAPrivateKeyBSAFETemplate, encodedKey);
880		return 0;
881	}
882	catch(...) {
883		/* ? */
884		return CSSMERR_CSP_MEMORY_ERROR;
885	}
886}
887
888/*
889 * DSA private keys, PKCS8/SMIME format.
890 */
891static
892CSSM_RETURN DSAPrivateKeyDecodePKCS8(
893	SecNssCoder 	&coder,
894	DSA 			*openKey,
895	void 			*p,
896	unsigned		length)
897{
898	NSS_DSAPrivateKeyPKCS8 nssPrivKeyInfo;
899	PRErrorCode perr;
900
901	memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo));
902	perr = coder.decode(p, length, kSecAsn1DSAPrivateKeyPKCS8Template,
903		&nssPrivKeyInfo);
904	if(perr) {
905		logAsnErr("decode(DSA NSS_DSAPrivateKeyPKCS8)", perr);
906		return CSSMERR_CSP_INVALID_KEY;
907	}
908
909	CSSM_RETURN crtn = nssAlgIdToDsaX509(nssPrivKeyInfo.dsaAlg, openKey);
910	if(crtn) {
911		return crtn;
912	}
913
914	/*
915	 * Post-decode, nssPrivKeyInfo.privateKey is the DER-encoding of a
916	 * an ASN integer.
917	 */
918	 try {
919		PRErrorCode perr;
920		CSSM_DATA privKeyInt = {0, NULL};
921
922		perr = coder.decodeItem(nssPrivKeyInfo.privateKey,
923			kSecAsn1UnsignedIntegerTemplate, &privKeyInt);
924		if(perr) {
925			logAsnErr("decode(DSA nssPrivKeyInfo.privateKey)", perr);
926			return CSSMERR_CSP_INVALID_KEY;
927		}
928
929		openKey->priv_key = cssmDataToBn(privKeyInt);
930		if(openKey->priv_key == NULL) {
931			return CSSMERR_CSP_INVALID_KEY;
932		}
933		return 0;
934	}
935	catch(...) {
936		return CSSMERR_CSP_INVALID_KEY;
937	}
938}
939
940static
941CSSM_RETURN	DSAPrivateKeyEncodePKCS8(
942	SecNssCoder 	&coder,
943	DSA 			*openKey,
944	CssmOwnedData	&encodedKey)
945{
946	try {
947		/* First convert into a NSS_DSAPrivateKeyPKCS8 */
948		NSS_DSAPrivateKeyPKCS8 nssPrivKey;
949		NSS_DSAAlgParams algParams;
950		memset(&nssPrivKey, 0, sizeof(nssPrivKey));
951		memset(&algParams, 0, sizeof(algParams));
952		nssPrivKey.dsaAlg.params = &algParams;
953		intToCssmData(openKey->version, nssPrivKey.version, coder);
954		dsaToNssAlgIdX509(openKey, nssPrivKey.dsaAlg, coder);
955
956		/* pre-encode, nssPrivKey.privateKey is the DER-encoding of
957		 * an ASN integer... */
958		CSSM_DATA privKeyInt;
959		bnToCssmData(openKey->priv_key, privKeyInt, coder);
960
961		/* DER encode the privateKey portion into arena pool memory
962		 * into NSS_DSAPrivateKeyPKCS8.privateKey */
963		coder.encodeItem(&privKeyInt, kSecAsn1UnsignedIntegerTemplate,
964			nssPrivKey.privateKey);
965
966		/* DER encode the whole thing */
967		PRErrorCode perr;
968		perr = SecNssEncodeItemOdata(&nssPrivKey,
969			kSecAsn1DSAPrivateKeyPKCS8Template, encodedKey);
970		return 0;
971	}
972	catch(...) {
973		/* ? */
974		return CSSMERR_CSP_MEMORY_ERROR;
975	}
976}
977
978/*
979 * DSA public key, X509/openssl format.
980 */
981static CSSM_RETURN DSAPublicKeyDecodeX509(
982	SecNssCoder 	&coder,
983	DSA 			*openKey,
984	void 			*p,
985	size_t			length)
986{
987	NSS_DSAPublicKeyX509 nssPubKey;
988	PRErrorCode perr;
989	CSSM_RETURN crtn;
990
991	memset(&nssPubKey, 0, sizeof(nssPubKey));
992	perr = coder.decode(p, length, kSecAsn1DSAPublicKeyX509Template,
993		&nssPubKey);
994	if(perr) {
995		logAsnErr("decode(DSAPublicKeyX509)", perr);
996		return CSSMERR_CSP_INVALID_KEY;
997	}
998
999	/* X509 style DSA-specific alg params */
1000	NSS_DSAAlgorithmIdX509 &algId = nssPubKey.dsaAlg;
1001	crtn = nssAlgIdToDsaX509(algId, openKey);
1002	if(crtn) {
1003		return crtn;
1004	}
1005
1006	/* inside of nssPubKey.publicKey is the DER-encoding of a
1007	 * ASN Integer; decoded length was in bits */
1008	nssPubKey.publicKey.Length = (nssPubKey.publicKey.Length + 7) / 8;
1009	CSSM_DATA pubKeyBytes = {0, NULL};
1010	perr = coder.decodeItem(nssPubKey.publicKey,
1011		kSecAsn1UnsignedIntegerTemplate,
1012		&pubKeyBytes);
1013	if(perr) {
1014		logAsnErr("decode(NSS_DSAPublicKeyX509.publicKey)", perr);
1015		return CSSMERR_CSP_INVALID_KEY;
1016	}
1017	openKey->pub_key = cssmDataToBn(pubKeyBytes);
1018
1019	if(openKey->pub_key == NULL) {
1020		return CSSMERR_CSP_INVALID_KEY;
1021	}
1022	return 0;
1023}
1024
1025static CSSM_RETURN DSAPublicKeyEncodeX509(
1026	SecNssCoder 	&coder,
1027	DSA 			*openKey,
1028	CssmOwnedData	&encodedKey)
1029{
1030	try {
1031		/* convert to NSS_DSAPublicKeyX509 */
1032		NSS_DSAPublicKeyX509 nssPubKey;
1033		NSS_DSAAlgParams algParams;
1034		memset(&nssPubKey, 0, sizeof(nssPubKey));
1035		memset(&algParams, 0, sizeof(algParams));
1036		nssPubKey.dsaAlg.params = &algParams;
1037		dsaToNssAlgIdX509(openKey, nssPubKey.dsaAlg, coder);
1038
1039		/*
1040		 * publicKey is the DER-encoding of a ASN INTEGER wrapped in
1041		 * an AsnBits
1042		 */
1043		CSSM_DATA pubKeyRaw;
1044		PRErrorCode perr;
1045		bnToCssmData(openKey->pub_key, pubKeyRaw, coder);
1046		perr = coder.encodeItem(&pubKeyRaw,	kSecAsn1UnsignedIntegerTemplate,
1047			nssPubKey.publicKey);
1048		if(perr) {
1049			logAsnErr("encodeItem(DSAPublicKeyX509.publicKey)", perr);
1050			return CSSMERR_CSP_MEMORY_ERROR;
1051		}
1052		nssPubKey.publicKey.Length *= 8;
1053
1054		/* DER encode */
1055		SecNssEncodeItemOdata(&nssPubKey, kSecAsn1DSAPublicKeyX509Template,
1056			encodedKey);
1057		return CSSM_OK;
1058	}
1059	catch(...) {
1060		/* ? */
1061		return CSSMERR_CSP_MEMORY_ERROR;
1062	}
1063}
1064
1065/*
1066 * Encode public key portion only for calculating key digest.
1067 * Note this works just fine on a partial DSA public key, i.e.,
1068 * A DSA public key's digest-capable blob is the same whether or
1069 * not the DSA key has its DSA parameters p, q, and g.
1070 */
1071static CSSM_RETURN DSAPublicKeyEncodeHashable(
1072	SecNssCoder 	&coder,
1073	DSA 			*openKey,
1074	CssmOwnedData	&encodedKey)
1075{
1076	try {
1077		/*
1078		 * publicKey is the DER-encoding of an ASN integer
1079		 */
1080		CSSM_DATA pubKey;
1081		bnToCssmData(openKey->pub_key, pubKey, coder);
1082		PRErrorCode perr;
1083
1084		perr = SecNssEncodeItemOdata(&pubKey, kSecAsn1UnsignedIntegerTemplate,
1085			encodedKey);
1086		if(perr) {
1087			logAsnErr("encode(DSAPubHashable)", perr);
1088			return CSSMERR_CSP_MEMORY_ERROR;
1089		}
1090		return CSSM_OK;
1091	}
1092	catch(...) {
1093		/* ? */
1094		return CSSMERR_CSP_MEMORY_ERROR;
1095	}
1096}
1097
1098/*
1099 * DSA private key, custom openssl format.
1100 */
1101static CSSM_RETURN DSAPrivateKeyDecodeOpenssl(
1102	SecNssCoder 	&coder,
1103	DSA 			*openKey,
1104	void 			*p,
1105	size_t			length)
1106{
1107	NSS_DSAPrivateKeyOpenssl nssPrivKey;
1108	PRErrorCode perr;
1109
1110	memset(&nssPrivKey, 0, sizeof(nssPrivKey));
1111	perr = coder.decode(p, length, kSecAsn1DSAPrivateKeyOpensslTemplate,
1112		&nssPrivKey);
1113	if(perr) {
1114		logAsnErr("decode(DSAPrivateKeyOpenssl)", perr);
1115		return CSSMERR_CSP_INVALID_KEY;
1116	}
1117
1118	/* convert nssPrivKey fields to RSA key fields */
1119	try {
1120		openKey->version = cssmDataToInt(nssPrivKey.version);
1121		openKey->p	 	  = cssmDataToBn(nssPrivKey.p);
1122		openKey->q	 	  = cssmDataToBn(nssPrivKey.q);
1123		openKey->g 	 	  = cssmDataToBn(nssPrivKey.g);
1124		openKey->pub_key  = cssmDataToBn(nssPrivKey.pub);
1125		openKey->priv_key = cssmDataToBn(nssPrivKey.priv);
1126	}
1127	catch(...) {
1128		return CSSMERR_CSP_MEMORY_ERROR;
1129	}
1130	return 0;
1131}
1132
1133static CSSM_RETURN DSAPrivateKeyEncodeOpenssl(
1134	SecNssCoder 	&coder,
1135	DSA 			*openKey,
1136	CssmOwnedData	&encodedKey)
1137{
1138	NSS_DSAPrivateKeyOpenssl nssPrivKey;
1139	PRErrorCode perr;
1140
1141	/* convert to NSS_DSAPrivateKeyOpenssl */
1142	try {
1143		intToCssmData(openKey->version, nssPrivKey.version, coder);
1144		bnToCssmData(openKey->p, 		nssPrivKey.p, coder);
1145		bnToCssmData(openKey->q, 		nssPrivKey.q, coder);
1146		bnToCssmData(openKey->g, 		nssPrivKey.g, coder);
1147		bnToCssmData(openKey->pub_key, 	nssPrivKey.pub, coder);
1148		bnToCssmData(openKey->priv_key,	nssPrivKey.priv, coder);
1149	}
1150	catch(...) {
1151		/* ? */
1152		return CSSMERR_CSP_MEMORY_ERROR;
1153	}
1154
1155	/* DER encode */
1156	perr = SecNssEncodeItemOdata(&nssPrivKey, kSecAsn1DSAPrivateKeyOpensslTemplate,
1157		encodedKey);
1158	if(perr) {
1159		logAsnErr("encode(DSAPrivateKeyOpenssl)", perr);
1160		return CSSMERR_CSP_MEMORY_ERROR;
1161	}
1162	return CSSM_OK;
1163}
1164
1165CSSM_RETURN DSAPublicKeyDecode(
1166	DSA 				*openKey,
1167	CSSM_KEYBLOB_FORMAT	format,
1168	void 				*p,
1169	size_t				length)
1170{
1171	SecNssCoder coder;
1172
1173	switch(format) {
1174		case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
1175			return DSAPublicKeyDecodeFIPS186(coder, openKey, p, length);
1176		case CSSM_KEYBLOB_RAW_FORMAT_X509:
1177			return DSAPublicKeyDecodeX509(coder, openKey, p, length);
1178		case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2:
1179			return DSAPublicKeyDecodeOpenSSH2(openKey, p, length);
1180		default:
1181			assert(0);
1182			return CSSMERR_CSP_INTERNAL_ERROR;
1183	}
1184}
1185
1186CSSM_RETURN	DSAPublicKeyEncode(
1187	DSA 				*openKey,
1188	CSSM_KEYBLOB_FORMAT	format,
1189	const CssmData		&descData,
1190	CssmOwnedData		&encodedKey)
1191{
1192	SecNssCoder coder;
1193
1194	switch(format) {
1195		case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
1196			return DSAPublicKeyEncodeFIPS186(coder, openKey, encodedKey);
1197		case CSSM_KEYBLOB_RAW_FORMAT_X509:
1198			return DSAPublicKeyEncodeX509(coder, openKey, encodedKey);
1199		case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
1200			return DSAPublicKeyEncodeHashable(coder, openKey, encodedKey);
1201		case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2:
1202			return DSAPublicKeyEncodeOpenSSH2(openKey, descData, encodedKey);
1203		default:
1204			assert(0);
1205			return CSSMERR_CSP_INTERNAL_ERROR;
1206	}
1207}
1208
1209CSSM_RETURN DSAPrivateKeyDecode(
1210	DSA 				*openKey,
1211	CSSM_KEYBLOB_FORMAT	format,
1212	void 				*p,
1213	size_t				length)
1214{
1215	SecNssCoder coder;
1216
1217	switch(format) {
1218		case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
1219			return DSAPrivateKeyDecodeFIPS186(coder, openKey, p, (unsigned)length);
1220		case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL:
1221			return DSAPrivateKeyDecodeOpenssl(coder, openKey, p, length);
1222		case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
1223			return DSAPrivateKeyDecodePKCS8(coder, openKey, p, (unsigned)length);
1224		default:
1225			assert(0);
1226			return CSSMERR_CSP_INTERNAL_ERROR;
1227	}
1228}
1229
1230CSSM_RETURN	DSAPrivateKeyEncode(
1231	DSA 				*openKey,
1232	CSSM_KEYBLOB_FORMAT	format,
1233	const CssmData		&descData,
1234	CssmOwnedData		&encodedKey)
1235{
1236	SecNssCoder coder;
1237
1238	switch(format) {
1239		case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
1240			return DSAPrivateKeyEncodeFIPS186(coder, openKey, encodedKey);
1241		case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL:
1242			return DSAPrivateKeyEncodeOpenssl(coder, openKey, encodedKey);
1243		case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
1244			return DSAPrivateKeyEncodePKCS8(coder, openKey, encodedKey);
1245		default:
1246			assert(0);
1247			return CSSMERR_CSP_INTERNAL_ERROR;
1248	}
1249}
1250
1251#pragma mark -
1252#pragma mark *** DSA Signature encode/decode ***
1253
1254CSSM_RETURN DSASigEncode(
1255	DSA_SIG			*openSig,
1256	CssmOwnedData	&encodedSig)
1257{
1258	/* temp allocs from this pool */
1259	SecNssCoder coder;
1260	/* convert to NSS_DSASignature */
1261	NSS_DSASignature nssSig;
1262
1263	try {
1264		bnToCssmData(openSig->r, nssSig.r, coder);
1265		bnToCssmData(openSig->s, nssSig.s, coder);
1266	}
1267	catch(...) {
1268		/* ? */
1269		return CSSMERR_CSP_MEMORY_ERROR;
1270	}
1271
1272	PRErrorCode prtn = SecNssEncodeItemOdata(&nssSig,
1273		kSecAsn1DSASignatureTemplate, encodedSig);
1274	if(prtn) {
1275		return CSSMERR_CSP_MEMORY_ERROR;
1276	}
1277	return CSSM_OK;
1278}
1279
1280CSSM_RETURN DSASigDecode(
1281	DSA_SIG 		*openSig,
1282	const void 		*p,
1283	unsigned		length)
1284{
1285	NSS_DSASignature nssSig;
1286	SecNssCoder coder;
1287
1288	memset(&nssSig, 0, sizeof(nssSig));
1289	PRErrorCode perr = coder.decode(p, length,
1290		kSecAsn1DSASignatureTemplate, &nssSig);
1291	if(perr) {
1292		logAsnErr("decode(DSASigDecode)", perr);
1293		return CSSMERR_CSP_INVALID_SIGNATURE;
1294	}
1295
1296	try {
1297		openSig->r = cssmDataToBn(nssSig.r);
1298		openSig->s = cssmDataToBn(nssSig.s);
1299	}
1300	catch(...) {
1301		return CSSMERR_CSP_MEMORY_ERROR;
1302	}
1303	return 0;
1304}
1305
1306#pragma mark -
1307#pragma mark *** DSA Algorithm Parameters encode/decode ***
1308
1309CSSM_RETURN DSAEncodeAlgParams(
1310	NSS_DSAAlgParams	&algParams,
1311	CssmOwnedData		&encodedParams)
1312{
1313	PRErrorCode prtn = SecNssEncodeItemOdata(&algParams,
1314		kSecAsn1DSAAlgParamsTemplate, encodedParams);
1315	if(prtn) {
1316		return CSSMERR_CSP_MEMORY_ERROR;
1317	}
1318	return CSSM_OK;
1319}
1320
1321CSSM_RETURN DSADecodeAlgParams(
1322	NSS_DSAAlgParams	&algParams,
1323	const void			*p,
1324	unsigned			len,
1325	SecNssCoder 		&coder)
1326{
1327
1328	memset(&algParams, 0, sizeof(algParams));
1329	PRErrorCode perr = coder.decode(p, len,
1330		kSecAsn1DSAAlgParamsTemplate, &algParams);
1331	if(perr) {
1332		logAsnErr("decode(DSAAlgParams)", perr);
1333		return CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS;
1334	}
1335	return CSSM_OK;
1336}
1337
1338#pragma mark -
1339#pragma mark *** Diffie-Hellman key encode/decode ***
1340static
1341CSSM_RETURN DHPrivateKeyDecodePKCS3(
1342	SecNssCoder		&coder,
1343	DH	 			*openKey,
1344	unsigned char 	*p,
1345	unsigned 		length)
1346{
1347	NSS_DHPrivateKey nssPrivKey;
1348	PRErrorCode perr;
1349
1350	memset(&nssPrivKey, 0, sizeof(nssPrivKey));
1351	perr = coder.decode(p, length, kSecAsn1DHPrivateKeyTemplate, &nssPrivKey);
1352	if(perr) {
1353		logAsnErr("decode(DHPrivateKey)", perr);
1354		return CSSMERR_CSP_INVALID_KEY;
1355	}
1356
1357	/* verify alg identifier */
1358	const CSSM_OID *oid = &nssPrivKey.dhOid;
1359	if(!cspCompareCssmData(oid, &CSSMOID_DH)) {
1360		sslAsn1Debug("DHPrivateKeyDecode: bad OID");
1361		return CSSMERR_CSP_ALGID_MISMATCH;
1362	}
1363
1364	NSS_DHParameter	&params = nssPrivKey.params;
1365
1366	try {
1367		openKey->priv_key = cssmDataToBn(nssPrivKey.secretPart);
1368		openKey->p	      = cssmDataToBn(params.prime);
1369		openKey->g 	      = cssmDataToBn(params.base);
1370		/* TBD - ignore privateValueLength for now */
1371	}
1372	catch(...) {
1373		/* FIXME - bad sig? memory? */
1374		return CSSMERR_CSP_MEMORY_ERROR;
1375	}
1376	return 0;
1377}
1378
1379static
1380CSSM_RETURN	DHPrivateKeyEncodePKCS3(
1381	SecNssCoder		&coder,
1382	DH	 			*openKey,
1383	CssmOwnedData	&encodedKey)
1384{
1385	/* convert into a NSS_DHPrivateKey */
1386	NSS_DHPrivateKey nssPrivKey;
1387	NSS_DHParameter &params = nssPrivKey.params;
1388	memset(&nssPrivKey, 0, sizeof(nssPrivKey));
1389	nssPrivKey.dhOid = CSSMOID_DH;
1390
1391
1392	try {
1393		bnToCssmData(openKey->priv_key, nssPrivKey.secretPart, coder);
1394		bnToCssmData(openKey->p, params.prime, coder);
1395		bnToCssmData(openKey->g, params.base, coder);
1396		if(openKey->length) {
1397			/* actually currently not supported in openssl... */
1398			intToCssmData(openKey->length, params.privateValueLength, coder);
1399		}
1400	}
1401	catch(...) {
1402		return CSSMERR_CSP_MEMORY_ERROR;
1403	}
1404
1405	/* DER encode */
1406	PRErrorCode perr;
1407	perr = SecNssEncodeItemOdata(&nssPrivKey, kSecAsn1DHPrivateKeyTemplate,
1408		encodedKey);
1409	if(perr) {
1410		logAsnErr("encode(DHPrivateKey)", perr);
1411		return CSSMERR_CSP_MEMORY_ERROR;
1412	}
1413	return CSSM_OK;
1414}
1415
1416/*
1417 * NSS_DHAlgorithmIdentifierX942 <--> DH
1418 * NOTE this is incomplete. It's functional on decode, but we throw
1419 * away everything except p and g. On encode, we put zeroes in
1420 * all the fields we don't deal with. Thus the encode side will NOT be
1421 * interoperable with other implementations.
1422 */
1423static void dhToNssAlgIdX942(
1424	const DH *openKey,
1425	NSS_DHAlgorithmIdentifierX942 &algId,
1426	SecNssCoder &coder)
1427{
1428	/*
1429	 * When trying to encode a public key in X509 form, we may in
1430	 * fact have nothing here - public keys created and exported in
1431	 * PKCS3 have the pub_key value, and that's it.
1432	 */
1433
1434	memset(&algId, 0, sizeof(algId));
1435	algId.oid = CSSMOID_ANSI_DH_PUB_NUMBER;	// not mallocd
1436	NSS_DHDomainParamsX942 &params = algId.params;
1437	uint8 zero = 0;
1438	CSSM_DATA czero = {1, &zero};
1439	if(openKey->p != NULL) {
1440		bnToCssmData(openKey->p, params.p, coder);
1441	}
1442	else {
1443		coder.allocCopyItem(czero, params.p);
1444	}
1445	if(openKey->g != NULL) {
1446		bnToCssmData(openKey->g, params.g, coder);
1447	}
1448	else {
1449		coder.allocCopyItem(czero, params.g);
1450	}
1451	/* and we never have a vali0d q */
1452	coder.allocCopyItem(czero, params.q);
1453
1454}
1455
1456static CSSM_RETURN nssAlgIdToDhX942(
1457	NSS_DHAlgorithmIdentifierX942 &algId,
1458	DH *openKey)
1459{
1460	if(!cspCompareCssmData(&algId.oid, &CSSMOID_ANSI_DH_PUB_NUMBER)) {
1461		sslAsn1Debug("nssAlgIdToDhX942: bad OID");
1462		return CSSMERR_CSP_INVALID_KEY;
1463	}
1464	openKey->p = cssmDataToBn(algId.params.p);
1465	openKey->g = cssmDataToBn(algId.params.g);
1466	return CSSM_OK;
1467}
1468
1469static
1470CSSM_RETURN DHPrivateKeyDecodePKCS8(
1471	SecNssCoder		&coder,
1472	DH	 			*openKey,
1473	unsigned char 	*p,
1474	unsigned 		length)
1475{
1476	NSS_DHPrivateKeyPKCS8 nssPrivKey;
1477	PRErrorCode perr;
1478
1479	memset(&nssPrivKey, 0, sizeof(nssPrivKey));
1480	perr = coder.decode(p, length, kSecAsn1DHPrivateKeyPKCS8Template,
1481		&nssPrivKey);
1482	if(perr) {
1483		logAsnErr("decode(DHPrivateKeyPKCS8)", perr);
1484		return CSSMERR_CSP_INVALID_KEY;
1485	}
1486
1487	try {
1488		CSSM_RETURN crtn = nssAlgIdToDhX942(nssPrivKey.algorithm, openKey);
1489		if(crtn) {
1490			return crtn;
1491		}
1492
1493		/* post-decode private key is a DER encoded integer */
1494		CSSM_DATA privKeyInt = {0, NULL};
1495		if(coder.decodeItem(nssPrivKey.privateKey,
1496				kSecAsn1UnsignedIntegerTemplate,
1497				&privKeyInt)) {
1498			logAsnErr("decode(DHPrivateKeyPKCS8 privKey int)", perr);
1499			return CSSMERR_CSP_INVALID_KEY;
1500		}
1501
1502		openKey->priv_key = cssmDataToBn(privKeyInt);
1503	}
1504	catch(...) {
1505		/* FIXME - bad sig? memory? */
1506		return CSSMERR_CSP_MEMORY_ERROR;
1507	}
1508	return 0;
1509}
1510
1511static
1512CSSM_RETURN	DHPrivateKeyEncodePKCS8(
1513	SecNssCoder		&coder,
1514	DH	 			*openKey,
1515	CssmOwnedData	&encodedKey)
1516{
1517	/* convert into a NSS_DHPrivateKeyPKCS8 */
1518	NSS_DHPrivateKeyPKCS8 nssPrivKey;
1519	memset(&nssPrivKey, 0, sizeof(nssPrivKey));
1520	uint8 vers = 0;
1521	nssPrivKey.version.Length = 1;
1522	nssPrivKey.version.Data = &vers;
1523	NSS_DHAlgorithmIdentifierX942 &alg = nssPrivKey.algorithm;
1524
1525	try {
1526
1527		dhToNssAlgIdX942(openKey, alg, coder);
1528		/* pre-encode, nssPrivKey.privateKey is the DER-encoding of
1529		 * an ASN integer... */
1530		CSSM_DATA privKeyInt;
1531		bnToCssmData(openKey->priv_key, privKeyInt, coder);
1532
1533		/* DER encode the privateKey portion into arena pool memory
1534		 * into nssPrivKey.privateKey */
1535		coder.encodeItem(&privKeyInt, kSecAsn1UnsignedIntegerTemplate,
1536			nssPrivKey.privateKey);
1537	}
1538	catch(...) {
1539		return CSSMERR_CSP_MEMORY_ERROR;
1540	}
1541
1542	/* DER encode */
1543	PRErrorCode perr;
1544	perr = SecNssEncodeItemOdata(&nssPrivKey, kSecAsn1DHPrivateKeyPKCS8Template,
1545		encodedKey);
1546	if(perr) {
1547		logAsnErr("encode(DHPrivateKey)", perr);
1548		return CSSMERR_CSP_MEMORY_ERROR;
1549	}
1550	return CSSM_OK;
1551}
1552
1553/*
1554 * In the PKCS3 form, the public blob is simply the literal
1555 * public key value, not DER encoded.
1556 */
1557static CSSM_RETURN DHPublicKeyDecodePKCS3(
1558	DH	 			*openKey,
1559	SecNssCoder		&coder,
1560	unsigned char 	*p,
1561	unsigned 		length)
1562{
1563	try {
1564		CSSM_DATA pubKey = {(uint32)length, (uint8 *)p};
1565		openKey->pub_key = cssmDataToBn(pubKey);
1566		return CSSM_OK;
1567	}
1568	catch(...) {
1569		return CSSMERR_CSP_MEMORY_ERROR;
1570	}
1571}
1572
1573static CSSM_RETURN DHPublicKeyEncodePKCS3(
1574	DH	 			*openKey,
1575	SecNssCoder		&coder,
1576	CssmOwnedData	&encodedKey)
1577{
1578	try {
1579		CSSM_DATA pubKey;
1580		bnToCssmData(openKey->pub_key, pubKey, coder);
1581		encodedKey.copy(CssmData::overlay(pubKey));
1582		return CSSM_OK;
1583	}
1584	catch(...) {
1585		return CSSMERR_CSP_MEMORY_ERROR;
1586	}
1587}
1588
1589static CSSM_RETURN DHPublicKeyDecodeX509(
1590	DH	 			*openKey,
1591	SecNssCoder		&coder,
1592	unsigned char 	*p,
1593	unsigned 		length)
1594{
1595	NSS_DHPublicKeyX509 nssPubKey;
1596	PRErrorCode perr;
1597
1598	memset(&nssPubKey, 0, sizeof(nssPubKey));
1599	perr = coder.decode(p, length, kSecAsn1DHPublicKeyX509Template,
1600		&nssPubKey);
1601	if(perr) {
1602		logAsnErr("decode(DHPublicKeyX509)", perr);
1603		return CSSMERR_CSP_INVALID_KEY;
1604	}
1605
1606	try {
1607		CSSM_RETURN crtn = nssAlgIdToDhX942(nssPubKey.algorithm, openKey);
1608		if(crtn) {
1609			return crtn;
1610		}
1611
1612		/*
1613		 * Post-decode public key length in bits
1614		 * Contents are pub_key as DER-encoded INTEGER
1615		 */
1616		CSSM_DATA &pubKey = nssPubKey.publicKey;
1617		pubKey.Length = (pubKey.Length + 7) / 8;
1618		CSSM_DATA pubKeyInt = {0, NULL};
1619		if(coder.decodeItem(pubKey,
1620				kSecAsn1UnsignedIntegerTemplate, &pubKeyInt)) {
1621			logAsnErr("decode(DHPublicKeyX509 pub key int)", perr);
1622			return CSSMERR_CSP_INVALID_KEY;
1623		}
1624		openKey->pub_key = cssmDataToBn(pubKeyInt);
1625	}
1626	catch(...) {
1627		/* FIXME - bad sig? memory? */
1628		return CSSMERR_CSP_MEMORY_ERROR;
1629	}
1630	return 0;
1631}
1632
1633static CSSM_RETURN DHPublicKeyEncodeX509(
1634	DH	 			*openKey,
1635	SecNssCoder		&coder,
1636	CssmOwnedData	&encodedKey)
1637{
1638	/* convert into a NSS_DHPublicKeyX509 */
1639	NSS_DHPublicKeyX509 nssPubKey;
1640	memset(&nssPubKey, 0, sizeof(nssPubKey));
1641	NSS_DHAlgorithmIdentifierX942 &alg = nssPubKey.algorithm;
1642
1643	try {
1644		dhToNssAlgIdX942(openKey, alg, coder);
1645
1646		/* encode pub_key as integer */
1647		CSSM_DATA pubKeyInt = {0, NULL};
1648		bnToCssmData(openKey->pub_key, pubKeyInt, coder);
1649		coder.encodeItem(&pubKeyInt, kSecAsn1UnsignedIntegerTemplate,
1650			nssPubKey.publicKey);
1651		/* specify length in bits */
1652		nssPubKey.publicKey.Length *= 8;
1653	}
1654	catch(...) {
1655		return CSSMERR_CSP_MEMORY_ERROR;
1656	}
1657
1658	/* DER encode */
1659	PRErrorCode perr;
1660	perr = SecNssEncodeItemOdata(&nssPubKey, kSecAsn1DHPublicKeyX509Template,
1661		encodedKey);
1662	if(perr) {
1663		logAsnErr("encode(DHPublicKeyX509)", perr);
1664		return CSSMERR_CSP_MEMORY_ERROR;
1665	}
1666	return CSSM_OK;
1667}
1668
1669CSSM_RETURN DHPrivateKeyDecode(
1670	DH	 				*openKey,
1671	CSSM_KEYBLOB_FORMAT	format,
1672	unsigned char 		*p,
1673	unsigned 			length)
1674{
1675	SecNssCoder coder;
1676
1677	switch(format) {
1678		case CSSM_KEYBLOB_RAW_FORMAT_PKCS3:
1679			return DHPrivateKeyDecodePKCS3(coder, openKey, p, length);
1680		case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
1681			return DHPrivateKeyDecodePKCS8(coder, openKey, p, length);
1682		default:
1683			assert(0);
1684			return CSSMERR_CSP_INTERNAL_ERROR;
1685	}
1686}
1687
1688CSSM_RETURN	DHPrivateKeyEncode(
1689	DH	 				*openKey,
1690	CSSM_KEYBLOB_FORMAT	format,
1691	CssmOwnedData		&encodedKey)
1692{
1693	SecNssCoder coder;
1694
1695	switch(format) {
1696		case CSSM_KEYBLOB_RAW_FORMAT_PKCS3:
1697			return DHPrivateKeyEncodePKCS3(coder, openKey, encodedKey);
1698		case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
1699			return DHPrivateKeyEncodePKCS8(coder, openKey, encodedKey);
1700		default:
1701			assert(0);
1702			return CSSMERR_CSP_INTERNAL_ERROR;
1703	}
1704}
1705
1706CSSM_RETURN DHPublicKeyDecode(
1707	DH	 				*openKey,
1708	CSSM_KEYBLOB_FORMAT	format,
1709	unsigned char 		*p,
1710	unsigned 			length)
1711{
1712	SecNssCoder coder;
1713
1714	switch(format) {
1715		case CSSM_KEYBLOB_RAW_FORMAT_PKCS3:
1716			return DHPublicKeyDecodePKCS3(openKey, coder, p, length);
1717		case CSSM_KEYBLOB_RAW_FORMAT_X509:
1718			return DHPublicKeyDecodeX509(openKey, coder, p, length);
1719		default:
1720			assert(0);
1721			return CSSMERR_CSP_INTERNAL_ERROR;
1722	}
1723}
1724
1725CSSM_RETURN	DHPublicKeyEncode(
1726	DH	 				*openKey,
1727	CSSM_KEYBLOB_FORMAT	format,
1728	CssmOwnedData		&encodedKey)
1729{
1730	SecNssCoder coder;
1731
1732	switch(format) {
1733		case CSSM_KEYBLOB_RAW_FORMAT_PKCS3:
1734			return DHPublicKeyEncodePKCS3(openKey, coder, encodedKey);
1735		case CSSM_KEYBLOB_RAW_FORMAT_X509:
1736			return DHPublicKeyEncodeX509(openKey, coder, encodedKey);
1737		default:
1738			assert(0);
1739			return CSSMERR_CSP_INTERNAL_ERROR;
1740	}
1741}
1742
1743/*
1744 * Encode/decode a NSS_DHParameterBlock.
1745 */
1746CSSM_RETURN DHParamBlockDecode(
1747	const CSSM_DATA &encParam,
1748	NSS_DHParameterBlock &paramBlock,
1749	SecNssCoder &coder)
1750{
1751	PRErrorCode perr;
1752
1753	memset(&paramBlock, 0, sizeof(paramBlock));
1754	perr = coder.decodeItem(encParam, kSecAsn1DHParameterBlockTemplate,
1755		&paramBlock);
1756	if(perr == 0) {
1757		return CSSM_OK;
1758	}
1759
1760	/*
1761	 * CDSA Extension: the CDSA Algorithm Guide says that the D-H
1762	 * parameter block is supposed to be wrapped with its accompanying
1763	 * OID. However Openssl does not do this; it just exports
1764	 * an encoded DHParameter rather than a DHParameterBlock.
1765	 * For compatibility we'll try decoding the parameters as one
1766	 * of these.
1767	 */
1768	memset(&paramBlock, 0, sizeof(paramBlock));
1769	perr = coder.decodeItem(encParam, kSecAsn1DHParameterTemplate,
1770		&paramBlock.params);
1771	if(perr == 0) {
1772		return CSSM_OK;
1773	}
1774	return CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS;
1775}
1776
1777#pragma mark -
1778#pragma mark *** Message Digest ***
1779
1780/*
1781 * Given a message digest and associated algorithm, cook up a PKCS1-style
1782 * DigestInfo and return its DER encoding. This is a necessary step for
1783 * RSA signature (both generating and verifying) - the output of this
1784 * routine is what gets encrypted during signing, and what is expected when
1785 * verifying (i.e., decrypting the signature).
1786 *
1787 * A good guess for the length of the output digestInfo is the size of the
1788 * key being used to sign/verify. The digest can never be larger than that.
1789 */
1790CSSM_RETURN generateDigestInfo(
1791	const void		*msgDigest,
1792	size_t			digestLen,
1793	CSSM_ALGORITHMS	digestAlg,		// CSSM_ALGID_SHA1, etc.
1794	CssmOwnedData	&encodedInfo,
1795	size_t			maxEncodedSize)
1796{
1797	if(digestAlg == CSSM_ALGID_NONE) {
1798		/* special case, no encode, just copy */
1799		encodedInfo.copy(msgDigest, digestLen);
1800		return 0;
1801	}
1802
1803	NSS_DigestInfo	digestInfo;
1804	CSSM_X509_ALGORITHM_IDENTIFIER &algId = digestInfo.digestAlgorithm;
1805
1806	memset(&digestInfo, 0, sizeof(digestInfo));
1807	switch(digestAlg) {
1808		case CSSM_ALGID_MD5:
1809			algId.algorithm = CSSMOID_MD5;
1810			break;
1811		case CSSM_ALGID_MD2:
1812			algId.algorithm = CSSMOID_MD2;
1813			break;
1814		case CSSM_ALGID_SHA1:
1815			algId.algorithm = CSSMOID_SHA1;
1816			break;
1817		case CSSM_ALGID_SHA224:
1818			algId.algorithm = CSSMOID_SHA224;
1819			break;
1820		case CSSM_ALGID_SHA256:
1821			algId.algorithm = CSSMOID_SHA256;
1822			break;
1823		case CSSM_ALGID_SHA384:
1824			algId.algorithm = CSSMOID_SHA384;
1825			break;
1826		case CSSM_ALGID_SHA512:
1827			algId.algorithm = CSSMOID_SHA512;
1828			break;
1829		default:
1830			return CSSMERR_CSP_INVALID_ALGORITHM;
1831	}
1832	nullAlgParams(algId);
1833	digestInfo.digest.Data = (uint8 *)msgDigest;
1834	digestInfo.digest.Length = digestLen;
1835
1836	/* DER encode */
1837	PRErrorCode perr;
1838	perr = SecNssEncodeItemOdata(&digestInfo, kSecAsn1DigestInfoTemplate,
1839		encodedInfo);
1840	if(perr) {
1841		logAsnErr("encode(digestInfo)", perr);
1842		return CSSMERR_CSP_MEMORY_ERROR;
1843	}
1844	return CSSM_OK;
1845}
1846
1847