]> git.saurik.com Git - apple/security.git/blame - AppleX509CL/DecodedCert.cpp
Security-54.1.9.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/*
20 * DecodedCert.cpp - object representing a snacc-decoded cert, with extensions
21 * parsed and decoded (still in snacc 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 "SnaccUtils.h"
29#include "cldebugging.h"
30#include "AppleX509CLSession.h"
31#include "CSPAttacher.h"
32#include <Security/cdsaUtils.h>
33#include <Security/cssmapple.h>
34
35DecodedCert::DecodedCert(
36 AppleX509CLSession &session)
29654253 37 : alloc(session),
bac41a7b
A
38 mSession(session)
39{
40 certificateToSign = new CertificateToSign;
41 reset();
42}
43
44/* one-shot constructor, decoding from DER-encoded data */
45DecodedCert::DecodedCert(
46 AppleX509CLSession &session,
47 const CssmData &encodedCert)
29654253 48 : alloc(session),
bac41a7b
A
49 mSession(session)
50{
51 reset();
52 SC_decodeAsnObj(encodedCert, *this);
53 decodeExtensions();
54 mState = CS_DecodedCert;
55}
56
57DecodedCert::~DecodedCert()
58{
59 /* free all extensions */
60 unsigned dex;
61
62 for(dex=0; dex<mNumExtensions; dex++) {
63 DecodedExten *exten = &mExtensions[dex];
64 delete exten->extnId;
65 delete exten->snaccObj;
66 }
67 alloc.free(mExtensions);
68 reset();
69}
70
71/* decode TBSCert and its extensions */
72void DecodedCert::decodeTbs(
73 const CssmData &encodedTbs)
74{
75 CASSERT(mState == CS_Empty);
76 CASSERT(certificateToSign != NULL);
77 try {
78 SC_decodeAsnObj(encodedTbs, *certificateToSign);
79 }
80 catch (...) {
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;
85 }
86 decodeExtensions();
87 mState = CS_DecodedTBS;
88}
89
90/*
91 * FIXME : how to determine max encoding size at run time!?
92 */
93#define MAX_TEMPLATE_SIZE (8 * 1024)
94
95/* encode TBS component; only called from CertCreateTemplate */
96void DecodedCert::encodeTbs(
97 CssmOwnedData &encodedTbs)
98{
99 encodeExtensions();
100 CASSERT(mState == CS_Building);
101 if(certificateToSign == NULL) {
102 errorLog0("DecodedCert::encodeTbs: no TBS\n");
103 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
104 }
105
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);
115 }
116 SC_encodeAsnObj(*certificateToSign, encodedTbs, MAX_TEMPLATE_SIZE);
117}
118
119/*
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.
123 *
124 * Note that the standard KeyUsage flags involving 'signing' translate
125 * to verify since we're only dealing with public keys.
126 */
127CSSM_KEYUSE DecodedCert::inferKeyUsage() const
128{
129 CSSM_KEYUSE keyUse = 0;
130 DecodedExten *decodedExten;
131 uint32 numFields;
132
133 decodedExten = findDecodedExt(id_ce_keyUsage, false, 0, numFields);
134 if(decodedExten) {
135 KeyUsage *ku = dynamic_cast<KeyUsage *>(decodedExten->snaccObj);
136 if(ku == NULL) {
137 errorLog0("inferKeyUsage: dynamic_cast failure(1)\n");
138 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
139 }
140 if(ku->GetBit(KeyUsage::digitalSignature)) {
141 keyUse |= CSSM_KEYUSE_VERIFY;
142 }
143 if(ku->GetBit(KeyUsage::nonRepudiation)) {
144 keyUse |= CSSM_KEYUSE_VERIFY;
145 }
146 if(ku->GetBit(KeyUsage::keyEncipherment)) {
147 keyUse |= CSSM_KEYUSE_WRAP;
148 }
149 if(ku->GetBit(KeyUsage::keyAgreement)) {
150 keyUse |= CSSM_KEYUSE_DERIVE;
151 }
152 if(ku->GetBit(KeyUsage::keyCertSign)) {
153 keyUse |= CSSM_KEYUSE_VERIFY;
154 }
155 if(ku->GetBit(KeyUsage::cRLSign)) {
156 keyUse |= CSSM_KEYUSE_VERIFY;
157 }
158 if(ku->GetBit(KeyUsage::dataEncipherment)) {
159 keyUse |= CSSM_KEYUSE_ENCRYPT;
160 }
161 }
162 decodedExten = findDecodedExt(id_ce_extKeyUsage, false, 0, numFields);
163 if(decodedExten) {
164 ExtKeyUsageSyntax *eku =
165 dynamic_cast<ExtKeyUsageSyntax *>(decodedExten->snaccObj);
166 if(eku == NULL) {
167 errorLog0("inferKeyUsage: dynamic_cast failure(2)\n");
168 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
169 }
170 unsigned numOids = eku->Count();
171 eku->SetCurrToFirst();
172 unsigned oidDex;
173 for(oidDex=0; oidDex<numOids; oidDex++) {
174 KeyPurposeId *purp = eku->Curr();
175 if(*purp == id_kp_codeSigning) {
176 keyUse |= CSSM_KEYUSE_VERIFY;
177 }
178 /* I don't think the other purposes are useful... */
179 eku->GoNext();
180 }
181 }
182 if(keyUse == 0) {
183 /* Nothing found; take the default. */
184 keyUse = CSSM_KEYUSE_ANY;
185 }
186 return keyUse;
187}
188
189/*
190 * Obtain a CSSM_KEY from a decoded cert, inferring as much as we can
191 * from required fields (subjectPublicKeyInfo) and extensions (for
192 * KeyUse).
193 */
194CSSM_KEY_PTR DecodedCert::extractCSSMKey(
195 CssmAllocator &alloc) const
196{
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);
202 }
29654253 203 return CL_extractCSSMKey(*snaccKeyInfo, alloc, this);
bac41a7b
A
204}
205