]> git.saurik.com Git - apple/security.git/blame_incremental - AppleX509CL/DecodedCert.cpp
Security-177.tar.gz
[apple/security.git] / AppleX509CL / DecodedCert.cpp
... / ...
CommitLineData
1/*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19/*
20 * DecodedCert.cpp - object representing a decoded cert, in NSS
21 * format, with extensions parsed and decoded (still in NSS format).
22 *
23 * Created 9/1/2000 by Doug Mitchell.
24 * Copyright (c) 2000 by Apple Computer.
25 */
26
27#include "DecodedCert.h"
28#include "clNssUtils.h"
29#include "cldebugging.h"
30#include "AppleX509CLSession.h"
31#include "CSPAttacher.h"
32#include <Security/cssmapple.h>
33#include <Security/oidscert.h>
34// ??? #include "clExtensionTemplates.h"
35
36DecodedCert::DecodedCert(
37 AppleX509CLSession &session)
38 : DecodedItem(session)
39{
40 memset(&mCert, 0, sizeof(mCert));
41}
42
43/* one-shot constructor, decoding from DER-encoded data */
44DecodedCert::DecodedCert(
45 AppleX509CLSession &session,
46 const CssmData &encodedCert)
47 : DecodedItem(session)
48{
49 memset(&mCert, 0, sizeof(mCert));
50 PRErrorCode prtn = mCoder.decode(encodedCert.data(), encodedCert.length(),
51 NSS_SignedCertTemplate, &mCert);
52 if(prtn) {
53 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
54 }
55 mDecodedExtensions.decodeFromNss(mCert.tbs.extensions);
56 mState = IS_DecodedAll;
57}
58
59DecodedCert::~DecodedCert()
60{
61}
62
63/* decode TBSCert and its extensions */
64void DecodedCert::decodeTbs(
65 const CssmData &encodedTbs)
66{
67 assert(mState == IS_Empty);
68
69 memset(&mCert, 0, sizeof(mCert));
70 PRErrorCode prtn = mCoder.decode(encodedTbs.data(), encodedTbs.length(),
71 NSS_TBSCertificateTemplate, &mCert.tbs);
72 if(prtn) {
73 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
74 }
75 mDecodedExtensions.decodeFromNss(mCert.tbs.extensions);
76 mState = IS_DecodedTBS;
77}
78
79void DecodedCert::encodeExtensions()
80{
81 NSS_TBSCertificate &tbs = mCert.tbs;
82 assert(mState == IS_Building);
83 assert(tbs.extensions == NULL);
84
85 if(mDecodedExtensions.numExtensions() == 0) {
86 /* no extensions, no error */
87 return;
88 }
89 mDecodedExtensions.encodeToNss(tbs.extensions);
90}
91
92/*
93 * FIXME : how to determine max encoding size at run time!?
94 */
95#define MAX_TEMPLATE_SIZE (8 * 1024)
96
97/* encode TBS component; only called from CertCreateTemplate */
98void DecodedCert::encodeTbs(
99 CssmOwnedData &encodedTbs)
100{
101 encodeExtensions();
102 assert(mState == IS_Building);
103
104 /* enforce required fields - could go deeper, maybe we should */
105 NSS_TBSCertificate &tbs = mCert.tbs;
106 if((tbs.signature.algorithm.Data == NULL) ||
107 (tbs.issuer.rdns == NULL) ||
108 (tbs.subject.rdns == NULL) ||
109 (tbs.subjectPublicKeyInfo.subjectPublicKey.Data == NULL)) {
110 clErrorLog("DecodedCert::encodeTbs: incomplete TBS");
111 /* an odd, undocumented error return */
112 CssmError::throwMe(CSSMERR_CL_NO_FIELD_VALUES);
113 }
114
115 PRErrorCode prtn;
116 prtn = SecNssEncodeItemOdata(&tbs, NSS_TBSCertificateTemplate,
117 encodedTbs);
118 if(prtn) {
119 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
120 }
121}
122
123/*
124 * Cook up CSSM_KEYUSE, gleaning as much as possible from
125 * (optional) extensions. If no applicable extensions available,
126 * we'll just return CSSM_KEYUSE_ANY.
127 *
128 * Note that the standard KeyUsage flags involving 'signing' translate
129 * to verify since we're only dealing with public keys.
130 */
131CSSM_KEYUSE DecodedCert::inferKeyUsage() const
132{
133 CSSM_KEYUSE keyUse = 0;
134 const DecodedExten *decodedExten;
135 uint32 numFields;
136
137 /* Basic KeyUsage */
138 decodedExten = DecodedItem::findDecodedExt(CSSMOID_KeyUsage, false,
139 0, numFields);
140 if(decodedExten) {
141 CSSM_DATA *ku = (CSSM_DATA *)decodedExten->nssObj();
142 assert(ku != NULL);
143 CE_KeyUsage kuse = clBitStringToKeyUsage(*ku);
144 if(kuse & CE_KU_DigitalSignature) {
145 keyUse |= CSSM_KEYUSE_VERIFY;
146 }
147 if(kuse & CE_KU_NonRepudiation) {
148 keyUse |= CSSM_KEYUSE_VERIFY;
149 }
150 if(kuse & CE_KU_KeyEncipherment) {
151 keyUse |= CSSM_KEYUSE_WRAP;
152 }
153 if(kuse & CE_KU_KeyAgreement) {
154 keyUse |= CSSM_KEYUSE_DERIVE;
155 }
156 if(kuse & CE_KU_KeyCertSign) {
157 keyUse |= CSSM_KEYUSE_VERIFY;
158 }
159 if(kuse & CE_KU_CRLSign) {
160 keyUse |= CSSM_KEYUSE_VERIFY;
161 }
162 if(kuse & CE_KU_DataEncipherment) {
163 keyUse |= CSSM_KEYUSE_ENCRYPT;
164 }
165 }
166
167 /* Extended key usage */
168 decodedExten = DecodedItem::findDecodedExt(CSSMOID_ExtendedKeyUsage,
169 false, 0, numFields);
170 if(decodedExten) {
171 NSS_ExtKeyUsage *euse = (NSS_ExtKeyUsage *)decodedExten->nssObj();
172 assert(euse != NULL);
173 unsigned numUses = clNssArraySize((const void **)euse->purposes);
174 for(unsigned dex=0; dex<numUses; dex++) {
175 const CSSM_OID *thisUse = euse->purposes[dex];
176 if(clCompareCssmData(thisUse, &CSSMOID_ExtendedKeyUsageAny)) {
177 /* we're done */
178 keyUse = CSSM_KEYUSE_ANY;
179 break;
180 }
181 else if(clCompareCssmData(thisUse, &CSSMOID_ServerAuth)) {
182 keyUse |= (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_ENCRYPT);
183 }
184 else if(clCompareCssmData(thisUse, &CSSMOID_ClientAuth)) {
185 keyUse |= (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_ENCRYPT);
186 }
187 else if(clCompareCssmData(thisUse, &CSSMOID_ExtendedUseCodeSigning)) {
188 keyUse |= CSSM_KEYUSE_VERIFY;
189 }
190 else if(clCompareCssmData(thisUse, &CSSMOID_EmailProtection)) {
191 keyUse |=
192 (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP | CSSM_KEYUSE_DERIVE);
193 }
194 else if(clCompareCssmData(thisUse, &CSSMOID_TimeStamping)) {
195 keyUse |= CSSM_KEYUSE_VERIFY;
196 }
197 else if(clCompareCssmData(thisUse, &CSSMOID_OCSPSigning)) {
198 keyUse |= CSSM_KEYUSE_VERIFY;
199 }
200 }
201 }
202 if(keyUse == 0) {
203 /* Nothing found; take the default. */
204 keyUse = CSSM_KEYUSE_ANY;
205 }
206 return keyUse;
207}
208
209/*
210 * Obtain a CSSM_KEY from a decoded cert, inferring as much as we can
211 * from required fields (subjectPublicKeyInfo) and extensions (for
212 * KeyUse).
213 */
214CSSM_KEY_PTR DecodedCert::extractCSSMKey(
215 CssmAllocator &alloc) const
216{
217 const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &keyInfo =
218 mCert.tbs.subjectPublicKeyInfo;
219 return CL_extractCSSMKeyNSS(keyInfo, alloc, this);
220}
221