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