2 * Copyright (c) 2003,2011-2012,2014 Apple Inc. All Rights Reserved.
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
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.
19 * clNssUtils.cpp - support for libnssasn1-based ASN1 encode/decode
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>
35 #pragma mark ----- ArenaAllocator -----
38 * Avoid inlining this for debuggability
40 void *ArenaAllocator::malloc(size_t len
) throw(std::bad_alloc
)
43 return mCoder
.malloc(len
);
46 throw std::bad_alloc();
50 /* intentionally not implemented, should never be called */
51 void ArenaAllocator::free(void *p
) throw()
53 throw std::bad_alloc();
56 void *ArenaAllocator::realloc(void *p
, size_t len
) throw(std::bad_alloc
)
58 throw std::bad_alloc();
61 #pragma mark ----- Malloc/Copy/Compare CSSM_DATA -----
64 * Misc. alloc/copy with arbitrary Allocator
66 /* malloc d.Data, set d.Length */
76 dst
.Data
= (uint8
*)alloc
.malloc(len
);
87 clAllocData(alloc
, dst
, src
.Length
);
89 memmove(dst
.Data
, src
.Data
, src
.Length
);
94 * Compare two CSSM_DATAs (or two CSSM_OIDs), return true if identical.
96 bool clCompareCssmData(
97 const CSSM_DATA
*data1
,
98 const CSSM_DATA
*data2
)
100 if((data1
== NULL
) || (data1
->Data
== NULL
) ||
101 (data2
== NULL
) || (data2
->Data
== NULL
) ||
102 (data1
->Length
!= data2
->Length
)) {
105 if(data1
->Length
!= data2
->Length
) {
108 if(memcmp(data1
->Data
, data2
->Data
, data1
->Length
) == 0) {
116 #pragma mark ----- CSSM_DATA <--> uint32 -----
119 const CSSM_DATA
&cdata
,
120 CSSM_RETURN toThrow
) /* = CSSMERR_CL_INVALID_CERT_POINTER */
122 if((cdata
.Length
== 0) || (cdata
.Data
== NULL
)) {
125 size_t len
= cdata
.Length
;
126 if(len
> sizeof(uint32
)) {
129 len
= sizeof(uint32
);
132 CssmError::throwMe(toThrow
);
137 uint8
*cp
= cdata
.Data
;
138 for(size_t i
=0; i
<len
; i
++) {
139 rtn
= (rtn
<< 8) | *cp
++;
154 else if(num
< 0x10000) {
157 else if(num
< 0x1000000) {
163 clAllocData(alloc
, cdata
, len
);
164 uint8
*cp
= &cdata
.Data
[len
- 1];
165 for(unsigned i
=0; i
<len
; i
++) {
171 #pragma mark ----- CSSM_BOOL <--> CSSM_DATA -----
173 * A Bool is encoded as one byte of either 0 or 0xff
174 * Default of NSS boolean not present is false
176 CSSM_BOOL
clNssBoolToCssm(
177 const CSSM_DATA
&nssBool
)
179 if((nssBool
.Data
!= NULL
) && (nssBool
.Data
[0] == 0xff)) {
187 void clCssmBoolToNss(
192 uint32 num
= cBool
? 0xff : 0;
193 clIntToData(num
, nssBool
, alloc
);
196 #pragma mark ----- Bit String manipulation -----
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).
205 void clCssmBitStringToNss(
208 size_t numBits
= b
.Length
* 8;
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
++) {
230 /* !foundSet --> numBits = 0 */
231 assert(((numBits
> 0) & foundSet
) || ((numBits
== 0) && !foundSet
));
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.
241 void clNssBitStringToCssm(
244 CSSM_SIZE byteCount
= (b
.Length
+ 7) / 8;
245 unsigned partialBits
= b
.Length
& 0x7;
246 b
.Length
= byteCount
;
247 if(partialBits
== 0) {
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;
259 #pragma mark ----- NSS array manipulation -----
261 * How many items in a NULL-terminated array of pointers?
263 unsigned clNssArraySize(
275 /* malloc a NULL-ed array of pointers of size num+1 */
276 void **clNssNullArray(
280 unsigned len
= (num
+ 1) * sizeof(void *);
281 void **p
= (void **)coder
.malloc(len
);
287 * GIven a CSSM_DATA containing a decoded BIT_STRING,
288 * convert to a KeyUsage.
290 CE_KeyUsage
clBitStringToKeyUsage(
291 const CSSM_DATA
&cdata
)
293 size_t toCopy
= (cdata
.Length
+ 7) / 8;
295 /* I hope I never see this... */
296 clErrorLog("clBitStringToKeyUsage: KeyUsage larger than 2 bytes!");
299 unsigned char bits
[2] = {0, 0};
300 memmove(bits
, cdata
.Data
, toCopy
);
301 CE_KeyUsage usage
= (((unsigned)bits
[0]) << 8) | bits
[1];
305 CSSM_ALGORITHMS
CL_oidToAlg(
309 bool found
= cssmOidToAlg(&oid
, &alg
);
311 clErrorLog("CL_oidToAlg: unknown alg\n");
312 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT
);
317 #pragma mark ----- copy CSSM_X509_ALGORITHM_IDENTIFIER -----
320 * Copy CSSM_X509_ALGORITHM_IDENTIFIER, same format (NSS and CSSM).
323 const CSSM_X509_ALGORITHM_IDENTIFIER
&srcAlgId
,
324 CSSM_X509_ALGORITHM_IDENTIFIER
&dstAlgId
,
327 clAllocCopyData(alloc
, srcAlgId
.algorithm
, dstAlgId
.algorithm
);
328 clAllocCopyData(alloc
, srcAlgId
.parameters
, dstAlgId
.parameters
);
331 void CL_freeCssmAlgId(
332 CSSM_X509_ALGORITHM_IDENTIFIER
*cdsaObj
, // optional
335 if(cdsaObj
== NULL
) {
338 alloc
.free(cdsaObj
->algorithm
.Data
);
339 alloc
.free(cdsaObj
->parameters
.Data
);
340 memset(cdsaObj
, 0, sizeof(CSSM_X509_ALGORITHM_IDENTIFIER
));
344 #pragma mark ----- CSSM_X509_TIME <--> NSS format -----
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
354 /* The template chooser does the work here */
356 bool CL_nssTimeToCssm(
357 const NSS_TaggedItem
&nssTime
,
358 CSSM_X509_TIME
&cssmObj
,
361 cssmObj
.timeType
= nssTime
.tag
;
362 clAllocCopyData(alloc
, nssTime
.item
, cssmObj
.time
);
367 * CSSM time to NSS time.
369 void CL_cssmTimeToNss(
370 const CSSM_X509_TIME
&cssmTime
,
371 NSS_TaggedItem
&nssTime
,
374 nssTime
.tag
= cssmTime
.timeType
;
375 coder
.allocCopyItem(cssmTime
.time
, nssTime
.item
);
378 void CL_freeCssmTime(
379 CSSM_X509_TIME
*cssmTime
,
382 if(cssmTime
== NULL
) {
385 if(cssmTime
->time
.Data
) {
386 alloc
.free(cssmTime
->time
.Data
);
388 memset(cssmTime
, 0, sizeof(CSSM_X509_TIME
));
392 #pragma mark ----- CSSM_X509_SUBJECT_PUBLIC_KEY_INFO <--> CSSM_KEY -----
395 * Copy a CSSM_X509_SUBJECT_PUBLIC_KEY_INFO.
397 * Same format (NSS and CSSM), EXCEPT:
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.
403 * Caller tells us which format (bits or bytes)
404 * to use for each of {src, dst}.
406 void CL_copySubjPubKeyInfo(
407 const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
&srcInfo
,
409 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
&dstInfo
,
413 CL_copyAlgId(srcInfo
.algorithm
, dstInfo
.algorithm
, alloc
);
415 CSSM_DATA srcKey
= srcInfo
.subjectPublicKey
;
417 srcKey
.Length
= (srcKey
.Length
+ 7) / 8;
419 clAllocCopyData(alloc
, srcKey
, dstInfo
.subjectPublicKey
);
421 dstInfo
.subjectPublicKey
.Length
*= 8;
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).
431 CSSM_KEY_PTR
CL_extractCSSMKeyNSS(
432 const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
&keyInfo
,
434 const DecodedCert
*decodedCert
) // optional
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
);
441 hdr
.HeaderVersion
= CSSM_KEYHEADER_VERSION
;
443 hdr
.BlobType
= CSSM_KEYBLOB_RAW
;
444 hdr
.AlgorithmId
= CL_oidToAlg(keyInfo
.algorithm
.algorithm
);
445 hdr
.KeyAttr
= CSSM_KEYATTR_MODIFIABLE
| CSSM_KEYATTR_EXTRACTABLE
;
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.
453 switch(hdr
.AlgorithmId
) {
455 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_PKCS1
;
458 case CSSM_ALGID_ECDSA
:
460 case CSSM_ALGMODE_PKCS1_EME_OAEP
:
461 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_X509
;
464 /* CSSM_KEYBLOB_RAW_FORMAT_NONE --> DER encoded */
465 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_NONE
;
469 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_NONE
;
471 hdr
.KeyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
473 /* KeyUsage inferred from extensions */
475 hdr
.KeyUsage
= decodedCert
->inferKeyUsage();
478 hdr
.KeyUsage
= CSSM_KEYUSE_ANY
;
481 /* start/end date unknown, leave zero */
482 hdr
.WrapAlgorithmId
= CSSM_ALGID_NONE
;
483 hdr
.WrapMode
= CSSM_ALGMODE_NONE
;
485 switch(hdr
.AlgorithmId
) {
487 case CSSM_ALGID_ECDSA
:
489 case CSSM_ALGMODE_PKCS1_EME_OAEP
:
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.
497 PRErrorCode prtn
= SecNssEncodeItemOdata(&keyInfo
,
498 kSecAsn1SubjectPublicKeyInfoTemplate
, keyData
);
500 clErrorLog("extractCSSMKey: error on reencode\n");
501 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR
);
508 * keyInfo.subjectPublicKey (in BITS) ==> KeyData
510 keyData
.copy(keyInfo
.subjectPublicKey
.Data
,
511 (keyInfo
.subjectPublicKey
.Length
+ 7) / 8);
515 * LogicalKeySizeInBits - ask the CSP
517 CSSM_CSP_HANDLE cspHand
= getGlobalCspHand(true);
518 CSSM_KEY_SIZE keySize
;
520 crtn
= CSSM_QueryKeySizeInBits(cspHand
, CSSM_INVALID_HANDLE
, cssmKey
,
524 CssmError::throwMe(crtn
);
525 case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE
:
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).
531 hdr
.KeyAttr
|= CSSM_KEYATTR_PARTIAL
;
534 cssmKey
->KeyHeader
.LogicalKeySizeInBits
=
535 keySize
.LogicalKeySizeInBits
;
544 * Set up a encoded NULL for CSSM_X509_ALGORITHM_IDENTIFIER.parameters.
546 void CL_nullAlgParams(
547 CSSM_X509_ALGORITHM_IDENTIFIER
&algId
)
549 static const uint8 encNull
[2] = { SEC_ASN1_NULL
, 0 };
550 CSSM_DATA encNullData
;
551 encNullData
.Data
= (uint8
*)encNull
;
552 encNullData
.Length
= 2;
554 algId
.parameters
= encNullData
;
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
564 void CL_CSSMKeyToSubjPubKeyInfoNSS(
565 const CSSM_KEY
&cssmKey
,
566 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
&nssKeyInfo
,
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
);
574 memset(&nssKeyInfo
, 0, sizeof(nssKeyInfo
));
576 /* algorithm and format dependent from here... */
577 switch(hdr
.AlgorithmId
) {
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
);
586 /* Key header's algorithm --> OID */
587 const CSSM_OID
*oid
= cssmAlgToOid(hdr
.AlgorithmId
);
589 clErrorLog("CL SetField: Unknown key algorithm\n");
590 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
592 CSSM_X509_ALGORITHM_IDENTIFIER
&algId
= nssKeyInfo
.algorithm
;
593 coder
.allocCopyItem(*oid
, algId
.algorithm
);
595 /* NULL algorithm parameters, always in this case */
596 CL_nullAlgParams(algId
);
598 /* Copy key bits, destination is a BIT STRING */
599 coder
.allocCopyItem(cssmKey
.KeyData
, nssKeyInfo
.subjectPublicKey
);
600 nssKeyInfo
.subjectPublicKey
.Length
*= 8;
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
);
611 * All we do is decode the whole key blob into the
612 * SubjectPublicKeyInfo.
614 if(coder
.decodeItem(cssmKey
.KeyData
,
615 kSecAsn1SubjectPublicKeyInfoTemplate
,
617 clErrorLog("CL SetField: Error decoding DSA public key\n");
618 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
625 CSSM_KEY_PTR cssmKey
,
629 if(cssmKey
== NULL
) {
632 alloc
.free(cssmKey
->KeyData
.Data
);
633 memset(cssmKey
, 0, sizeof(CSSM_KEY
));
639 #pragma mark ----- CE_AuthorityKeyID <--> NSS_AuthorityKeyId -----
641 void CL_cssmAuthorityKeyIdToNss(
642 const CE_AuthorityKeyID
&cdsaObj
,
643 NSS_AuthorityKeyId
&nssObj
,
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
);
651 if(cdsaObj
.generalNamesPresent
) {
652 /* GeneralNames, the hard one */
653 CL_cssmGeneralNamesToNss(*cdsaObj
.generalNames
,
654 nssObj
.genNames
, coder
);
656 if(cdsaObj
.serialNumberPresent
) {
657 coder
.allocCopyItem(cdsaObj
.serialNumber
,nssObj
.serialNumber
);
661 void CL_nssAuthorityKeyIdToCssm(
662 const NSS_AuthorityKeyId
&nssObj
,
663 CE_AuthorityKeyID
&cdsaObj
,
664 SecNssCoder
&coder
, // for temp decoding
667 if(nssObj
.keyIdentifier
!= NULL
) {
668 cdsaObj
.keyIdentifierPresent
= CSSM_TRUE
;
669 clAllocCopyData(alloc
, *nssObj
.keyIdentifier
, cdsaObj
.keyIdentifier
);
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
,
681 if(nssObj
.serialNumber
.Data
!= NULL
) {
682 cdsaObj
.serialNumberPresent
= CSSM_TRUE
;
683 clAllocCopyData(alloc
, nssObj
.serialNumber
, cdsaObj
.serialNumber
);
687 #pragma mark ----- CE_AuthorityInfoAccess <--> NSS_AuthorityInfoAccess -----
689 void CL_cssmInfoAccessToNss(
690 const CE_AuthorityInfoAccess
&cdsaObj
,
691 NSS_AuthorityInfoAccess
&nssObj
,
694 memset(&nssObj
, 0, sizeof(nssObj
));
695 uint32 numDescs
= cdsaObj
.numAccessDescriptions
;
696 nssObj
.accessDescriptions
= (NSS_AccessDescription
**)clNssNullArray(numDescs
, coder
);
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
);
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
);
710 clErrorLog("CL_cssmInfoAccessToNss: encode error\n");
711 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR
);
716 void CL_infoAccessToCssm(
717 const NSS_AuthorityInfoAccess
&nssObj
,
718 CE_AuthorityInfoAccess
&cdsaObj
,
719 SecNssCoder
&coder
, // for temp decoding
722 memset(&cdsaObj
, 0, sizeof(cdsaObj
));
723 unsigned numDescs
= clNssArraySize((const void **)nssObj
.accessDescriptions
);
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
);
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
);
741 clErrorLog("***Error decoding NSS_AuthorityInfoAccess.accessLocation\n");
742 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT
);
745 /* then convert the result to CSSM */
746 CL_nssGeneralNameToCssm(nssGenName
, dst
->accessLocation
, coder
, alloc
);
750 void CL_freeInfoAccess(
751 CE_AuthorityInfoAccess
&cssmInfo
,
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
);
760 alloc
.free(cssmInfo
.accessDescriptions
);
764 #pragma mark ----- CE_QC_Statements <--> NSS_QC_Statements -----
766 void CL_cssmQualCertStatementsToNss(
767 const CE_QC_Statements
&cdsaObj
,
768 NSS_QC_Statements
&nssObj
,
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
) {
784 /* this is either/or, not both */
785 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER
);
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
);
797 if(srcSI
->nameRegistrationAuthorities
) {
798 dstSI
.nameRegistrationAuthorities
=
799 (NSS_GeneralNames
*)coder
.malloc(sizeof(NSS_GeneralNames
));
800 CL_cssmGeneralNamesToNss(*srcSI
->nameRegistrationAuthorities
,
801 *dstSI
.nameRegistrationAuthorities
, coder
);
803 PRErrorCode prtn
= coder
.encodeItem(&dstSI
, kSecAsn1SemanticsInformationTemplate
,
806 clErrorLog("CL_cssmQualCertStatementsToNss: encode error\n");
807 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR
);
812 /* drop in as ASN_ANY */
813 coder
.allocCopyItem(*src
->otherInfo
, dst
->info
);
818 void CL_qualCertStatementsToCssm(
819 const NSS_QC_Statements
&nssObj
,
820 CE_QC_Statements
&cdsaObj
,
821 SecNssCoder
&coder
, // for temp decoding
824 memset(&cdsaObj
, 0, sizeof(cdsaObj
));
825 unsigned numQcs
= clNssArraySize((const void **)nssObj
.qcStatements
);
829 cdsaObj
.qcStatements
= (CE_QC_Statement
*)alloc
.malloc(
830 numQcs
* sizeof(CE_AccessDescription
));
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
];
836 memset(dst
, 0, sizeof(*dst
));
837 clAllocCopyData(alloc
, src
->statementId
, dst
->statementId
);
840 * Whether the optional info is a SemanticsInformation or is uninterpreted
841 * DER data depends on statementId.
844 if(clCompareCssmData(&src
->statementId
, &CSSMOID_OID_QCS_SYNTAX_V2
)) {
845 NSS_SemanticsInformation srcSI
;
846 memset(&srcSI
, 0, sizeof(srcSI
));
848 /* decode info as a NSS_SemanticsInformation */
849 PRErrorCode prtn
= coder
.decodeItem(src
->info
,
850 kSecAsn1SemanticsInformationTemplate
, &srcSI
);
852 clErrorLog("***Error decoding CE_SemanticsInformation\n");
853 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT
);
856 /* NSS_SemanticsInformation --> CE_SemanticsInformation */
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
);
865 if(srcSI
.nameRegistrationAuthorities
) {
866 dstSI
->nameRegistrationAuthorities
=
867 (CE_NameRegistrationAuthorities
*)alloc
.malloc(
868 sizeof(CE_NameRegistrationAuthorities
));
869 CL_nssGeneralNamesToCssm(*srcSI
.nameRegistrationAuthorities
,
870 *dstSI
->nameRegistrationAuthorities
,
876 dst
->otherInfo
= (CSSM_DATA_PTR
)alloc
.malloc(sizeof(CSSM_DATA
));
877 clAllocCopyData(alloc
, src
->info
, *dst
->otherInfo
);
883 void CL_freeQualCertStatements(
884 CE_QC_Statements
&cssmQCs
,
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
);
897 if(si
->nameRegistrationAuthorities
) {
898 CL_freeCssmGeneralNames(si
->nameRegistrationAuthorities
, alloc
);
899 alloc
.free(si
->nameRegistrationAuthorities
);
904 alloc
.free(dst
->otherInfo
->Data
);
905 alloc
.free(dst
->otherInfo
);
908 alloc
.free(cssmQCs
.qcStatements
);
911 #pragma mark ----- decode/encode CE_DistributionPointName -----
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
,
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
);
925 unsigned char tag
= nssBlob
.Data
[0] & SEC_ASN1_TAGNUM_MASK
;
927 case NSS_DIST_POINT_FULL_NAME_TAG
:
929 /* decode to temp coder memory */
930 NSS_GeneralNames gnames
;
932 if(coder
.decodeItem(nssBlob
, kSecAsn1DistPointFullNameTemplate
,
934 clErrorLog("***Error decoding DistPointFullName\n");
935 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT
);
938 cssmDpn
.nameType
= CE_CDNT_FullName
;
939 cssmDpn
.dpn
.fullName
= (CE_GeneralNames
*)alloc
.malloc(
940 sizeof(CE_GeneralNames
));
942 /* copy out to caller */
943 CL_nssGeneralNamesToCssm(gnames
,
944 *cssmDpn
.dpn
.fullName
, coder
, alloc
);
947 case NSS_DIST_POINT_RDN_TAG
:
949 /* decode to temp coder memory */
951 memset(&rdn
, 0, sizeof(rdn
));
952 if(coder
.decodeItem(nssBlob
, kSecAsn1DistPointRDNTemplate
,
954 clErrorLog("***Error decoding DistPointRDN\n");
955 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT
);
958 cssmDpn
.nameType
= CE_CDNT_NameRelativeToCrlIssuer
;
959 cssmDpn
.dpn
.rdn
= (CSSM_X509_RDN_PTR
)alloc
.malloc(
960 sizeof(CSSM_X509_RDN
));
962 /* copy out to caller */
963 CL_nssRdnToCssm(rdn
, *cssmDpn
.dpn
.rdn
, alloc
, coder
);
967 clErrorLog("***Bad CE_DistributionPointName tag\n");
968 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT
);
972 void CL_encodeDistributionPointName(
973 CE_DistributionPointName
&cpoint
,
977 const SecAsn1Template
*templ
= NULL
;
978 NSS_GeneralNames gnames
;
980 void *encodeSrc
= NULL
;
983 * Our job is to convert one of two incoming aggregate types
984 * into NSS format, then encode the result into npoint.
986 switch(cpoint
.nameType
) {
987 case CE_CDNT_FullName
:
988 CL_cssmGeneralNamesToNss(*cpoint
.dpn
.fullName
,
991 templ
= kSecAsn1DistPointFullNameTemplate
;
994 case CE_CDNT_NameRelativeToCrlIssuer
:
995 CL_cssmRdnToNss(*cpoint
.dpn
.rdn
, rdn
, coder
);
997 templ
= kSecAsn1DistPointRDNTemplate
;
1000 clErrorLog("CL_encodeDistributionPointName: bad nameType\n");
1001 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG
);
1003 if(coder
.encodeItem(encodeSrc
, templ
, npoint
)) {
1004 clErrorLog("CL_encodeDistributionPointName: encode error\n");
1005 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR
);
1010 #pragma mark --- CE_CRLDistPointsSyntax <--> NSS_CRLDistributionPoints ---
1012 void CL_cssmDistPointsToNss(
1013 const CE_CRLDistPointsSyntax
&cdsaObj
,
1014 NSS_CRLDistributionPoints
&nssObj
,
1017 memset(&nssObj
, 0, sizeof(nssObj
));
1018 unsigned numPoints
= cdsaObj
.numDistPoints
;
1019 if(numPoints
== 0) {
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
];
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
);
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;
1049 if(cpoint
->crlIssuer
) {
1050 CL_cssmGeneralNamesToNss(*cpoint
->crlIssuer
,
1051 npoint
->crlIssuer
, coder
);
1056 void CL_nssDistPointsToCssm(
1057 const NSS_CRLDistributionPoints
&nssObj
,
1058 CE_CRLDistPointsSyntax
&cdsaObj
,
1059 SecNssCoder
&coder
, // for temp decoding
1062 memset(&cdsaObj
, 0, sizeof(cdsaObj
));
1063 unsigned numPoints
= clNssArraySize((const void **)nssObj
.distPoints
);
1064 if(numPoints
== 0) {
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
;
1073 for(unsigned dex
=0; dex
<numPoints
; dex
++) {
1074 CE_CRLDistributionPoint
&cpoint
= cdsaObj
.distPoints
[dex
];
1075 NSS_DistributionPoint
&npoint
= *(nssObj
.distPoints
[dex
]);
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
;
1087 * This one is currently still encoded; we have to peek
1088 * at its tag and decode accordingly.
1090 CL_decodeDistributionPointName(*npoint
.distPointName
,
1091 *cname
, coder
, alloc
);
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
);
1100 cpoint
.reasonsPresent
= CSSM_TRUE
;
1101 if(npoint
.reasons
.Length
!= 0) {
1102 cpoint
.reasons
= npoint
.reasons
.Data
[0];
1106 if(npoint
.crlIssuer
.names
!= NULL
) {
1107 /* Cook up a new CE_GeneralNames */
1109 (CE_GeneralNames
*)alloc
.malloc(sizeof(CE_GeneralNames
));
1110 CL_nssGeneralNamesToCssm(npoint
.crlIssuer
, *cpoint
.crlIssuer
,
1116 #pragma mark ----- IssuingDistributionPoint -----
1118 void CL_nssIssuingDistPointToCssm(
1119 NSS_IssuingDistributionPoint
*nssIdp
,
1120 CE_IssuingDistributionPoint
*cssmIdp
,
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
));
1131 * This one is currently still encoded; we have to peek
1132 * at its tag and decode accordingly.
1134 CL_decodeDistributionPointName(*nssIdp
->distPointName
,
1135 *cssmDp
, coder
, alloc
);
1136 cssmIdp
->distPointName
= cssmDp
;
1138 if(nssIdp
->onlyUserCerts
) {
1139 cssmIdp
->onlyUserCertsPresent
= CSSM_TRUE
;
1140 cssmIdp
->onlyUserCerts
= clNssBoolToCssm(*nssIdp
->onlyUserCerts
);
1142 if(nssIdp
->onlyCACerts
) {
1143 cssmIdp
->onlyCACertsPresent
= CSSM_TRUE
;
1144 cssmIdp
->onlyCACerts
= clNssBoolToCssm(*nssIdp
->onlyCACerts
);
1146 if(nssIdp
->onlySomeReasons
) {
1147 cssmIdp
->onlySomeReasonsPresent
= CSSM_TRUE
;
1148 if(nssIdp
->onlySomeReasons
->Length
> 0) {
1149 cssmIdp
->onlySomeReasons
= *nssIdp
->onlySomeReasons
->Data
;
1152 cssmIdp
->onlySomeReasons
= 0;
1155 if(nssIdp
->indirectCRL
) {
1156 cssmIdp
->indirectCrlPresent
= CSSM_TRUE
;
1157 cssmIdp
->indirectCrl
= clNssBoolToCssm(*nssIdp
->indirectCRL
);
1161 #pragma mark --- CE_NameConstraints <--> NSS_NameConstraints ---
1163 void CL_cssmNameConstraintsToNss(
1164 const CE_NameConstraints
&cdsaObj
,
1165 NSS_NameConstraints
&nssObj
,
1171 void CL_nssNameConstraintsToCssm(
1172 const NSS_NameConstraints
&nssObj
,
1173 CE_NameConstraints
&cdsaObj
,
1174 SecNssCoder
&coder
, // for temp decoding
1180 void CL_freeCssmNameConstraints(
1181 CE_NameConstraints
*cssmNcs
,
1184 if(cssmNcs
== NULL
) {
1187 //%%%FIXME need to add a CL_freeCssmGeneralSubtrees function to clNameUtils{.h,.cpp}
1189 switch(cssmDpn
->nameType
) {
1190 case CE_CDNT_FullName
:
1191 CL_freeCssmGeneralNames(cssmDpn
->dpn
.fullName
, alloc
);
1192 alloc
.free(cssmDpn
->dpn
.fullName
);
1194 case CE_CDNT_NameRelativeToCrlIssuer
:
1195 CL_freeX509Rdn(cssmDpn
->dpn
.rdn
, alloc
);
1196 alloc
.free(cssmDpn
->dpn
.rdn
);
1200 memset(cssmNcs
, 0, sizeof(*cssmNcs
));
1203 #pragma mark --- CE_PolicyMappings <--> NSS_PolicyMappings ---
1205 void CL_cssmPolicyMappingsToNss(
1206 const CE_PolicyMappings
&cdsaObj
,
1207 NSS_PolicyMappings
&nssObj
,
1213 void CL_nssPolicyMappingsToCssm(
1214 const NSS_PolicyMappings
&nssObj
,
1215 CE_PolicyMappings
&cdsaObj
,
1216 SecNssCoder
&coder
, // for temp decoding
1222 void CL_freeCssmPolicyMappings(
1223 CE_PolicyMappings
*cssmPms
,
1226 if(cssmPms
== NULL
) {
1231 memset(cssmPms
, 0, sizeof(*cssmPms
));
1234 #pragma mark --- CE_PolicyConstraints <--> NSS_PolicyConstraints ---
1236 void CL_cssmPolicyConstraintsToNss(
1237 const CE_PolicyConstraints
*cdsaObj
,
1238 NSS_PolicyConstraints
*nssObj
,
1244 void CL_nssPolicyConstraintsToCssm(
1245 const NSS_PolicyConstraints
*nssObj
,
1246 CE_PolicyConstraints
*cdsaObj
,
1247 SecNssCoder
&coder
, // for temp decoding
1250 memset(cdsaObj
, 0, sizeof(*cdsaObj
));
1251 if(nssObj
->requireExplicitPolicy
.Data
) {
1252 cdsaObj
->requireExplicitPolicyPresent
= CSSM_TRUE
;
1253 cdsaObj
->inhibitPolicyMapping
= clDataToInt(
1254 nssObj
->requireExplicitPolicy
, 0);
1256 if(nssObj
->inhibitPolicyMapping
.Data
) {
1257 cdsaObj
->inhibitPolicyMappingPresent
= CSSM_TRUE
;
1258 cdsaObj
->inhibitPolicyMapping
= clDataToInt(
1259 nssObj
->inhibitPolicyMapping
, 0);
1263 void CL_freeCssmPolicyConstraints(
1264 CE_PolicyConstraints
*cssmPcs
,
1267 if(cssmPcs
== NULL
) {
1271 memset(cssmPcs
, 0, sizeof(*cssmPcs
));
1275 #pragma mark ----- ECDSA_SigAlgParams support -----
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.
1286 CSSM_ALGORITHMS
CL_nssDecodeECDSASigAlgParams(
1287 const CSSM_DATA
&encParams
,
1290 CSSM_X509_ALGORITHM_IDENTIFIER algParams
;
1291 memset(&algParams
, 0, sizeof(algParams
));
1292 PRErrorCode prtn
= coder
.decodeItem(encParams
, kSecAsn1AlgorithmIDTemplate
, &algParams
);
1294 clErrorLog("CL_nssDecodeECDSASigAlgParams: error decoding CSSM_X509_ALGORITHM_IDENTIFIER\n");
1295 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT
);
1298 /* get the digest algorithm, convert to ECDSA w/digest OID */
1299 CSSM_ALGORITHMS digestAlg
= CL_oidToAlg(algParams
.algorithm
);
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
;
1312 clErrorLog("CL_nssDecodeECDSASigAlgParams: unknown digest algorithm\n");
1313 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT
);
1317 #pragma mark ----- Top-level Cert/CRL encode and decode -----
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).
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)
1336 /* BER-decode into temp memory */
1337 NSS_SignedCertOrCRL nssObj
;
1341 memset(&nssObj
, 0, sizeof(nssObj
));
1342 prtn
= coder
.decode(signedItem
.data(), signedItem
.length(),
1343 kSecAsn1SignedCertOrCRLTemplate
, &nssObj
);
1345 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT
);
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
);
1354 /* signature is a bit string which we do in fact decode */
1355 rawSig
.copy(nssObj
.signature
.Data
,
1356 (nssObj
.signature
.Length
+ 7) / 8);
1361 * Given pre-DER-encoded blobs, do the final encode step for a signed cert.
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
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
1380 prtn
= SecNssEncodeItemOdata(&nssObj
,
1381 kSecAsn1SignedCertOrCRLTemplate
,signedCert
);
1383 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR
);