]> git.saurik.com Git - apple/security.git/blob - AppleCSP/AppleCSP/AppleCSPContext.cpp
Security-179.tar.gz
[apple/security.git] / AppleCSP / AppleCSP / AppleCSPContext.cpp
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 // AppleCSPContext.cpp - CSP-wide contexts
21 //
22
23 #include "AppleCSPContext.h"
24 #include "AppleCSPSession.h"
25 #include "AppleCSPUtils.h"
26
27 /*
28 * Empty destructor (just to avoid out-of-line copies)
29 */
30 AppleCSPContext::~AppleCSPContext()
31 { }
32
33 /*
34 * get symmetric key bits - context.key can be either ref or raw.
35 * A convenience routine typically used by subclass's init().
36 */
37 void AppleCSPContext::symmetricKeyBits(
38 const Context &context,
39 CSSM_ALGORITHMS requiredAlg, // throws if this doesn't match key alg
40 CSSM_KEYUSE intendedUse, // throws if key usage doesn't match this
41 UInt8 *&keyBits, // RETURNED (not mallocd or copied)
42 UInt32 &keyLen) // RETURNED
43 {
44 /* key must be present and it must be a session key matching caller's spec */
45 CssmKey &key =
46 context.get<CssmKey>(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY);
47 if(key.keyClass() != CSSM_KEYCLASS_SESSION_KEY) {
48 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
49 }
50 if(key.algorithm() != requiredAlg) {
51 CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH);
52 }
53 cspValidateIntendedKeyUsage(&key.KeyHeader, intendedUse);
54 cspVerifyKeyTimes(key.KeyHeader);
55
56 /* extract raw bits one way or the other */
57 switch(key.blobType()) {
58 case CSSM_KEYBLOB_RAW:
59 /* easy case, the bits are right there in the CssmKey */
60 if(key.blobFormat() != CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING) {
61 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
62 }
63 keyLen = key.length();
64 keyBits = key.KeyData.Data;
65 break;
66
67 case CSSM_KEYBLOB_REFERENCE:
68 {
69 /* do a lookup to get a binary key */
70 BinaryKey &binKey = mSession.lookupRefKey(key);
71 /* fails if this is not a SymmetricBinaryKey */
72 SymmetricBinaryKey *symBinKey =
73 dynamic_cast<SymmetricBinaryKey *>(&binKey);
74 if(symBinKey == NULL) {
75 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
76 }
77 keyLen = symBinKey->mKeyData.Length;
78 keyBits = symBinKey->mKeyData.Data;
79 break;
80 }
81 default:
82 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
83 }
84 return;
85 }
86
87 // Called from subclass after it allocates its BinaryKeys.
88 // Caller frees BinaryKeys if we throw any exception.
89 void AppleKeyPairGenContext::generate(
90 const Context &context,
91 AppleCSPSession &session,
92 CssmKey &pubKey,
93 BinaryKey *pubBinKey,
94 CssmKey &privKey,
95 BinaryKey *privBinKey)
96 {
97 uint32 keySize;
98 cspKeyStorage privStorage;
99 cspKeyStorage pubStorage;
100 CssmKey::Header &pubHdr = pubKey.header();
101 CssmKey::Header &privHdr = privKey.header();
102
103 // validate context and key header args
104 pubStorage = cspParseKeyAttr(CKT_Public, pubHdr.KeyAttr);
105 privStorage = cspParseKeyAttr(CKT_Private, privHdr.KeyAttr);
106 cspValidateKeyUsageBits(CKT_Public, pubHdr.KeyUsage);
107 cspValidateKeyUsageBits(CKT_Private, privHdr.KeyUsage);
108
109 // have subclass generate the key pairs in the form of
110 // its native BinaryKeys
111 generate(context, *pubBinKey, *privBinKey, keySize);
112
113 // FIXME - Any other header setup?
114 pubHdr.LogicalKeySizeInBits =
115 privHdr.LogicalKeySizeInBits = keySize;
116 pubHdr.KeyAttr &= ~KEY_ATTR_RETURN_MASK;
117 privHdr.KeyAttr &= ~KEY_ATTR_RETURN_MASK;
118
119 // Handle key formatting. Delete the BinaryKeys if
120 // we're not creating ref keys, after safe completion of
121 // generateKeyBlob (which may throw, in which case the binary keys
122 // get deleted by our caller).
123 CSSM_KEYATTR_FLAGS attrFlags = 0;
124 switch(pubStorage) {
125 case CKS_Ref:
126 session.addRefKey(*pubBinKey, pubKey);
127 break;
128 case CKS_Data:
129 pubHdr.Format = requestedKeyFormat(context, pubKey);
130 pubBinKey->mKeyHeader = pubHdr;
131 pubBinKey->generateKeyBlob(
132 session.normAlloc(), // alloc in user space
133 CssmData::overlay(pubKey.KeyData),
134 pubHdr.Format,
135 session,
136 NULL, // no paramKey here!
137 attrFlags);
138 break;
139 case CKS_None:
140 break;
141 }
142 switch(privStorage) {
143 case CKS_Ref:
144 session.addRefKey(*privBinKey, privKey);
145 break;
146 case CKS_Data:
147 privHdr.Format = requestedKeyFormat(context, privKey);
148 privBinKey->mKeyHeader = privHdr;
149 privBinKey->generateKeyBlob(
150 session.normAlloc(), // alloc in user space
151 CssmData::overlay(privKey.KeyData),
152 privHdr.Format,
153 session,
154 NULL,
155 attrFlags);
156 break;
157 case CKS_None:
158 break;
159 }
160 if(pubStorage != CKS_Ref) {
161 delete pubBinKey;
162 }
163 if(privStorage != CKS_Ref) {
164 delete privBinKey;
165 }
166 }
167
168 /*
169 * Called from subclass's generate method. Subclass is also a
170 * AppleCSPContext.
171 */
172 void AppleSymmKeyGenContext::generateSymKey(
173 const Context &context,
174 AppleCSPSession &session, // for ref keys
175 CssmKey &cssmKey) // RETURNED
176 {
177 /* there really is no legal way this should throw... */
178 uint32 reqKeySize = context.getInt(
179 CSSM_ATTRIBUTE_KEY_LENGTH,
180 CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH);
181 if((reqKeySize < minSizeInBits) ||
182 (reqKeySize > maxSizeInBits)) {
183 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE);
184 }
185 if(mustBeByteSized) {
186 if((reqKeySize & 0x7) != 0) {
187 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE);
188 }
189 }
190
191 // validate KeyAtrr and KeyUsage already present in header
192 cspKeyStorage keyStorage;
193 CssmKey::Header &hdr = cssmKey.header();
194
195 keyStorage = cspParseKeyAttr(CKT_Session, hdr.KeyAttr);
196 cspValidateKeyUsageBits(CKT_Session, hdr.KeyUsage);
197 hdr.KeyAttr &= ~KEY_ATTR_RETURN_MASK;
198
199 hdr.LogicalKeySizeInBits = reqKeySize;
200 uint32 keySizeInBytes = (reqKeySize + 7) / 8;
201 SymmetricBinaryKey *binKey = NULL;
202 CssmData *keyData = NULL;
203
204 switch(keyStorage) {
205 case CKS_None:
206 /* no way */
207 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
208 case CKS_Ref:
209 /* cook up a symmetric binary key */
210 binKey = new SymmetricBinaryKey(reqKeySize);
211 keyData = &binKey->mKeyData;
212 break;
213 case CKS_Data:
214 /* key bytes --> caller's cssmKey */
215 keyData = &(CssmData::overlay(cssmKey.KeyData));
216 setUpCssmData(*keyData, keySizeInBytes,
217 session.normAlloc());
218 break;
219 }
220
221 // in any case, fill key bytes with random data
222 session.getRandomBytes(keySizeInBytes, keyData->Data);
223
224 if(keyStorage == CKS_Ref) {
225 session.addRefKey(*binKey, cssmKey);
226 }
227 else {
228 /* Raw data */
229 hdr.BlobType = CSSM_KEYBLOB_RAW;
230 hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
231 }
232
233 // FIXME - any other header fields?
234 }
235
236 //
237 // Symmetric Binary Key support
238 //
239 SymmetricBinaryKey::SymmetricBinaryKey(
240 unsigned keySizeInBits) :
241 mAllocator(CssmAllocator::standard(CssmAllocator::sensitive))
242 {
243 setUpCssmData(mKeyData, (keySizeInBits + 7) / 8, mAllocator);
244 }
245
246 SymmetricBinaryKey::~SymmetricBinaryKey()
247 {
248 freeCssmData(mKeyData, mAllocator);
249 }
250
251 void SymmetricBinaryKey::generateKeyBlob(
252 CssmAllocator &allocator,
253 CssmData &blob,
254 CSSM_KEYBLOB_FORMAT &format, // CSSM_KEYBLOB_RAW_FORMAT_PKCS1, etc.
255 AppleCSPSession &session,
256 const CssmKey *paramKey, /* optional, unused here */
257 CSSM_KEYATTR_FLAGS &attrFlags) /* IN/OUT */
258 {
259 switch(format) {
260 case CSSM_KEYBLOB_RAW_FORMAT_NONE: // default
261 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: // the one we can do
262 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: // same thing
263 break;
264 default:
265 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SYMMETRIC_KEY_FORMAT);
266 }
267 copyCssmData(mKeyData, blob, allocator);
268 format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
269 }
270