]> git.saurik.com Git - apple/security.git/blob - AppleCSP/AppleCSP/AppleCSPContext.cpp
0bccf35520cdf1bbf11fadffec8e2ad4578638d0
[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
55 /* extract raw bits one way or the other */
56 switch(key.blobType()) {
57 case CSSM_KEYBLOB_RAW:
58 /* easy case, the bits are right there in the CssmKey */
59 if(key.blobFormat() != CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING) {
60 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
61 }
62 keyLen = key.length();
63 keyBits = key.KeyData.Data;
64 break;
65
66 case CSSM_KEYBLOB_REFERENCE:
67 {
68 /* do a lookup to get a binary key */
69 BinaryKey &binKey = mSession.lookupRefKey(key);
70 /* fails if this is not a SymmetricBinaryKey */
71 SymmetricBinaryKey *symBinKey =
72 dynamic_cast<SymmetricBinaryKey *>(&binKey);
73 if(symBinKey == NULL) {
74 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
75 }
76 keyLen = symBinKey->mKeyData.Length;
77 keyBits = symBinKey->mKeyData.Data;
78 break;
79 }
80 default:
81 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
82 }
83 return;
84 }
85
86 // Called from subclass after it allocates its BinaryKeys.
87 // Caller frees BinaryKeys if we throw any exception.
88 void AppleKeyPairGenContext::generate(
89 const Context &context,
90 AppleCSPSession &session,
91 CssmKey &pubKey,
92 BinaryKey *pubBinKey,
93 CssmKey &privKey,
94 BinaryKey *privBinKey)
95 {
96 uint32 keySize;
97 cspKeyStorage privStorage;
98 cspKeyStorage pubStorage;
99 CssmKey::Header &pubHdr = pubKey.header();
100 CssmKey::Header &privHdr = privKey.header();
101
102 // validate context and key header args
103 pubStorage = cspParseKeyAttr(CKT_Public, pubHdr.KeyAttr);
104 privStorage = cspParseKeyAttr(CKT_Private, privHdr.KeyAttr);
105 cspValidateKeyUsageBits(CKT_Public, pubHdr.KeyUsage);
106 cspValidateKeyUsageBits(CKT_Private, privHdr.KeyUsage);
107
108 // have subclass generate the key pairs in the form of
109 // its native BinaryKeys
110 generate(context, *pubBinKey, *privBinKey, keySize);
111
112 // FIXME - Any other header setup?
113 pubHdr.LogicalKeySizeInBits =
114 privHdr.LogicalKeySizeInBits = keySize;
115 pubHdr.KeyAttr &= ~KEY_ATTR_RETURN_MASK;
116 privHdr.KeyAttr &= ~KEY_ATTR_RETURN_MASK;
117
118 // Handle key formatting. Delete the BinaryKeys if
119 // we're not creating ref keys.
120 switch(pubStorage) {
121 case CKS_Ref:
122 session.addRefKey(*pubBinKey, pubKey);
123 break;
124 case CKS_Data:
125 pubHdr.Format = requestedKeyFormat(context, pubKey);
126 pubBinKey->mKeyHeader = pubHdr;
127 pubBinKey->generateKeyBlob(
128 session.normAlloc(), // alloc in user space
129 CssmData::overlay(pubKey.KeyData),
130 pubHdr.Format);
131 delete pubBinKey;
132 break;
133 case CKS_None:
134 delete pubBinKey;
135 break;
136 }
137 switch(privStorage) {
138 case CKS_Ref:
139 session.addRefKey(*privBinKey, privKey);
140 break;
141 case CKS_Data:
142 privHdr.Format = requestedKeyFormat(context, privKey);
143 privBinKey->mKeyHeader = privHdr;
144 privBinKey->generateKeyBlob(
145 session.normAlloc(), // alloc in user space
146 CssmData::overlay(privKey.KeyData),
147 privHdr.Format);
148 delete privBinKey;
149 break;
150 case CKS_None:
151 delete privBinKey;
152 break;
153 }
154 }
155
156 /*
157 * Called from subclass's generate method. Subclass is also a
158 * AppleCSPContext.
159 */
160 void AppleSymmKeyGenContext::generateSymKey(
161 const Context &context,
162 AppleCSPSession &session, // for ref keys
163 CssmKey &cssmKey) // RETURNED
164 {
165 /* there really is no legal way this should throw... */
166 uint32 reqKeySize = context.getInt(
167 CSSM_ATTRIBUTE_KEY_LENGTH,
168 CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH);
169 if((reqKeySize < minSizeInBits) ||
170 (reqKeySize > maxSizeInBits)) {
171 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE);
172 }
173 if(mustBeByteSized) {
174 if((reqKeySize & 0x7) != 0) {
175 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE);
176 }
177 }
178
179 // validate KeyAtrr and KeyUsage already present in header
180 cspKeyStorage keyStorage;
181 CssmKey::Header &hdr = cssmKey.header();
182
183 keyStorage = cspParseKeyAttr(CKT_Session, hdr.KeyAttr);
184 cspValidateKeyUsageBits(CKT_Session, hdr.KeyUsage);
185 hdr.KeyAttr &= ~KEY_ATTR_RETURN_MASK;
186
187 hdr.LogicalKeySizeInBits = reqKeySize;
188 uint32 keySizeInBytes = (reqKeySize + 7) / 8;
189 SymmetricBinaryKey *binKey = NULL;
190 CssmData *keyData = NULL;
191
192 switch(keyStorage) {
193 case CKS_None:
194 /* no way */
195 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
196 case CKS_Ref:
197 /* cook up a symmetric binary key */
198 binKey = new SymmetricBinaryKey(reqKeySize);
199 keyData = &binKey->mKeyData;
200 break;
201 case CKS_Data:
202 /* key bytes --> caller's cssmKey */
203 keyData = &(CssmData::overlay(cssmKey.KeyData));
204 setUpCssmData(*keyData, keySizeInBytes,
205 session.normAlloc());
206 break;
207 }
208
209 // in any case, fill key bytes with random data
210 session.getRandomBytes(keySizeInBytes, keyData->Data);
211
212 if(keyStorage == CKS_Ref) {
213 session.addRefKey(*binKey, cssmKey);
214 }
215 else {
216 /* Raw data */
217 hdr.BlobType = CSSM_KEYBLOB_RAW;
218 hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
219 }
220
221 // FIXME - any other header fields?
222 }
223
224 //
225 // Symmetric Binary Key support
226 //
227 SymmetricBinaryKey::SymmetricBinaryKey(
228 unsigned keySizeInBits) :
229 mAllocator(CssmAllocator::standard(CssmAllocator::sensitive))
230 {
231 setUpCssmData(mKeyData, (keySizeInBits + 7) / 8, mAllocator);
232 }
233
234 SymmetricBinaryKey::~SymmetricBinaryKey()
235 {
236 freeCssmData(mKeyData, mAllocator);
237 }
238
239 void SymmetricBinaryKey::generateKeyBlob(
240 CssmAllocator &allocator,
241 CssmData &blob,
242 CSSM_KEYBLOB_FORMAT &format) // CSSM_KEYBLOB_RAW_FORMAT_PKCS1, etc.
243 {
244 switch(format) {
245 case CSSM_KEYBLOB_RAW_FORMAT_NONE: // default
246 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: // the one we can do
247 break;
248 default:
249 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SYMMETRIC_KEY_FORMAT);
250 }
251 copyCssmData(mKeyData, blob, allocator);
252 format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
253 }
254