]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_apple_x509_cl/lib/clNssUtils.cpp
Security-58286.1.32.tar.gz
[apple/security.git] / OSX / libsecurity_apple_x509_cl / lib / clNssUtils.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 * clNssUtils.cpp - support for libnssasn1-based ASN1 encode/decode
20 */
21
22 #include "clNssUtils.h"
23 #include "clNameUtils.h"
24 #include "CSPAttacher.h"
25 #include <security_asn1/secasn1.h>
26 #include <security_asn1/SecNssCoder.h>
27 #include <security_asn1/nssUtils.h>
28 #include <Security/keyTemplates.h>
29 #include <Security/certExtensionTemplates.h>
30 #include <Security/oidsalg.h>
31 #include <Security/oidsattr.h>
32 #include <Security/cssmapple.h>
33 #include <string.h>
34
35 #pragma mark ----- ArenaAllocator -----
36
37 /*
38 * Avoid inlining this for debuggability
39 */
40 void *ArenaAllocator::malloc(size_t len) throw(std::bad_alloc)
41 {
42 try {
43 return mCoder.malloc(len);
44 }
45 catch (...) {
46 throw std::bad_alloc();
47 }
48 }
49
50 /* intentionally not implemented, should never be called */
51 void ArenaAllocator::free(void *p) throw()
52 {
53 throw std::bad_alloc();
54 }
55
56 void *ArenaAllocator::realloc(void *p, size_t len) throw(std::bad_alloc)
57 {
58 throw std::bad_alloc();
59 }
60
61 #pragma mark ----- Malloc/Copy/Compare CSSM_DATA -----
62
63 /*
64 * Misc. alloc/copy with arbitrary Allocator
65 */
66 /* malloc d.Data, set d.Length */
67 void clAllocData(
68 Allocator &alloc,
69 CSSM_DATA &dst,
70 size_t len)
71 {
72 if(len == 0) {
73 dst.Data = NULL;
74 }
75 else {
76 dst.Data = (uint8 *)alloc.malloc(len);
77 }
78 dst.Length = len;
79 }
80
81 /* malloc and copy */
82 void clAllocCopyData(
83 Allocator &alloc,
84 const CSSM_DATA &src,
85 CSSM_DATA &dst)
86 {
87 clAllocData(alloc, dst, src.Length);
88 if(dst.Length != 0) {
89 memmove(dst.Data, src.Data, src.Length);
90 }
91 }
92
93 /*
94 * Compare two CSSM_DATAs (or two CSSM_OIDs), return true if identical.
95 */
96 bool clCompareCssmData(
97 const CSSM_DATA *data1,
98 const CSSM_DATA *data2)
99 {
100 if((data1 == NULL) || (data1->Data == NULL) ||
101 (data2 == NULL) || (data2->Data == NULL) ||
102 (data1->Length != data2->Length)) {
103 return false;
104 }
105 if(data1->Length != data2->Length) {
106 return false;
107 }
108 if(memcmp(data1->Data, data2->Data, data1->Length) == 0) {
109 return true;
110 }
111 else {
112 return false;
113 }
114 }
115
116 #pragma mark ----- CSSM_DATA <--> uint32 -----
117
118 uint32 clDataToInt(
119 const CSSM_DATA &cdata,
120 CSSM_RETURN toThrow) /* = CSSMERR_CL_INVALID_CERT_POINTER */
121 {
122 if((cdata.Length == 0) || (cdata.Data == NULL)) {
123 return 0;
124 }
125 size_t len = cdata.Length;
126 if(len > sizeof(uint32)) {
127 if(toThrow == 0) {
128 /* tolerate this */
129 len = sizeof(uint32);
130 }
131 else {
132 CssmError::throwMe(toThrow);
133 }
134 }
135
136 uint32 rtn = 0;
137 uint8 *cp = cdata.Data;
138 for(size_t i=0; i<len; i++) {
139 rtn = (rtn << 8) | *cp++;
140 }
141 return rtn;
142 }
143
144 void clIntToData(
145 uint32 num,
146 CSSM_DATA &cdata,
147 Allocator &alloc)
148 {
149 uint32 len = 0;
150
151 if(num < 0x100) {
152 len = 1;
153 }
154 else if(num < 0x10000) {
155 len = 2;
156 }
157 else if(num < 0x1000000) {
158 len = 3;
159 }
160 else {
161 len = 4;
162 }
163 clAllocData(alloc, cdata, len);
164 uint8 *cp = &cdata.Data[len - 1];
165 for(unsigned i=0; i<len; i++) {
166 *cp-- = num & 0xff;
167 num >>= 8;
168 }
169 }
170
171 #pragma mark ----- CSSM_BOOL <--> CSSM_DATA -----
172 /*
173 * A Bool is encoded as one byte of either 0 or 0xff
174 * Default of NSS boolean not present is false
175 */
176 CSSM_BOOL clNssBoolToCssm(
177 const CSSM_DATA &nssBool)
178 {
179 if((nssBool.Data != NULL) && (nssBool.Data[0] == 0xff)) {
180 return CSSM_TRUE;
181 }
182 else {
183 return CSSM_FALSE;
184 }
185 }
186
187 void clCssmBoolToNss(
188 CSSM_BOOL cBool,
189 CSSM_DATA &nssBool,
190 Allocator &alloc)
191 {
192 uint32 num = cBool ? 0xff : 0;
193 clIntToData(num, nssBool, alloc);
194 }
195
196 #pragma mark ----- Bit String manipulation -----
197
198 /*
199 * Adjust the length of a CSSM_DATA representing a pre-encoded
200 * bit string. On entry the length field is the number of bytes
201 * of data; en exit, the number if bits. Trailing zero bits
202 * are counted as unused (which is how KeyUsage and NetscapeCertType
203 * extensions are encoded).
204 */
205 void clCssmBitStringToNss(
206 CSSM_DATA &b)
207 {
208 size_t numBits = b.Length * 8;
209
210 /* start at end of bit array, scanning backwards looking
211 * for the first set bit */
212 bool foundSet = false;
213 for(ptrdiff_t dex=b.Length-1; dex>=0; dex--) {
214 unsigned bitMask = 0x01;
215 uint8 byte = b.Data[dex];
216 for(unsigned bdex=0; bdex<8; bdex++) {
217 if(byte & bitMask) {
218 foundSet = true;
219 break;
220 }
221 else {
222 bitMask <<= 1;
223 numBits--;
224 }
225 }
226 if(foundSet) {
227 break;
228 }
229 }
230 /* !foundSet --> numBits = 0 */
231 assert(((numBits > 0) & foundSet) || ((numBits == 0) && !foundSet));
232 b.Length = numBits;
233 }
234
235 /*
236 * On entry, Length is bit count; on exit, a byte count.
237 * The job here is to ensure that bits marked as "unused" in the
238 * BER encoding are cleared. Encoding rules say they are undefined in
239 * the actual encoding.
240 */
241 void clNssBitStringToCssm(
242 CSSM_DATA &b)
243 {
244 CSSM_SIZE byteCount = (b.Length + 7) / 8;
245 unsigned partialBits = b.Length & 0x7;
246 b.Length = byteCount;
247 if(partialBits == 0) {
248 return;
249 }
250
251 /* mask off unused bits */
252 unsigned unusedBits = 8 - partialBits;
253 uint8 *bp = b.Data + b.Length - 1;
254 /* mask = (2 ** unusedBits) - 1 */
255 unsigned mask = (1 << unusedBits) - 1;
256 *bp &= ~mask;
257 }
258
259 #pragma mark ----- NSS array manipulation -----
260 /*
261 * How many items in a NULL-terminated array of pointers?
262 */
263 unsigned clNssArraySize(
264 const void **array)
265 {
266 unsigned count = 0;
267 if (array) {
268 while (*array++) {
269 count++;
270 }
271 }
272 return count;
273 }
274
275 /* malloc a NULL-ed array of pointers of size num+1 */
276 void **clNssNullArray(
277 uint32 num,
278 SecNssCoder &coder)
279 {
280 unsigned len = (num + 1) * sizeof(void *);
281 void **p = (void **)coder.malloc(len);
282 memset(p, 0, len);
283 return p;
284 }
285
286 /*
287 * GIven a CSSM_DATA containing a decoded BIT_STRING,
288 * convert to a KeyUsage.
289 */
290 CE_KeyUsage clBitStringToKeyUsage(
291 const CSSM_DATA &cdata)
292 {
293 size_t toCopy = (cdata.Length + 7) / 8;
294 if(toCopy > 2) {
295 /* I hope I never see this... */
296 clErrorLog("clBitStringToKeyUsage: KeyUsage larger than 2 bytes!");
297 toCopy = 2;
298 }
299 unsigned char bits[2] = {0, 0};
300 memmove(bits, cdata.Data, toCopy);
301 CE_KeyUsage usage = (((unsigned)bits[0]) << 8) | bits[1];
302 return usage;
303 }
304
305 CSSM_ALGORITHMS CL_oidToAlg(
306 const CSSM_OID &oid)
307 {
308 CSSM_ALGORITHMS alg;
309 bool found = cssmOidToAlg(&oid, &alg);
310 if(!found) {
311 clErrorLog("CL_oidToAlg: unknown alg\n");
312 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
313 }
314 return alg;
315 }
316
317 #pragma mark ----- copy CSSM_X509_ALGORITHM_IDENTIFIER -----
318
319 /*
320 * Copy CSSM_X509_ALGORITHM_IDENTIFIER, same format (NSS and CSSM).
321 */
322 void CL_copyAlgId(
323 const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId,
324 CSSM_X509_ALGORITHM_IDENTIFIER &dstAlgId,
325 Allocator &alloc)
326 {
327 clAllocCopyData(alloc, srcAlgId.algorithm, dstAlgId.algorithm);
328 clAllocCopyData(alloc, srcAlgId.parameters, dstAlgId.parameters);
329 }
330
331 void CL_freeCssmAlgId(
332 CSSM_X509_ALGORITHM_IDENTIFIER *cdsaObj, // optional
333 Allocator &alloc)
334 {
335 if(cdsaObj == NULL) {
336 return;
337 }
338 alloc.free(cdsaObj->algorithm.Data);
339 alloc.free(cdsaObj->parameters.Data);
340 memset(cdsaObj, 0, sizeof(CSSM_X509_ALGORITHM_IDENTIFIER));
341 }
342
343
344 #pragma mark ----- CSSM_X509_TIME <--> NSS format -----
345
346 /*
347 * Map the tag associated with a choice of DirectoryString elements to
348 * a template array for encoding/decoding that string type.
349 * Contrary to RFC2459, we allow the IA5String type, which is actually
350 * used in the real world (cf. the email address in Thawte's serverbasic
351 * cert).
352 */
353
354 /* The template chooser does the work here */
355
356 bool CL_nssTimeToCssm(
357 const NSS_TaggedItem &nssTime,
358 CSSM_X509_TIME &cssmObj,
359 Allocator &alloc)
360 {
361 cssmObj.timeType = nssTime.tag;
362 clAllocCopyData(alloc, nssTime.item, cssmObj.time);
363 return true;
364 }
365
366 /*
367 * CSSM time to NSS time.
368 */
369 void CL_cssmTimeToNss(
370 const CSSM_X509_TIME &cssmTime,
371 NSS_TaggedItem &nssTime,
372 SecNssCoder &coder)
373 {
374 nssTime.tag = cssmTime.timeType;
375 coder.allocCopyItem(cssmTime.time, nssTime.item);
376 }
377
378 void CL_freeCssmTime(
379 CSSM_X509_TIME *cssmTime,
380 Allocator &alloc)
381 {
382 if(cssmTime == NULL) {
383 return;
384 }
385 if(cssmTime->time.Data) {
386 alloc.free(cssmTime->time.Data);
387 }
388 memset(cssmTime, 0, sizeof(CSSM_X509_TIME));
389 }
390
391
392 #pragma mark ----- CSSM_X509_SUBJECT_PUBLIC_KEY_INFO <--> CSSM_KEY -----
393
394 /*
395 * Copy a CSSM_X509_SUBJECT_PUBLIC_KEY_INFO.
396 *
397 * Same format (NSS and CSSM), EXCEPT:
398 *
399 * Objects which have just been NSS decoded or are about to be
400 * NSS encoded have the subjectPublicKey.Length field in BITS
401 * since this field is wrapped in a BIT STRING upon encoding.
402 *
403 * Caller tells us which format (bits or bytes)
404 * to use for each of {src, dst}.
405 */
406 void CL_copySubjPubKeyInfo(
407 const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &srcInfo,
408 bool srcInBits,
409 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &dstInfo,
410 bool dstInBits,
411 Allocator &alloc)
412 {
413 CL_copyAlgId(srcInfo.algorithm, dstInfo.algorithm, alloc);
414
415 CSSM_DATA srcKey = srcInfo.subjectPublicKey;
416 if(srcInBits) {
417 srcKey.Length = (srcKey.Length + 7) / 8;
418 }
419 clAllocCopyData(alloc, srcKey, dstInfo.subjectPublicKey);
420 if(dstInBits) {
421 dstInfo.subjectPublicKey.Length *= 8;
422 }
423 }
424
425 /*
426 * Obtain a CSSM_KEY from a CSSM_X509_SUBJECT_PUBLIC_KEY_INFO,
427 * inferring as much as we can from required fields
428 * (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO) and extensions (for
429 * KeyUse, obtained from the optional DecodedCert).
430 */
431 CSSM_KEY_PTR CL_extractCSSMKeyNSS(
432 const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &keyInfo,
433 Allocator &alloc,
434 const DecodedCert *decodedCert) // optional
435 {
436 CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR) alloc.malloc(sizeof(CSSM_KEY));
437 memset(cssmKey, 0, sizeof(CSSM_KEY));
438 CSSM_KEYHEADER &hdr = cssmKey->KeyHeader;
439 CssmRemoteData keyData(alloc, cssmKey->KeyData);
440
441 hdr.HeaderVersion = CSSM_KEYHEADER_VERSION;
442 /* CspId blank */
443 hdr.BlobType = CSSM_KEYBLOB_RAW;
444 hdr.AlgorithmId = CL_oidToAlg(keyInfo.algorithm.algorithm);
445 hdr.KeyAttr = CSSM_KEYATTR_MODIFIABLE | CSSM_KEYATTR_EXTRACTABLE;
446
447 /*
448 * Format inferred from AlgorithmId. I have never seen these defined
449 * anywhere, e.g., what's the format of an RSA public key in a cert?
450 * X509 certainly doesn't say. However. the following two cases are
451 * known to be correct.
452 */
453 switch(hdr.AlgorithmId) {
454 case CSSM_ALGID_RSA:
455 hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
456 break;
457 case CSSM_ALGID_DSA:
458 case CSSM_ALGID_ECDSA:
459 case CSSM_ALGID_DH:
460 case CSSM_ALGMODE_PKCS1_EME_OAEP:
461 hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_X509;
462 break;
463 case CSSM_ALGID_FEE:
464 /* CSSM_KEYBLOB_RAW_FORMAT_NONE --> DER encoded */
465 hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE;
466 break;
467 default:
468 /* punt */
469 hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE;
470 }
471 hdr.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
472
473 /* KeyUsage inferred from extensions */
474 if(decodedCert) {
475 hdr.KeyUsage = decodedCert->inferKeyUsage();
476 }
477 else {
478 hdr.KeyUsage = CSSM_KEYUSE_ANY;
479 }
480
481 /* start/end date unknown, leave zero */
482 hdr.WrapAlgorithmId = CSSM_ALGID_NONE;
483 hdr.WrapMode = CSSM_ALGMODE_NONE;
484
485 switch(hdr.AlgorithmId) {
486 case CSSM_ALGID_DSA:
487 case CSSM_ALGID_ECDSA:
488 case CSSM_ALGID_DH:
489 case CSSM_ALGMODE_PKCS1_EME_OAEP:
490 {
491 /*
492 * Just encode the whole subject public key info blob.
493 * NOTE we're assuming that the keyInfo.subjectPublicKey
494 * field is in the NSS_native BITSTRING format, i.e.,
495 * its Length field is in bits and we don't have to adjust.
496 */
497 PRErrorCode prtn = SecNssEncodeItemOdata(&keyInfo,
498 kSecAsn1SubjectPublicKeyInfoTemplate, keyData);
499 if(prtn) {
500 clErrorLog("extractCSSMKey: error on reencode\n");
501 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
502 }
503 break;
504 }
505 default:
506 /*
507 * RSA, FEE for now.
508 * keyInfo.subjectPublicKey (in BITS) ==> KeyData
509 */
510 keyData.copy(keyInfo.subjectPublicKey.Data,
511 (keyInfo.subjectPublicKey.Length + 7) / 8);
512 }
513
514 /*
515 * LogicalKeySizeInBits - ask the CSP
516 */
517 CSSM_CSP_HANDLE cspHand = getGlobalCspHand(true);
518 CSSM_KEY_SIZE keySize;
519 CSSM_RETURN crtn;
520 crtn = CSSM_QueryKeySizeInBits(cspHand, CSSM_INVALID_HANDLE, cssmKey,
521 &keySize);
522 switch(crtn) {
523 default:
524 CssmError::throwMe(crtn);
525 case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE:
526 /*
527 * This is how the CSP indicates a "partial" public key,
528 * with a valid public key value but no alg-specific
529 * parameters (currently, DSA only).
530 */
531 hdr.KeyAttr |= CSSM_KEYATTR_PARTIAL;
532 /* and drop thru */
533 case CSSM_OK:
534 cssmKey->KeyHeader.LogicalKeySizeInBits =
535 keySize.LogicalKeySizeInBits;
536 break;
537 }
538
539 keyData.release();
540 return cssmKey;
541 }
542
543 /*
544 * Set up a encoded NULL for CSSM_X509_ALGORITHM_IDENTIFIER.parameters.
545 */
546 void CL_nullAlgParams(
547 CSSM_X509_ALGORITHM_IDENTIFIER &algId)
548 {
549 static const uint8 encNull[2] = { SEC_ASN1_NULL, 0 };
550 CSSM_DATA encNullData;
551 encNullData.Data = (uint8 *)encNull;
552 encNullData.Length = 2;
553
554 algId.parameters = encNullData;
555 }
556
557 /*
558 * Convert a CSSM_KEY to a CSSM_X509_SUBJECT_PUBLIC_KEY_INFO. The
559 * CSSM key must be in raw format and with a specific blob format.
560 * -- RSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_PKCS1
561 * -- DSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_X509
562 * -- ECDSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_X509
563 */
564 void CL_CSSMKeyToSubjPubKeyInfoNSS(
565 const CSSM_KEY &cssmKey,
566 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &nssKeyInfo,
567 SecNssCoder &coder)
568 {
569 const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader;
570 if(hdr.BlobType != CSSM_KEYBLOB_RAW) {
571 clErrorLog("CL SetField: must specify RAW key blob\n");
572 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
573 }
574 memset(&nssKeyInfo, 0, sizeof(nssKeyInfo));
575
576 /* algorithm and format dependent from here... */
577 switch(hdr.AlgorithmId) {
578 case CSSM_ALGID_RSA:
579 if(hdr.Format != CSSM_KEYBLOB_RAW_FORMAT_PKCS1) {
580 clErrorLog("CL SetField: RSA key must be in PKCS1 format\n");
581 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
582 }
583 /* and fall thru */
584 default:
585 {
586 /* Key header's algorithm --> OID */
587 const CSSM_OID *oid = cssmAlgToOid(hdr.AlgorithmId);
588 if(oid == NULL) {
589 clErrorLog("CL SetField: Unknown key algorithm\n");
590 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
591 }
592 CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssKeyInfo.algorithm;
593 coder.allocCopyItem(*oid, algId.algorithm);
594
595 /* NULL algorithm parameters, always in this case */
596 CL_nullAlgParams(algId);
597
598 /* Copy key bits, destination is a BIT STRING */
599 coder.allocCopyItem(cssmKey.KeyData, nssKeyInfo.subjectPublicKey);
600 nssKeyInfo.subjectPublicKey.Length *= 8;
601 break;
602 }
603 case CSSM_ALGID_DSA:
604 case CSSM_ALGID_ECDSA:
605 if(hdr.Format != CSSM_KEYBLOB_RAW_FORMAT_X509) {
606 clErrorLog("CL SetField: DSA/ECDSA key must be in X509 format\n");
607 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
608 }
609
610 /*
611 * All we do is decode the whole key blob into the
612 * SubjectPublicKeyInfo.
613 */
614 if(coder.decodeItem(cssmKey.KeyData,
615 kSecAsn1SubjectPublicKeyInfoTemplate,
616 &nssKeyInfo)) {
617 clErrorLog("CL SetField: Error decoding DSA public key\n");
618 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
619 }
620 break;
621 }
622 }
623
624 void CL_freeCSSMKey(
625 CSSM_KEY_PTR cssmKey,
626 Allocator &alloc,
627 bool freeTop)
628 {
629 if(cssmKey == NULL) {
630 return;
631 }
632 alloc.free(cssmKey->KeyData.Data);
633 memset(cssmKey, 0, sizeof(CSSM_KEY));
634 if(freeTop) {
635 alloc.free(cssmKey);
636 }
637 }
638
639 #pragma mark ----- CE_AuthorityKeyID <--> NSS_AuthorityKeyId -----
640
641 void CL_cssmAuthorityKeyIdToNss(
642 const CE_AuthorityKeyID &cdsaObj,
643 NSS_AuthorityKeyId &nssObj,
644 SecNssCoder &coder)
645 {
646 memset(&nssObj, 0, sizeof(nssObj));
647 if(cdsaObj.keyIdentifierPresent) {
648 nssObj.keyIdentifier = (CSSM_DATA_PTR)coder.malloc(sizeof(CSSM_DATA));
649 coder.allocCopyItem(cdsaObj.keyIdentifier, *nssObj.keyIdentifier);
650 }
651 if(cdsaObj.generalNamesPresent ) {
652 /* GeneralNames, the hard one */
653 CL_cssmGeneralNamesToNss(*cdsaObj.generalNames,
654 nssObj.genNames, coder);
655 }
656 if(cdsaObj.serialNumberPresent) {
657 coder.allocCopyItem(cdsaObj.serialNumber,nssObj.serialNumber);
658 }
659 }
660
661 void CL_nssAuthorityKeyIdToCssm(
662 const NSS_AuthorityKeyId &nssObj,
663 CE_AuthorityKeyID &cdsaObj,
664 SecNssCoder &coder, // for temp decoding
665 Allocator &alloc)
666 {
667 if(nssObj.keyIdentifier != NULL) {
668 cdsaObj.keyIdentifierPresent = CSSM_TRUE;
669 clAllocCopyData(alloc, *nssObj.keyIdentifier, cdsaObj.keyIdentifier);
670 }
671 if(nssObj.genNames.names != NULL) {
672 /* GeneralNames, the hard one */
673 cdsaObj.generalNamesPresent = CSSM_TRUE;
674 cdsaObj.generalNames =
675 (CE_GeneralNames *)alloc.malloc(sizeof(CE_GeneralNames));
676 CL_nssGeneralNamesToCssm(nssObj.genNames,
677 *cdsaObj.generalNames,
678 coder,
679 alloc);
680 }
681 if(nssObj.serialNumber.Data != NULL) {
682 cdsaObj.serialNumberPresent = CSSM_TRUE;
683 clAllocCopyData(alloc, nssObj.serialNumber, cdsaObj.serialNumber);
684 }
685 }
686
687 #pragma mark ----- CE_AuthorityInfoAccess <--> NSS_AuthorityInfoAccess -----
688
689 void CL_cssmInfoAccessToNss(
690 const CE_AuthorityInfoAccess &cdsaObj,
691 NSS_AuthorityInfoAccess &nssObj,
692 SecNssCoder &coder)
693 {
694 memset(&nssObj, 0, sizeof(nssObj));
695 uint32 numDescs = cdsaObj.numAccessDescriptions;
696 nssObj.accessDescriptions = (NSS_AccessDescription **)clNssNullArray(numDescs, coder);
697
698 for(unsigned dex=0; dex<numDescs; dex++) {
699 nssObj.accessDescriptions[dex] = coder.mallocn<NSS_AccessDescription>();
700 CE_AccessDescription *src = &cdsaObj.accessDescriptions[dex];
701 NSS_AccessDescription *dst = nssObj.accessDescriptions[dex];
702 coder.allocCopyItem(src->accessMethod, dst->accessMethod);
703
704 /* Convert general name, then encode it into destination */
705 NSS_GeneralName nssGenName;
706 CL_cssmGeneralNameToNss(src->accessLocation, nssGenName, coder);
707 PRErrorCode prtn = coder.encodeItem(&nssGenName, kSecAsn1GeneralNameTemplate,
708 dst->encodedAccessLocation);
709 if(prtn) {
710 clErrorLog("CL_cssmInfoAccessToNss: encode error\n");
711 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
712 }
713 }
714 }
715
716 void CL_infoAccessToCssm(
717 const NSS_AuthorityInfoAccess &nssObj,
718 CE_AuthorityInfoAccess &cdsaObj,
719 SecNssCoder &coder, // for temp decoding
720 Allocator &alloc)
721 {
722 memset(&cdsaObj, 0, sizeof(cdsaObj));
723 unsigned numDescs = clNssArraySize((const void **)nssObj.accessDescriptions);
724 if(numDescs == 0) {
725 return;
726 }
727 cdsaObj.accessDescriptions = (CE_AccessDescription *)alloc.malloc(
728 numDescs * sizeof(CE_AccessDescription));
729 cdsaObj.numAccessDescriptions = numDescs;
730 for(unsigned dex=0; dex<numDescs; dex++) {
731 CE_AccessDescription *dst = &cdsaObj.accessDescriptions[dex];
732 NSS_AccessDescription *src = nssObj.accessDescriptions[dex];
733 clAllocCopyData(alloc, src->accessMethod, dst->accessMethod);
734
735 /* decode the general name */
736 NSS_GeneralName nssGenName;
737 memset(&nssGenName, 0, sizeof(nssGenName));
738 PRErrorCode prtn = coder.decodeItem(src->encodedAccessLocation,
739 kSecAsn1GeneralNameTemplate, &nssGenName);
740 if(prtn) {
741 clErrorLog("***Error decoding NSS_AuthorityInfoAccess.accessLocation\n");
742 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
743 }
744
745 /* then convert the result to CSSM */
746 CL_nssGeneralNameToCssm(nssGenName, dst->accessLocation, coder, alloc);
747 }
748 }
749
750 void CL_freeInfoAccess(
751 CE_AuthorityInfoAccess &cssmInfo,
752 Allocator &alloc)
753 {
754 uint32 numDescs = cssmInfo.numAccessDescriptions;
755 for(unsigned dex=0; dex<numDescs; dex++) {
756 CE_AccessDescription *dst = &cssmInfo.accessDescriptions[dex];
757 alloc.free(dst->accessMethod.Data);
758 CL_freeCssmGeneralName(dst->accessLocation, alloc);
759 }
760 alloc.free(cssmInfo.accessDescriptions);
761 }
762
763
764 #pragma mark ----- CE_QC_Statements <--> NSS_QC_Statements -----
765
766 void CL_cssmQualCertStatementsToNss(
767 const CE_QC_Statements &cdsaObj,
768 NSS_QC_Statements &nssObj,
769 SecNssCoder &coder)
770 {
771 memset(&nssObj, 0, sizeof(nssObj));
772 uint32 numQcs = cdsaObj.numQCStatements;
773 nssObj.qcStatements =
774 (NSS_QC_Statement **)clNssNullArray(numQcs, coder);
775 for(uint32 dex=0; dex<numQcs; dex++) {
776 nssObj.qcStatements[dex] = (NSS_QC_Statement *)
777 coder.malloc(sizeof(NSS_QC_Statement));
778 NSS_QC_Statement *dst = nssObj.qcStatements[dex];
779 CE_QC_Statement *src = &cdsaObj.qcStatements[dex];
780 memset(dst, 0, sizeof(*dst));
781 coder.allocCopyItem(src->statementId, dst->statementId);
782 if(src->semanticsInfo) {
783 if(src->otherInfo) {
784 /* this is either/or, not both */
785 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
786 }
787
788 /* encode this CE_SemanticsInformation */
789 CE_SemanticsInformation *srcSI = src->semanticsInfo;
790 NSS_SemanticsInformation dstSI;
791 memset(&dstSI, 0, sizeof(dstSI));
792 if(srcSI->semanticsIdentifier) {
793 dstSI.semanticsIdentifier = (CSSM_DATA_PTR)coder.malloc(sizeof(CSSM_DATA));
794 coder.allocCopyItem(*srcSI->semanticsIdentifier,
795 *dstSI.semanticsIdentifier);
796 }
797 if(srcSI->nameRegistrationAuthorities) {
798 dstSI.nameRegistrationAuthorities =
799 (NSS_GeneralNames *)coder.malloc(sizeof(NSS_GeneralNames));
800 CL_cssmGeneralNamesToNss(*srcSI->nameRegistrationAuthorities,
801 *dstSI.nameRegistrationAuthorities, coder);
802 }
803 PRErrorCode prtn = coder.encodeItem(&dstSI, kSecAsn1SemanticsInformationTemplate,
804 dst->info);
805 if(prtn) {
806 clErrorLog("CL_cssmQualCertStatementsToNss: encode error\n");
807 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
808 }
809
810 }
811 if(src->otherInfo) {
812 /* drop in as ASN_ANY */
813 coder.allocCopyItem(*src->otherInfo, dst->info);
814 }
815 }
816 }
817
818 void CL_qualCertStatementsToCssm(
819 const NSS_QC_Statements &nssObj,
820 CE_QC_Statements &cdsaObj,
821 SecNssCoder &coder, // for temp decoding
822 Allocator &alloc)
823 {
824 memset(&cdsaObj, 0, sizeof(cdsaObj));
825 unsigned numQcs = clNssArraySize((const void **)nssObj.qcStatements);
826 if(numQcs == 0) {
827 return;
828 }
829 cdsaObj.qcStatements = (CE_QC_Statement *)alloc.malloc(
830 numQcs * sizeof(CE_QC_Statement));
831 cdsaObj.numQCStatements = numQcs;
832 for(unsigned dex=0; dex<numQcs; dex++) {
833 CE_QC_Statement *dst = &cdsaObj.qcStatements[dex];
834 NSS_QC_Statement *src = nssObj.qcStatements[dex];
835
836 memset(dst, 0, sizeof(*dst));
837 clAllocCopyData(alloc, src->statementId, dst->statementId);
838
839 /*
840 * Whether the optional info is a SemanticsInformation or is uninterpreted
841 * DER data depends on statementId.
842 */
843 if(src->info.Data) {
844 if(clCompareCssmData(&src->statementId, &CSSMOID_OID_QCS_SYNTAX_V2)) {
845 NSS_SemanticsInformation srcSI;
846 memset(&srcSI, 0, sizeof(srcSI));
847
848 /* decode info as a NSS_SemanticsInformation */
849 PRErrorCode prtn = coder.decodeItem(src->info,
850 kSecAsn1SemanticsInformationTemplate, &srcSI);
851 if(prtn) {
852 clErrorLog("***Error decoding CE_SemanticsInformation\n");
853 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
854 }
855
856 /* NSS_SemanticsInformation --> CE_SemanticsInformation */
857 dst->semanticsInfo =
858 (CE_SemanticsInformation *)alloc.malloc(sizeof(CE_SemanticsInformation));
859 CE_SemanticsInformation *dstSI = dst->semanticsInfo;
860 memset(dstSI, 0, sizeof(*dstSI));
861 if(srcSI.semanticsIdentifier) {
862 dstSI->semanticsIdentifier = (CSSM_OID *)alloc.malloc(sizeof(CSSM_OID));
863 clAllocCopyData(alloc, *srcSI.semanticsIdentifier, *dstSI->semanticsIdentifier);
864 }
865 if(srcSI.nameRegistrationAuthorities) {
866 dstSI->nameRegistrationAuthorities =
867 (CE_NameRegistrationAuthorities *)alloc.malloc(
868 sizeof(CE_NameRegistrationAuthorities));
869 CL_nssGeneralNamesToCssm(*srcSI.nameRegistrationAuthorities,
870 *dstSI->nameRegistrationAuthorities,
871 coder,
872 alloc);
873 }
874 }
875 else {
876 dst->otherInfo = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA));
877 clAllocCopyData(alloc, src->info, *dst->otherInfo);
878 }
879 }
880 }
881 }
882
883 void CL_freeQualCertStatements(
884 CE_QC_Statements &cssmQCs,
885 Allocator &alloc)
886 {
887 uint32 numQCs = cssmQCs.numQCStatements;
888 for(unsigned dex=0; dex<numQCs; dex++) {
889 CE_QC_Statement *dst = &cssmQCs.qcStatements[dex];
890 alloc.free(dst->statementId.Data);
891 if(dst->semanticsInfo) {
892 CE_SemanticsInformation *si = dst->semanticsInfo;
893 if(si->semanticsIdentifier) {
894 alloc.free(si->semanticsIdentifier->Data);
895 alloc.free(si->semanticsIdentifier);
896 }
897 if(si->nameRegistrationAuthorities) {
898 CL_freeCssmGeneralNames(si->nameRegistrationAuthorities, alloc);
899 alloc.free(si->nameRegistrationAuthorities);
900 }
901 alloc.free(si);
902 }
903 if(dst->otherInfo) {
904 alloc.free(dst->otherInfo->Data);
905 alloc.free(dst->otherInfo);
906 }
907 }
908 alloc.free(cssmQCs.qcStatements);
909 }
910
911 #pragma mark ----- decode/encode CE_DistributionPointName -----
912
913 /* This is always a DER-encoded blob at the NSS level */
914 void CL_decodeDistributionPointName(
915 const CSSM_DATA &nssBlob,
916 CE_DistributionPointName &cssmDpn,
917 SecNssCoder &coder,
918 Allocator &alloc)
919 {
920 memset(&cssmDpn, 0, sizeof(CE_DistributionPointName));
921 if(nssBlob.Length == 0) {
922 clErrorLog("***CL_decodeDistributionPointName: bad PointName\n");
923 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
924 }
925 unsigned char tag = nssBlob.Data[0] & SEC_ASN1_TAGNUM_MASK;
926 switch(tag) {
927 case NSS_DIST_POINT_FULL_NAME_TAG:
928 {
929 /* decode to temp coder memory */
930 NSS_GeneralNames gnames;
931 gnames.names = NULL;
932 if(coder.decodeItem(nssBlob, kSecAsn1DistPointFullNameTemplate,
933 &gnames)) {
934 clErrorLog("***Error decoding DistPointFullName\n");
935 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
936 }
937
938 cssmDpn.nameType = CE_CDNT_FullName;
939 cssmDpn.dpn.fullName = (CE_GeneralNames *)alloc.malloc(
940 sizeof(CE_GeneralNames));
941
942 /* copy out to caller */
943 CL_nssGeneralNamesToCssm(gnames,
944 *cssmDpn.dpn.fullName, coder, alloc);
945 break;
946 }
947 case NSS_DIST_POINT_RDN_TAG:
948 {
949 /* decode to temp coder memory */
950 NSS_RDN rdn;
951 memset(&rdn, 0, sizeof(rdn));
952 if(coder.decodeItem(nssBlob, kSecAsn1DistPointRDNTemplate,
953 &rdn)) {
954 clErrorLog("***Error decoding DistPointRDN\n");
955 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
956 }
957
958 cssmDpn.nameType = CE_CDNT_NameRelativeToCrlIssuer;
959 cssmDpn.dpn.rdn = (CSSM_X509_RDN_PTR)alloc.malloc(
960 sizeof(CSSM_X509_RDN));
961
962 /* copy out to caller */
963 CL_nssRdnToCssm(rdn, *cssmDpn.dpn.rdn, alloc, coder);
964 break;
965 }
966 default:
967 clErrorLog("***Bad CE_DistributionPointName tag\n");
968 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
969 }
970 }
971
972 void CL_encodeDistributionPointName(
973 CE_DistributionPointName &cpoint,
974 CSSM_DATA &npoint,
975 SecNssCoder &coder)
976 {
977 const SecAsn1Template *templ = NULL;
978 NSS_GeneralNames gnames;
979 NSS_RDN rdn;
980 void *encodeSrc = NULL;
981
982 /*
983 * Our job is to convert one of two incoming aggregate types
984 * into NSS format, then encode the result into npoint.
985 */
986 switch(cpoint.nameType) {
987 case CE_CDNT_FullName:
988 CL_cssmGeneralNamesToNss(*cpoint.dpn.fullName,
989 gnames, coder);
990 encodeSrc = &gnames;
991 templ = kSecAsn1DistPointFullNameTemplate;
992 break;
993
994 case CE_CDNT_NameRelativeToCrlIssuer:
995 CL_cssmRdnToNss(*cpoint.dpn.rdn, rdn, coder);
996 encodeSrc = &rdn;
997 templ = kSecAsn1DistPointRDNTemplate;
998 break;
999 default:
1000 clErrorLog("CL_encodeDistributionPointName: bad nameType\n");
1001 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG);
1002 }
1003 if(coder.encodeItem(encodeSrc, templ, npoint)) {
1004 clErrorLog("CL_encodeDistributionPointName: encode error\n");
1005 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
1006 }
1007 }
1008
1009
1010 #pragma mark --- CE_CRLDistPointsSyntax <--> NSS_CRLDistributionPoints ---
1011
1012 void CL_cssmDistPointsToNss(
1013 const CE_CRLDistPointsSyntax &cdsaObj,
1014 NSS_CRLDistributionPoints &nssObj,
1015 SecNssCoder &coder)
1016 {
1017 memset(&nssObj, 0, sizeof(nssObj));
1018 unsigned numPoints = cdsaObj.numDistPoints;
1019 if(numPoints == 0) {
1020 return;
1021 }
1022 nssObj.distPoints =
1023 (NSS_DistributionPoint **)clNssNullArray(numPoints, coder);
1024 for(unsigned dex=0; dex<numPoints; dex++) {
1025 nssObj.distPoints[dex] = (NSS_DistributionPoint *)
1026 coder.malloc(sizeof(NSS_DistributionPoint));
1027 NSS_DistributionPoint *npoint = nssObj.distPoints[dex];
1028 memset(npoint, 0, sizeof(NSS_DistributionPoint));
1029 CE_CRLDistributionPoint *cpoint = &cdsaObj.distPoints[dex];
1030
1031 /* all fields are optional */
1032 if(cpoint->distPointName) {
1033 /* encode and drop into ASN_ANY slot */
1034 npoint->distPointName = (CSSM_DATA *)
1035 coder.malloc(sizeof(CSSM_DATA));
1036 CL_encodeDistributionPointName(*cpoint->distPointName,
1037 *npoint->distPointName, coder);
1038
1039 }
1040
1041 if(cpoint->reasonsPresent) {
1042 /* bit string, presumed max length 8 bits */
1043 coder.allocItem(npoint->reasons, 1);
1044 npoint->reasons.Data[0] = cpoint->reasons;
1045 /* adjust for bit string length */
1046 npoint->reasons.Length = 8;
1047 }
1048
1049 if(cpoint->crlIssuer) {
1050 CL_cssmGeneralNamesToNss(*cpoint->crlIssuer,
1051 npoint->crlIssuer, coder);
1052 }
1053 }
1054 }
1055
1056 void CL_nssDistPointsToCssm(
1057 const NSS_CRLDistributionPoints &nssObj,
1058 CE_CRLDistPointsSyntax &cdsaObj,
1059 SecNssCoder &coder, // for temp decoding
1060 Allocator &alloc)
1061 {
1062 memset(&cdsaObj, 0, sizeof(cdsaObj));
1063 unsigned numPoints = clNssArraySize((const void **)nssObj.distPoints);
1064 if(numPoints == 0) {
1065 return;
1066 }
1067
1068 unsigned len = sizeof(CE_CRLDistributionPoint) * numPoints;
1069 cdsaObj.distPoints = (CE_CRLDistributionPoint *)alloc.malloc(len);
1070 memset(cdsaObj.distPoints, 0, len);
1071 cdsaObj.numDistPoints = numPoints;
1072
1073 for(unsigned dex=0; dex<numPoints; dex++) {
1074 CE_CRLDistributionPoint &cpoint = cdsaObj.distPoints[dex];
1075 NSS_DistributionPoint &npoint = *(nssObj.distPoints[dex]);
1076
1077 /* All three fields are optional */
1078 if(npoint.distPointName != NULL) {
1079 /* Drop in a CE_DistributionPointName */
1080 CE_DistributionPointName *cname =
1081 (CE_DistributionPointName *)alloc.malloc(
1082 sizeof(CE_DistributionPointName));
1083 memset(cname, 0, sizeof(*cname));
1084 cpoint.distPointName = cname;
1085
1086 /*
1087 * This one is currently still encoded; we have to peek
1088 * at its tag and decode accordingly.
1089 */
1090 CL_decodeDistributionPointName(*npoint.distPointName,
1091 *cname, coder, alloc);
1092 }
1093
1094 if(npoint.reasons.Data != NULL) {
1095 /* careful, it's a bit string */
1096 if(npoint.reasons.Length > 8) {
1097 clErrorLog("***CL_nssDistPointsToCssm: Malformed reasons\n");
1098 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
1099 }
1100 cpoint.reasonsPresent = CSSM_TRUE;
1101 if(npoint.reasons.Length != 0) {
1102 cpoint.reasons = npoint.reasons.Data[0];
1103 }
1104 }
1105
1106 if(npoint.crlIssuer.names != NULL) {
1107 /* Cook up a new CE_GeneralNames */
1108 cpoint.crlIssuer =
1109 (CE_GeneralNames *)alloc.malloc(sizeof(CE_GeneralNames));
1110 CL_nssGeneralNamesToCssm(npoint.crlIssuer, *cpoint.crlIssuer,
1111 coder, alloc);
1112 }
1113 }
1114 }
1115
1116 #pragma mark ----- IssuingDistributionPoint -----
1117
1118 void CL_nssIssuingDistPointToCssm(
1119 NSS_IssuingDistributionPoint *nssIdp,
1120 CE_IssuingDistributionPoint *cssmIdp,
1121 SecNssCoder &coder,
1122 Allocator &alloc)
1123 {
1124 /* All fields optional */
1125 memset(cssmIdp, 0, sizeof(*cssmIdp));
1126 if(nssIdp->distPointName) {
1127 CE_DistributionPointName *cssmDp = (CE_DistributionPointName *)
1128 alloc.malloc(sizeof(CE_DistributionPointName));
1129
1130 /*
1131 * This one is currently still encoded; we have to peek
1132 * at its tag and decode accordingly.
1133 */
1134 CL_decodeDistributionPointName(*nssIdp->distPointName,
1135 *cssmDp, coder, alloc);
1136 cssmIdp->distPointName = cssmDp;
1137 }
1138 if(nssIdp->onlyUserCerts) {
1139 cssmIdp->onlyUserCertsPresent = CSSM_TRUE;
1140 cssmIdp->onlyUserCerts = clNssBoolToCssm(*nssIdp->onlyUserCerts);
1141 }
1142 if(nssIdp->onlyCACerts) {
1143 cssmIdp->onlyCACertsPresent = CSSM_TRUE;
1144 cssmIdp->onlyCACerts = clNssBoolToCssm(*nssIdp->onlyCACerts);
1145 }
1146 if(nssIdp->onlySomeReasons) {
1147 cssmIdp->onlySomeReasonsPresent = CSSM_TRUE;
1148 if(nssIdp->onlySomeReasons->Length > 0) {
1149 cssmIdp->onlySomeReasons = *nssIdp->onlySomeReasons->Data;
1150 }
1151 else {
1152 cssmIdp->onlySomeReasons = 0;
1153 }
1154 }
1155 if(nssIdp->indirectCRL) {
1156 cssmIdp->indirectCrlPresent = CSSM_TRUE;
1157 cssmIdp->indirectCrl = clNssBoolToCssm(*nssIdp->indirectCRL);
1158 }
1159 }
1160
1161 #pragma mark --- CE_NameConstraints <--> NSS_NameConstraints ---
1162
1163 void CL_cssmNameConstraintsToNss(
1164 const CE_NameConstraints &cdsaObj,
1165 NSS_NameConstraints &nssObj,
1166 SecNssCoder &coder)
1167 {
1168 //%%%FIXME tba
1169 }
1170
1171 void CL_nssNameConstraintsToCssm(
1172 const NSS_NameConstraints &nssObj,
1173 CE_NameConstraints &cdsaObj,
1174 SecNssCoder &coder, // for temp decoding
1175 Allocator &alloc)
1176 {
1177 //%%%FIXME tba
1178 }
1179
1180 void CL_freeCssmNameConstraints(
1181 CE_NameConstraints *cssmNcs,
1182 Allocator &alloc)
1183 {
1184 if(cssmNcs == NULL) {
1185 return;
1186 }
1187 //%%%FIXME need to add a CL_freeCssmGeneralSubtrees function to clNameUtils{.h,.cpp}
1188 #if 0
1189 switch(cssmDpn->nameType) {
1190 case CE_CDNT_FullName:
1191 CL_freeCssmGeneralNames(cssmDpn->dpn.fullName, alloc);
1192 alloc.free(cssmDpn->dpn.fullName);
1193 break;
1194 case CE_CDNT_NameRelativeToCrlIssuer:
1195 CL_freeX509Rdn(cssmDpn->dpn.rdn, alloc);
1196 alloc.free(cssmDpn->dpn.rdn);
1197 break;
1198 }
1199 #endif
1200 memset(cssmNcs, 0, sizeof(*cssmNcs));
1201 }
1202
1203 #pragma mark --- CE_PolicyMappings <--> NSS_PolicyMappings ---
1204
1205 void CL_cssmPolicyMappingsToNss(
1206 const CE_PolicyMappings &cdsaObj,
1207 NSS_PolicyMappings &nssObj,
1208 SecNssCoder &coder)
1209 {
1210 //%%%FIXME tba
1211 }
1212
1213 void CL_nssPolicyMappingsToCssm(
1214 const NSS_PolicyMappings &nssObj,
1215 CE_PolicyMappings &cdsaObj,
1216 SecNssCoder &coder, // for temp decoding
1217 Allocator &alloc)
1218 {
1219 //%%%FIXME tba
1220 }
1221
1222 void CL_freeCssmPolicyMappings(
1223 CE_PolicyMappings *cssmPms,
1224 Allocator &alloc)
1225 {
1226 if(cssmPms == NULL) {
1227 return;
1228 }
1229 //%%%FIXME tba
1230
1231 memset(cssmPms, 0, sizeof(*cssmPms));
1232 }
1233
1234 #pragma mark --- CE_PolicyConstraints <--> NSS_PolicyConstraints ---
1235
1236 void CL_cssmPolicyConstraintsToNss(
1237 const CE_PolicyConstraints *cdsaObj,
1238 NSS_PolicyConstraints *nssObj,
1239 SecNssCoder &coder)
1240 {
1241 //%%%FIXME tba
1242 }
1243
1244 void CL_nssPolicyConstraintsToCssm(
1245 const NSS_PolicyConstraints *nssObj,
1246 CE_PolicyConstraints *cdsaObj,
1247 SecNssCoder &coder, // for temp decoding
1248 Allocator &alloc)
1249 {
1250 memset(cdsaObj, 0, sizeof(*cdsaObj));
1251 if(nssObj->requireExplicitPolicy.Data) {
1252 cdsaObj->requireExplicitPolicyPresent = CSSM_TRUE;
1253 cdsaObj->inhibitPolicyMapping = clDataToInt(
1254 nssObj->requireExplicitPolicy, 0);
1255 }
1256 if(nssObj->inhibitPolicyMapping.Data) {
1257 cdsaObj->inhibitPolicyMappingPresent = CSSM_TRUE;
1258 cdsaObj->inhibitPolicyMapping = clDataToInt(
1259 nssObj->inhibitPolicyMapping, 0);
1260 }
1261 }
1262
1263 void CL_freeCssmPolicyConstraints(
1264 CE_PolicyConstraints *cssmPcs,
1265 Allocator &alloc)
1266 {
1267 if(cssmPcs == NULL) {
1268 return;
1269 }
1270
1271 memset(cssmPcs, 0, sizeof(*cssmPcs));
1272 }
1273
1274
1275 #pragma mark ----- ECDSA_SigAlgParams support -----
1276
1277 /*
1278 * Some implementations use a two-OID mechanism to specify ECDSA signature
1279 * algorithm with a digest of other than SHA1. This is really not necessary;
1280 * we use the single-OID method (e.g. CSSMOID_ECDSA_WithSHA512) when
1281 * encoding, but we have to accomodate externally generated items with
1282 * the two-OID method. This routine decodes the digest OID and infers a
1283 * CSSM_ALGORITHMS from it.
1284 * Throws CSSMERR_CL_UNKNOWN_FORMAT on any error.
1285 */
1286 CSSM_ALGORITHMS CL_nssDecodeECDSASigAlgParams(
1287 const CSSM_DATA &encParams,
1288 SecNssCoder &coder)
1289 {
1290 CSSM_X509_ALGORITHM_IDENTIFIER algParams;
1291 memset(&algParams, 0, sizeof(algParams));
1292 PRErrorCode prtn = coder.decodeItem(encParams, kSecAsn1AlgorithmIDTemplate, &algParams);
1293 if(prtn) {
1294 clErrorLog("CL_nssDecodeECDSASigAlgParams: error decoding CSSM_X509_ALGORITHM_IDENTIFIER\n");
1295 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
1296 }
1297
1298 /* get the digest algorithm, convert to ECDSA w/digest OID */
1299 CSSM_ALGORITHMS digestAlg = CL_oidToAlg(algParams.algorithm);
1300 switch(digestAlg) {
1301 case CSSM_ALGID_SHA1:
1302 return CSSM_ALGID_SHA1WithECDSA;
1303 case CSSM_ALGID_SHA224:
1304 return CSSM_ALGID_SHA224WithECDSA;
1305 case CSSM_ALGID_SHA256:
1306 return CSSM_ALGID_SHA256WithECDSA;
1307 case CSSM_ALGID_SHA384:
1308 return CSSM_ALGID_SHA384WithECDSA;
1309 case CSSM_ALGID_SHA512:
1310 return CSSM_ALGID_SHA512WithECDSA;
1311 default:
1312 clErrorLog("CL_nssDecodeECDSASigAlgParams: unknown digest algorithm\n");
1313 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
1314 }
1315 }
1316
1317 #pragma mark ----- Top-level Cert/CRL encode and decode -----
1318
1319 /*
1320 * To ensure a secure means of signing and verifying TBSCert blobs, we
1321 * provide these functions to encode and decode just the top-level
1322 * elements of a certificate. Unfortunately there is no guarantee
1323 * that when you decode and re-encode a TBSCert blob, you get the
1324 * same thing you started with (although with DER rules, as opposed
1325 * to BER rules, you should). Thus when signing, we sign the TBSCert
1326 * and encode the signed cert here without ever decoding the TBSCert (or,
1327 * at least, without using the decoded version to get the encoded TBS blob).
1328 */
1329
1330 void CL_certCrlDecodeComponents(
1331 const CssmData &signedItem, // DER-encoded cert or CRL
1332 CssmOwnedData &tbsBlob, // still DER-encoded
1333 CssmOwnedData &algId, // ditto
1334 CssmOwnedData &rawSig) // raw bits (not an encoded AsnBits)
1335 {
1336 /* BER-decode into temp memory */
1337 NSS_SignedCertOrCRL nssObj;
1338 SecNssCoder coder;
1339 PRErrorCode prtn;
1340
1341 memset(&nssObj, 0, sizeof(nssObj));
1342 prtn = coder.decode(signedItem.data(), signedItem.length(),
1343 kSecAsn1SignedCertOrCRLTemplate, &nssObj);
1344 if(prtn) {
1345 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
1346 }
1347
1348 /* tbsBlob and algId are raw ASN_ANY including tags, which we pass
1349 * back to caller intact */
1350 tbsBlob.copy(nssObj.tbsBlob.Data, nssObj.tbsBlob.Length);
1351 algId.copy(nssObj.signatureAlgorithm.Data,
1352 nssObj.signatureAlgorithm.Length);
1353
1354 /* signature is a bit string which we do in fact decode */
1355 rawSig.copy(nssObj.signature.Data,
1356 (nssObj.signature.Length + 7) / 8);
1357 }
1358
1359
1360 /*
1361 * Given pre-DER-encoded blobs, do the final encode step for a signed cert.
1362 */
1363 void
1364 CL_certEncodeComponents(
1365 const CssmData &TBSCert, // DER-encoded
1366 const CssmData &algId, // ditto
1367 const CssmData &rawSig, // raw bits, not encoded
1368 CssmOwnedData &signedCert) // DER-encoded
1369 {
1370 NSS_SignedCertOrCRL nssObj;
1371 nssObj.tbsBlob.Data = TBSCert.Data;
1372 nssObj.tbsBlob.Length = TBSCert.Length;
1373 nssObj.signatureAlgorithm.Data = algId.Data;
1374 nssObj.signatureAlgorithm.Length = algId.Length;
1375 nssObj.signature.Data = rawSig.Data;
1376 nssObj.signature.Length = rawSig.Length * 8; // BIT STRING
1377
1378 PRErrorCode prtn;
1379
1380 prtn = SecNssEncodeItemOdata(&nssObj,
1381 kSecAsn1SignedCertOrCRLTemplate,signedCert);
1382 if(prtn) {
1383 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
1384 }
1385
1386 }