2 * Copyright (c) 2000-2001 Apple Computer, 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.
20 * DecodedCert.cpp - object representing a snacc-decoded cert, with extensions
21 * parsed and decoded (still in snacc format).
23 * Created 9/1/2000 by Doug Mitchell.
24 * Copyright (c) 2000 by Apple Computer.
27 #include "DecodedCert.h"
28 #include "SnaccUtils.h"
29 #include "cldebugging.h"
30 #include "AppleX509CLSession.h"
31 #include "CSPAttacher.h"
32 #include <Security/cdsaUtils.h>
33 #include <Security/cssmapple.h>
35 DecodedCert::DecodedCert(
36 AppleX509CLSession
&session
)
37 : alloc(CssmAllocator::standard()),
40 certificateToSign
= new CertificateToSign
;
44 /* one-shot constructor, decoding from DER-encoded data */
45 DecodedCert::DecodedCert(
46 AppleX509CLSession
&session
,
47 const CssmData
&encodedCert
)
48 : alloc(CssmAllocator::standard()),
52 SC_decodeAsnObj(encodedCert
, *this);
54 mState
= CS_DecodedCert
;
57 DecodedCert::~DecodedCert()
59 /* free all extensions */
62 for(dex
=0; dex
<mNumExtensions
; dex
++) {
63 DecodedExten
*exten
= &mExtensions
[dex
];
65 delete exten
->snaccObj
;
67 alloc
.free(mExtensions
);
71 /* decode TBSCert and its extensions */
72 void DecodedCert::decodeTbs(
73 const CssmData
&encodedTbs
)
75 CASSERT(mState
== CS_Empty
);
76 CASSERT(certificateToSign
!= NULL
);
78 SC_decodeAsnObj(encodedTbs
, *certificateToSign
);
81 errorLog0("decodeTbs: tbs.BDec failure\n");
82 /* FIXME - leave in bad state? delete and clear? let's be cautious...*/
83 delete certificateToSign
;
84 certificateToSign
= new CertificateToSign
;
87 mState
= CS_DecodedTBS
;
91 * FIXME : how to determine max encoding size at run time!?
93 #define MAX_TEMPLATE_SIZE (8 * 1024)
95 /* encode TBS component; only called from CertCreateTemplate */
96 void DecodedCert::encodeTbs(
97 CssmOwnedData
&encodedTbs
)
100 CASSERT(mState
== CS_Building
);
101 if(certificateToSign
== NULL
) {
102 errorLog0("DecodedCert::encodeTbs: no TBS\n");
103 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR
);
106 /* enforce required fields - could go deeper, maybe we should */
107 if((certificateToSign
->signature
== NULL
) ||
108 (certificateToSign
->issuer
== NULL
) ||
109 (certificateToSign
->validity
== NULL
) ||
110 (certificateToSign
->subject
== NULL
) ||
111 (certificateToSign
->subjectPublicKeyInfo
== NULL
)) {
112 errorLog0("DecodedCert::encodeTbs: incomplete TBS\n");
113 /* an odd, undocumented error return */
114 CssmError::throwMe(CSSMERR_CL_NO_FIELD_VALUES
);
116 SC_encodeAsnObj(*certificateToSign
, encodedTbs
, MAX_TEMPLATE_SIZE
);
120 * Cook up CSSM_KEYUSE, gleaning as much as possible from
121 * (optional) extensions. If no applicable extensions available,
122 * we'll just return CSSM_KEYUSE_ANY.
124 * Note that the standard KeyUsage flags involving 'signing' translate
125 * to verify since we're only dealing with public keys.
127 CSSM_KEYUSE
DecodedCert::inferKeyUsage() const
129 CSSM_KEYUSE keyUse
= 0;
130 DecodedExten
*decodedExten
;
133 decodedExten
= findDecodedExt(id_ce_keyUsage
, false, 0, numFields
);
135 KeyUsage
*ku
= dynamic_cast<KeyUsage
*>(decodedExten
->snaccObj
);
137 errorLog0("inferKeyUsage: dynamic_cast failure(1)\n");
138 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR
);
140 if(ku
->GetBit(KeyUsage::digitalSignature
)) {
141 keyUse
|= CSSM_KEYUSE_VERIFY
;
143 if(ku
->GetBit(KeyUsage::nonRepudiation
)) {
144 keyUse
|= CSSM_KEYUSE_VERIFY
;
146 if(ku
->GetBit(KeyUsage::keyEncipherment
)) {
147 keyUse
|= CSSM_KEYUSE_WRAP
;
149 if(ku
->GetBit(KeyUsage::keyAgreement
)) {
150 keyUse
|= CSSM_KEYUSE_DERIVE
;
152 if(ku
->GetBit(KeyUsage::keyCertSign
)) {
153 keyUse
|= CSSM_KEYUSE_VERIFY
;
155 if(ku
->GetBit(KeyUsage::cRLSign
)) {
156 keyUse
|= CSSM_KEYUSE_VERIFY
;
158 if(ku
->GetBit(KeyUsage::dataEncipherment
)) {
159 keyUse
|= CSSM_KEYUSE_ENCRYPT
;
162 decodedExten
= findDecodedExt(id_ce_extKeyUsage
, false, 0, numFields
);
164 ExtKeyUsageSyntax
*eku
=
165 dynamic_cast<ExtKeyUsageSyntax
*>(decodedExten
->snaccObj
);
167 errorLog0("inferKeyUsage: dynamic_cast failure(2)\n");
168 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR
);
170 unsigned numOids
= eku
->Count();
171 eku
->SetCurrToFirst();
173 for(oidDex
=0; oidDex
<numOids
; oidDex
++) {
174 KeyPurposeId
*purp
= eku
->Curr();
175 if(*purp
== id_kp_codeSigning
) {
176 keyUse
|= CSSM_KEYUSE_VERIFY
;
178 /* I don't think the other purposes are useful... */
183 /* Nothing found; take the default. */
184 keyUse
= CSSM_KEYUSE_ANY
;
190 * Obtain a CSSM_KEY from a decoded cert, inferring as much as we can
191 * from required fields (subjectPublicKeyInfo) and extensions (for
194 CSSM_KEY_PTR
DecodedCert::extractCSSMKey(
195 CssmAllocator
&alloc
) const
197 CASSERT(certificateToSign
!= NULL
);
198 SubjectPublicKeyInfo
*snaccKeyInfo
= certificateToSign
->subjectPublicKeyInfo
;
199 if((snaccKeyInfo
== NULL
) ||
200 (snaccKeyInfo
->algorithm
== NULL
)) {
201 CssmError::throwMe(CSSMERR_CL_NO_FIELD_VALUES
);
203 CSSM_KEY_PTR cssmKey
= (CSSM_KEY_PTR
) alloc
.malloc(sizeof(CSSM_KEY
));
204 memset(cssmKey
, 0, sizeof(CSSM_KEY
));
205 CSSM_KEYHEADER
&hdr
= cssmKey
->KeyHeader
;
206 CssmRemoteData
keyData(alloc
, cssmKey
->KeyData
);
208 hdr
.HeaderVersion
= CSSM_KEYHEADER_VERSION
;
210 hdr
.BlobType
= CSSM_KEYBLOB_RAW
;
211 hdr
.AlgorithmId
= CL_snaccOidToCssmAlg(snaccKeyInfo
->algorithm
->algorithm
);
214 * Format inferred from AlgorithmId. I have never seen these defined
215 * anywhere, e.g., whart's the format of an RSA public key in a cert?
216 * X509 certainly doesn't say. However. the following two cases are known
219 switch(hdr
.AlgorithmId
) {
221 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_PKCS1
;
224 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_FIPS186
;
227 /* CSSM_KEYBLOB_RAW_FORMAT_NONE --> DER encoded */
228 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_NONE
;
232 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_NONE
;
234 hdr
.KeyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
236 /* KeyUsage inferred from extensions */
237 hdr
.KeyUsage
= inferKeyUsage();
239 /* start/end date unknown, leave zero */
240 hdr
.WrapAlgorithmId
= CSSM_ALGID_NONE
;
241 hdr
.WrapMode
= CSSM_ALGMODE_NONE
;
244 * subjectPublicKeyInfo.subjectPublicKey (AsnBits) ==> KeyData
246 SC_asnBitsToCssmData(snaccKeyInfo
->subjectPublicKey
, keyData
);
250 * LogicalKeySizeInBits - ask the CSP
252 CSSM_CSP_HANDLE cspHand
= getGlobalCspHand(true);
253 CSSM_KEY_SIZE keySize
;
255 crtn
= CSSM_QueryKeySizeInBits(cspHand
, NULL
, cssmKey
, &keySize
);
257 CssmError::throwMe(crtn
);
259 cssmKey
->KeyHeader
.LogicalKeySizeInBits
=
260 keySize
.LogicalKeySizeInBits
;
269 void DecodedCert::freeCSSMKey(
270 CSSM_KEY_PTR cssmKey
,
271 CssmAllocator
&alloc
,
274 if(cssmKey
== NULL
) {
277 alloc
.free(cssmKey
->KeyData
.Data
);
278 memset(cssmKey
, 0, sizeof(CSSM_KEY
));