]> git.saurik.com Git - apple/security.git/blame - AppleX509CL/DecodedCert.cpp
Security-177.tar.gz
[apple/security.git] / AppleX509CL / DecodedCert.cpp
CommitLineData
bac41a7b
A
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/*
df0e469f
A
20 * DecodedCert.cpp - object representing a decoded cert, in NSS
21 * format, with extensions parsed and decoded (still in NSS format).
bac41a7b
A
22 *
23 * Created 9/1/2000 by Doug Mitchell.
24 * Copyright (c) 2000 by Apple Computer.
25 */
26
27#include "DecodedCert.h"
df0e469f 28#include "clNssUtils.h"
bac41a7b
A
29#include "cldebugging.h"
30#include "AppleX509CLSession.h"
31#include "CSPAttacher.h"
bac41a7b 32#include <Security/cssmapple.h>
df0e469f
A
33#include <Security/oidscert.h>
34// ??? #include "clExtensionTemplates.h"
bac41a7b
A
35
36DecodedCert::DecodedCert(
37 AppleX509CLSession &session)
df0e469f 38 : DecodedItem(session)
bac41a7b 39{
df0e469f 40 memset(&mCert, 0, sizeof(mCert));
bac41a7b
A
41}
42
43/* one-shot constructor, decoding from DER-encoded data */
44DecodedCert::DecodedCert(
45 AppleX509CLSession &session,
46 const CssmData &encodedCert)
df0e469f 47 : DecodedItem(session)
bac41a7b 48{
df0e469f
A
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;
bac41a7b
A
57}
58
59DecodedCert::~DecodedCert()
60{
bac41a7b
A
61}
62
63/* decode TBSCert and its extensions */
64void DecodedCert::decodeTbs(
65 const CssmData &encodedTbs)
66{
df0e469f
A
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);
bac41a7b 74 }
df0e469f
A
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;
bac41a7b 88 }
df0e469f 89 mDecodedExtensions.encodeToNss(tbs.extensions);
bac41a7b
A
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();
df0e469f
A
102 assert(mState == IS_Building);
103
bac41a7b 104 /* enforce required fields - could go deeper, maybe we should */
df0e469f
A
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");
bac41a7b
A
111 /* an odd, undocumented error return */
112 CssmError::throwMe(CSSMERR_CL_NO_FIELD_VALUES);
113 }
df0e469f
A
114
115 PRErrorCode prtn;
116 prtn = SecNssEncodeItemOdata(&tbs, NSS_TBSCertificateTemplate,
117 encodedTbs);
118 if(prtn) {
119 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
120 }
bac41a7b
A
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;
df0e469f 134 const DecodedExten *decodedExten;
bac41a7b
A
135 uint32 numFields;
136
df0e469f
A
137 /* Basic KeyUsage */
138 decodedExten = DecodedItem::findDecodedExt(CSSMOID_KeyUsage, false,
139 0, numFields);
bac41a7b 140 if(decodedExten) {
df0e469f
A
141 CSSM_DATA *ku = (CSSM_DATA *)decodedExten->nssObj();
142 assert(ku != NULL);
143 CE_KeyUsage kuse = clBitStringToKeyUsage(*ku);
144 if(kuse & CE_KU_DigitalSignature) {
bac41a7b
A
145 keyUse |= CSSM_KEYUSE_VERIFY;
146 }
df0e469f 147 if(kuse & CE_KU_NonRepudiation) {
bac41a7b
A
148 keyUse |= CSSM_KEYUSE_VERIFY;
149 }
df0e469f 150 if(kuse & CE_KU_KeyEncipherment) {
bac41a7b
A
151 keyUse |= CSSM_KEYUSE_WRAP;
152 }
df0e469f 153 if(kuse & CE_KU_KeyAgreement) {
bac41a7b
A
154 keyUse |= CSSM_KEYUSE_DERIVE;
155 }
df0e469f 156 if(kuse & CE_KU_KeyCertSign) {
bac41a7b
A
157 keyUse |= CSSM_KEYUSE_VERIFY;
158 }
df0e469f 159 if(kuse & CE_KU_CRLSign) {
bac41a7b
A
160 keyUse |= CSSM_KEYUSE_VERIFY;
161 }
df0e469f 162 if(kuse & CE_KU_DataEncipherment) {
bac41a7b
A
163 keyUse |= CSSM_KEYUSE_ENCRYPT;
164 }
165 }
df0e469f
A
166
167 /* Extended key usage */
168 decodedExten = DecodedItem::findDecodedExt(CSSMOID_ExtendedKeyUsage,
169 false, 0, numFields);
bac41a7b 170 if(decodedExten) {
df0e469f
A
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;
bac41a7b 199 }
bac41a7b
A
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{
df0e469f
A
217 const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &keyInfo =
218 mCert.tbs.subjectPublicKeyInfo;
219 return CL_extractCSSMKeyNSS(keyInfo, alloc, this);
bac41a7b
A
220}
221