]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp
Security-59306.120.7.tar.gz
[apple/security.git] / OSX / libsecurity_apple_csp / open_ssl / opensslUtils / opensslAsn1.cpp
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/opensslerr.h>
28 #include <openssl/bn_legacy.h>
29 #include <openssl/crypto_legacy.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...) secinfo("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
53 static 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 */
64 BIGNUM *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 */
79 void 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 */
97 unsigned 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 */
120 void 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 */
152 static 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 */
173 static 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
199 static 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 */
228 static 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
271 static 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 */
324 static 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
358 static 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 */
396 static 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
439 static 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
491 CSSM_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
514 CSSM_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
537 CSSM_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
558 CSSM_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
579 CSSM_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
591 CSSM_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
603 CSSM_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
626 CSSM_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} */
657 static 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
671 static 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} */
687 static 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
698 static 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 */
721 static
722 CSSM_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
766 static
767 CSSM_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 */
808 static
809 CSSM_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
855 static
856 CSSM_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 */
891 static
892 CSSM_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
940 static
941 CSSM_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 */
981 static 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
1025 static 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 */
1071 static 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 */
1101 static 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
1133 static 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
1165 CSSM_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
1186 CSSM_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
1209 CSSM_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
1230 CSSM_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
1254 CSSM_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
1280 CSSM_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
1309 CSSM_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
1321 CSSM_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 ***
1340 static
1341 CSSM_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
1379 static
1380 CSSM_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 */
1423 static 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
1456 static 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
1469 static
1470 CSSM_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
1511 static
1512 CSSM_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 */
1557 static 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
1573 static 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
1589 static 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
1633 static 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
1669 CSSM_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
1688 CSSM_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
1706 CSSM_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
1725 CSSM_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 */
1746 CSSM_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 */
1790 CSSM_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