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