]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSUserKeygen.c
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSUserKeygen.c
1 /*
2 * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #include <Security/SecureObjectSync/SOSUserKeygen.h>
26 #include <stdio.h>
27 #include <corecrypto/ccrng.h>
28 #include <corecrypto/ccrng_pbkdf2_prng.h>
29 #include <corecrypto/ccec.h>
30 #include <corecrypto/ccdigest.h>
31 #include <corecrypto/ccsha2.h>
32 #include <CommonCrypto/CommonRandomSPI.h>
33 #include <Security/SecKey.h>
34 #include <Security/SecKeyPriv.h>
35 #include <Security/SecFramework.h>
36 #include <utilities/SecCFWrappers.h>
37 #include <utilities/SecCFRelease.h>
38 #include <utilities/debugging.h>
39 #include <Security/SecureObjectSync/SOSCloudCircle.h>
40 #include <Security/SecureObjectSync/SOSInternal.h>
41 #include <Security/SecureObjectSync/SOSAccount.h>
42 #include <Security/SecFramework.h>
43 #include <Security/SecItem.h>
44 #include <utilities/der_plist.h>
45 #include <utilities/der_plist_internal.h>
46
47 #include <corecrypto/ccder.h>
48 #include <Security/oidsalg.h>
49
50 // A.2 PBKDF2
51 //
52 // The object identifier id-PBKDF2 identifies the PBKDF2 key derivation
53 // function (Section 5.2).
54 //
55 // id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12}
56 //
57 // The parameters field associated with this OID in an
58 // AlgorithmIdentifier shall have type PBKDF2-params:
59 //
60 // PBKDF2-params ::= SEQUENCE {
61 // salt CHOICE {
62 // specified OCTET STRING,
63 // otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}}
64 // },
65 // iterationCount INTEGER (1..MAX),
66 // keyLength INTEGER (1..MAX) OPTIONAL,
67 // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT
68 // algid-hmacWithSHA1 }
69 //
70 // The fields of type PKDF2-params have the following meanings:
71
72
73 static size_t der_sizeof_SecAsn1Oid(const SecAsn1Oid* secasn_oid)
74 {
75 return ccder_sizeof(CCDER_OBJECT_IDENTIFIER, secasn_oid->Length);
76 }
77
78 static uint8_t *der_encode_SecAsn1Oid(const SecAsn1Oid* secasn_oid, const uint8_t *der, uint8_t *der_end)
79 {
80 return ccder_encode_tl(CCDER_OBJECT_IDENTIFIER, secasn_oid->Length, der,
81 ccder_encode_body(secasn_oid->Length, secasn_oid->Data, der, der_end));
82 }
83
84 static const uint8_t *der_expect_SecAsn1Oid(const SecAsn1Oid* secasn_oid, const uint8_t *der, const uint8_t *der_end)
85 {
86 size_t len = 0;
87 der = ccder_decode_tl(CCDER_OBJECT_IDENTIFIER, &len,
88 der, der_end);
89
90 if (secasn_oid->Length != len || memcmp(secasn_oid->Data, der, len) != 0)
91 der = NULL;
92 else
93 der += len;
94
95 return der;
96 }
97
98 static size_t der_sizeof_pbkdf2_params(size_t saltLen, const uint8_t *salt,
99 unsigned long iterationCount,
100 unsigned long keyLength)
101 {
102 size_t body_size = ccder_sizeof_raw_octet_string(saltLen)
103 + ccder_sizeof_uint64(iterationCount)
104 + ccder_sizeof_uint64(keyLength)
105 + der_sizeof_SecAsn1Oid(&CSSMOID_PKCS5_HMAC_SHA1);
106
107 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, body_size);
108 }
109
110 static uint8_t *der_encode_pbkdf2_params(size_t saltLen, const uint8_t *salt,
111 unsigned long iterationCount,
112 unsigned long keyLength,
113 const uint8_t *der, uint8_t *der_end)
114 {
115 uint8_t* original_der_end = der_end;
116
117 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, original_der_end, der,
118 ccder_encode_raw_octet_string(saltLen, salt, der,
119 ccder_encode_uint64(iterationCount, der,
120 ccder_encode_uint64(keyLength, der,
121 der_encode_SecAsn1Oid(&CSSMOID_PKCS5_HMAC_SHA1, der, der_end)))));
122 }
123
124 static const uint8_t *der_decode_pbkdf2_params(size_t *saltLen, const uint8_t **salt,
125 unsigned long *iterationCount,
126 unsigned long *keyLength,
127 const uint8_t *der, const uint8_t *der_end)
128 {
129 const uint8_t * body_end = NULL;
130 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &body_end, der, der_end);
131
132 if (body_end != der_end)
133 der = NULL;
134
135 size_t salt_size = 0;
136 const uint8_t *salt_bytes = NULL;
137
138 der = ccder_decode_tl(CCDER_OCTET_STRING, &salt_size, der, body_end);
139 salt_bytes = der;
140 der += salt_size;
141
142 uint64_t iteration_count = 0;
143 uint64_t key_len = 0;
144 der = ccder_decode_uint64(&iteration_count, der, body_end);
145 if (iteration_count > UINT32_MAX)
146 der = NULL;
147
148 der = ccder_decode_uint64(&key_len, der, body_end);
149 if (key_len > UINT32_MAX)
150 der = NULL;
151
152 der = der_expect_SecAsn1Oid(&CSSMOID_PKCS5_HMAC_SHA1, der, body_end);
153
154 if (der) {
155 if (salt)
156 *salt = salt_bytes;
157 if (saltLen)
158 *saltLen = salt_size;
159 if (iterationCount)
160 *iterationCount = (unsigned long)iteration_count;
161 if (keyLength)
162 *keyLength = (unsigned long) key_len;
163 }
164
165 return der;
166 }
167
168
169 static SecKeyRef ccec2SecKey(ccec_full_ctx_t fk)
170 {
171 size_t export_size = ccec_x963_export_size(1, fk);
172 uint8_t export_keybytes[export_size];
173 ccec_x963_export(1, export_keybytes, fk);
174 CFDataRef exportedkey = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, export_keybytes, export_size, kCFAllocatorNull);
175
176 CFDictionaryRef keyattributes = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
177 kSecValueData, exportedkey,
178 kSecAttrKeyType, kSecAttrKeyTypeEC,
179 kSecAttrKeyClass, kSecAttrKeyClassPrivate,
180 NULL);
181
182 SecKeyRef retval = SecKeyCreateFromAttributeDictionary(keyattributes);
183
184 CFRelease(keyattributes);
185 CFRelease(exportedkey);
186 bzero(export_keybytes, 0);
187 return retval;
188 }
189
190 #define SALTMAX 16
191 #define ITERATIONMIN 50000
192
193 CFDataRef SOSUserKeyCreateGenerateParameters(CFErrorRef *error) {
194 size_t saltlen = SALTMAX;
195 uint8_t salt[saltlen];
196
197 size_t iterations = ITERATIONMIN;
198 size_t keysize = 256;
199
200 if(CCRandomCopyBytes(kCCRandomDefault, salt, sizeof(salt)) != kCCSuccess) {
201 SOSCreateError(kSOSErrorProcessingFailure, CFSTR("CCRandomCopyBytes failed"), NULL, error);
202 return NULL;
203 }
204
205 CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0);
206 CFDataSetLength(result, der_sizeof_pbkdf2_params(saltlen, salt, iterations, keysize));
207
208 uint8_t * encode = der_encode_pbkdf2_params(saltlen, salt, iterations, keysize,
209 CFDataGetBytePtr(result),
210 CFDataGetMutableBytePtr(result) + CFDataGetLength(result));
211
212 if (!encode)
213 CFReleaseNull(result);
214
215 if (result) {
216 secnotice("keygen", "Created new parameters: iterations %zd, keysize %zd: %@", iterations, keysize, result);
217 }
218
219 return result;
220 }
221
222 SecKeyRef SOSUserKeygen(CFDataRef password, CFDataRef parameters, CFErrorRef *error)
223 {
224 size_t saltlen;
225 const uint8_t *salt = NULL;
226
227 size_t iterations = 0;
228 size_t keysize = 0;
229
230 const uint8_t *der = CFDataGetBytePtr(parameters);
231 const uint8_t *der_end = der + CFDataGetLength(parameters);
232
233 der = der_decode_pbkdf2_params(&saltlen, &salt, &iterations, &keysize, der, der_end);
234
235 if (der == NULL) {
236 SOSCreateErrorWithFormat(kSOSErrorDecodeFailure, NULL, error, NULL,
237 CFSTR("Bad paramter encoding, got: %@"), parameters);
238 return NULL;
239 }
240 if (keysize != 256) {
241 SOSCreateErrorWithFormat(kSOSErrorUnsupported, NULL, error, NULL,
242 CFSTR("Key size not supported, requested %zd."), keysize);
243 return NULL;
244 }
245 if (saltlen < 4) {
246 SOSCreateErrorWithFormat(kSOSErrorUnsupported, NULL, error, NULL,
247 CFSTR("Salt length not supported, requested %zd."), saltlen);
248 return NULL;
249 }
250 if (iterations < ITERATIONMIN) {
251 SOSCreateErrorWithFormat(kSOSErrorUnsupported, NULL, error, NULL,
252 CFSTR("Too few iterations, params suggested %zd."), iterations);
253 return NULL;
254 }
255
256 debugDumpUserParameters(CFSTR("params-keygen"), parameters);
257
258
259 const uint8_t *password_bytes = CFDataGetBytePtr(password);
260 size_t password_length = CFDataGetLength(password);
261
262 const size_t maxbytes = 128;
263
264 ccec_const_cp_t cp = ccec_get_cp(keysize);
265 struct ccrng_pbkdf2_prng_state pbkdf2_prng;
266
267 ccec_full_ctx_decl_cp(cp, tmpkey);
268
269 secnotice("keygen", "Generating key for: iterations %zd, keysize %zd: %@", iterations, keysize, parameters);
270
271 if (ccrng_pbkdf2_prng_init(&pbkdf2_prng, maxbytes,
272 password_length, password_bytes,
273 saltlen, salt,
274 iterations)) {
275 SOSCreateError(kSOSErrorProcessingFailure, CFSTR("prng init failed"), NULL, error);
276 return NULL;
277 }
278
279 if (ccec_generate_key_legacy(cp, (struct ccrng_state *)&pbkdf2_prng, tmpkey)) {
280 SOSCreateError(kSOSErrorProcessingFailure, CFSTR("Keygen failed"), NULL, error);
281 return NULL;
282 }
283
284 return ccec2SecKey(tmpkey);
285 }
286
287 void debugDumpUserParameters(CFStringRef message, CFDataRef parameters)
288 {
289 size_t saltlen = 0;
290 const uint8_t *salt = NULL;
291
292 size_t iterations = 0;
293 size_t keysize = 0;
294
295 const uint8_t *der = CFDataGetBytePtr(parameters);
296 const uint8_t *der_end = der + CFDataGetLength(parameters);
297
298 der = der_decode_pbkdf2_params(&saltlen, &salt, &iterations, &keysize, der, der_end);
299 if (der == NULL) {
300 secnotice("keygen", "failed to decode pbkdf2 params");
301 return;
302 }
303
304 BufferPerformWithHexString(salt, saltlen, ^(CFStringRef saltHex) {
305 CFDataPerformWithHexString(parameters, ^(CFStringRef parametersHex) {
306 secnotice("keygen", "%@ <Params: count: %zd, keysize: %zd, salt: %@, raw: %@>]", message, iterations, keysize, saltHex, parametersHex);
307 });
308 });
309 }
310
311 CF_RETURNS_RETAINED CFStringRef UserParametersDescription(CFDataRef parameters){
312
313 __block CFStringRef description = NULL;
314 CFErrorRef error = NULL;
315 CFDataRef newParameters = NULL;
316 SecKeyRef newKey = NULL;
317
318 const uint8_t *parse_end = der_decode_cloud_parameters(kCFAllocatorDefault, kSecECDSAAlgorithmID,
319 &newKey, &newParameters, &error,
320 CFDataGetBytePtr(parameters), CFDataGetPastEndPtr(parameters));
321
322 if (parse_end != CFDataGetPastEndPtr(parameters)){
323 secnotice("keygen", "failed to decode cloud parameters");
324 return NULL;
325 }
326
327 size_t saltlen = 0;
328 const uint8_t *salt = NULL;
329
330 size_t iterations = 0;
331 size_t keysize = 0;
332
333 const uint8_t *der = CFDataGetBytePtr(newParameters);
334 const uint8_t *der_end = der + CFDataGetLength(newParameters);
335
336 der = der_decode_pbkdf2_params(&saltlen, &salt, &iterations, &keysize, der, der_end);
337 if (der == NULL) {
338 secnotice("keygen", "failed to decode pbkdf2 params");
339 return NULL;
340 }
341
342 BufferPerformWithHexString(salt, saltlen, ^(CFStringRef saltHex) {
343 CFDataPerformWithHexString(newParameters, ^(CFStringRef parametersHex) {
344 description = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("<Params: count: %zd, keysize: %zd, salt: %@, key: %@>"), iterations, keysize, saltHex, newKey);
345 });
346 });
347
348 return description;
349 }
350