]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/Regressions/sc-25-soskeygen.c
Security-59306.11.20.tar.gz
[apple/security.git] / keychain / SecureObjectSync / Regressions / sc-25-soskeygen.c
1 //
2 // sc-25-soskeygen.c
3 // sec
4 //
5 // Created by Richard Murphy on 6/1/15.
6 //
7 //
8
9 /*
10 * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved.
11 *
12 * @APPLE_LICENSE_HEADER_START@
13 *
14 * This file contains Original Code and/or Modifications of Original Code
15 * as defined in and that are subject to the Apple Public Source License
16 * Version 2.0 (the 'License'). You may not use this file except in
17 * compliance with the License. Please obtain a copy of the License at
18 * http://www.opensource.apple.com/apsl/ and read it before using this
19 * file.
20 *
21 * The Original Code and all software distributed under the License are
22 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
23 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
24 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
26 * Please see the License for the specific language governing rights and
27 * limitations under the License.
28 *
29 * @APPLE_LICENSE_HEADER_END@
30 */
31
32
33
34 #include <Security/SecBase.h>
35 #include <Security/SecItem.h>
36 #include <Security/SecKey.h>
37 #include <Security/SecKeyPriv.h>
38
39 #include "keychain/SecureObjectSync/SOSInternal.h"
40 #include "keychain/SecureObjectSync/SOSUserKeygen.h"
41
42 #include <utilities/SecCFWrappers.h>
43
44 #include <CoreFoundation/CoreFoundation.h>
45
46 #include <stdlib.h>
47 #include <unistd.h>
48 #include "SOSCircle_regressions.h"
49
50 #include "SOSRegressionUtilities.h"
51 #include <corecrypto/ccrng.h>
52 #include <corecrypto/ccrng_pbkdf2_prng.h>
53 #include <corecrypto/ccec.h>
54 #include <corecrypto/ccdigest.h>
55 #include <corecrypto/ccsha2.h>
56 #include <corecrypto/ccder.h>
57 #include <Security/oidsalg.h>
58
59
60 #if TARGET_OS_WATCH
61 #define NPARMS 3
62 #define NKEYS 3
63 #else
64 #define NPARMS 10
65 #define NKEYS 10
66 #endif
67
68
69 #define TESTCOMPAT 1
70 #if TESTCOMPAT == 1
71
72 static const uint8_t *der_expect_SecAsn1Oid(const SecAsn1Oid* secasn_oid, const uint8_t *der, const uint8_t *der_end)
73 {
74 size_t len = 0;
75 der = ccder_decode_tl(CCDER_OBJECT_IDENTIFIER, &len,
76 der, der_end);
77
78 if (secasn_oid->Length != len || memcmp(secasn_oid->Data, der, len) != 0)
79 der = NULL;
80 else
81 der += len;
82
83 return der;
84 }
85
86
87 static const uint8_t *der_decode_pbkdf2_params(size_t *saltLen, const uint8_t **salt,
88 unsigned long *iterationCount,
89 unsigned long *keyLength,
90 const uint8_t *der, const uint8_t *der_end)
91 {
92 const uint8_t * body_end = NULL;
93 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &body_end, der, der_end);
94
95 if (body_end != der_end)
96 der = NULL;
97
98 size_t salt_size = 0;
99 const uint8_t *salt_bytes = NULL;
100
101 der = ccder_decode_tl(CCDER_OCTET_STRING, &salt_size, der, body_end);
102 salt_bytes = der;
103 der += salt_size;
104
105 uint64_t iteration_count = 0;
106 uint64_t key_len = 0;
107 der = ccder_decode_uint64(&iteration_count, der, body_end);
108 if (iteration_count > UINT32_MAX)
109 der = NULL;
110
111 der = ccder_decode_uint64(&key_len, der, body_end);
112 if (key_len > UINT32_MAX)
113 der = NULL;
114
115 der = der_expect_SecAsn1Oid(&CSSMOID_PKCS5_HMAC_SHA1, der, body_end);
116
117 if (der) {
118 if (salt)
119 *salt = salt_bytes;
120 if (saltLen)
121 *saltLen = salt_size;
122 if (iterationCount)
123 *iterationCount = (unsigned long)iteration_count;
124 if (keyLength)
125 *keyLength = (unsigned long) key_len;
126 }
127
128 return der;
129 }
130 #define SALTMAX 16
131 #define ITERATIONMIN 50000
132
133 static SecKeyRef ccec2SecKey(ccec_full_ctx_t fk)
134 {
135 size_t export_size = ccec_x963_export_size(1, ccec_ctx_pub(fk));
136 uint8_t export_keybytes[export_size];
137 ccec_x963_export(1, export_keybytes, fk);
138 CFDataRef exportedkey = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, export_keybytes, export_size, kCFAllocatorNull);
139
140 CFDictionaryRef keyattributes = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
141 kSecValueData, exportedkey,
142 kSecAttrKeyType, kSecAttrKeyTypeEC,
143 kSecAttrKeyClass, kSecAttrKeyClassPrivate,
144 NULL);
145
146 SecKeyRef retval = SecKeyCreateFromAttributeDictionary(keyattributes);
147
148 CFRelease(keyattributes);
149 CFRelease(exportedkey);
150 cc_clear(export_size, export_keybytes);
151 return retval;
152 }
153
154 static SecKeyRef SOSOldUserKeygen(CFDataRef password, CFDataRef parameters, CFErrorRef *error)
155 {
156 size_t saltlen;
157 const uint8_t *salt = NULL;
158
159 size_t iterations = 0;
160 size_t keysize = 0;
161
162 const uint8_t *der = CFDataGetBytePtr(parameters);
163 const uint8_t *der_end = der + CFDataGetLength(parameters);
164
165 der = der_decode_pbkdf2_params(&saltlen, &salt, &iterations, &keysize, der, der_end);
166
167 if (der == NULL) {
168 SOSCreateErrorWithFormat(kSOSErrorDecodeFailure, NULL, error, NULL,
169 CFSTR("Bad paramter encoding, got: %@"), parameters);
170 return NULL;
171 }
172 if (keysize != 256) {
173 SOSCreateErrorWithFormat(kSOSErrorUnsupported, NULL, error, NULL,
174 CFSTR("Key size not supported, requested %zd."), keysize);
175 return NULL;
176 }
177 if (saltlen < 4) {
178 SOSCreateErrorWithFormat(kSOSErrorUnsupported, NULL, error, NULL,
179 CFSTR("Salt length not supported, requested %zd."), saltlen);
180 return NULL;
181 }
182 if (iterations < ITERATIONMIN) {
183 SOSCreateErrorWithFormat(kSOSErrorUnsupported, NULL, error, NULL,
184 CFSTR("Too few iterations, params suggested %zd."), iterations);
185 return NULL;
186 }
187
188 debugDumpUserParameters(CFSTR("params-keygen"), parameters);
189
190
191 const uint8_t *password_bytes = CFDataGetBytePtr(password);
192 size_t password_length = CFDataGetLength(password);
193
194 const size_t maxbytes = 128;
195
196 ccec_const_cp_t cp = ccec_get_cp(keysize);
197 struct ccrng_pbkdf2_prng_state pbkdf2_prng;
198
199 ccec_full_ctx_decl_cp(cp, tmpkey);
200
201 secnotice("circleOps", "Generating key for: iterations %zd, keysize %zd: %@", iterations, keysize, parameters);
202
203 if (ccrng_pbkdf2_prng_init(&pbkdf2_prng, maxbytes,
204 password_length, password_bytes,
205 saltlen, salt,
206 iterations)) {
207 SOSCreateError(kSOSErrorProcessingFailure, CFSTR("prng init failed"), NULL, error);
208 return NULL;
209 }
210
211 if (ccec_generate_key_legacy(cp, (struct ccrng_state *)&pbkdf2_prng, tmpkey)) {
212 SOSCreateError(kSOSErrorProcessingFailure, CFSTR("Keygen failed"), NULL, error);
213 return NULL;
214 }
215
216 return ccec2SecKey(tmpkey);
217 }
218
219
220 static SecKeyRef createOldTestKey(CFDataRef cfpassword, CFDataRef parameters, CFErrorRef *error) {
221 SecKeyRef user_privkey = SOSOldUserKeygen(cfpassword, parameters, error);
222 ok(user_privkey, "No key!");
223 ok(*error == NULL, "Error: (%@)", *error);
224 CFReleaseNull(*error);
225 return user_privkey;
226 }
227
228 #endif /* TESTCOMPAT */
229
230 static SecKeyRef createTestKey(CFDataRef cfpassword, CFDataRef parameters, CFErrorRef *error) {
231 SecKeyRef user_privkey = SOSUserKeygen(cfpassword, parameters, error);
232 ok(user_privkey, "No key!");
233 ok(*error == NULL, "Error: (%@)", *error);
234 CFReleaseNull(*error);
235 return user_privkey;
236 }
237
238 static void tests(void) {
239 CFErrorRef error = NULL;
240 CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10);
241
242 for(int j=0; j < NPARMS; j++) {
243 CFDataRef parameters = SOSUserKeyCreateGenerateParameters(&error);
244 ok(parameters, "No parameters!");
245 ok(error == NULL, "Error: (%@)", error);
246 CFReleaseNull(error);
247
248 SecKeyRef baseline_privkey = createTestKey(cfpassword, parameters, &error);
249 ok(baseline_privkey != NULL, "Failed to create baseline privkey");
250 if(baseline_privkey) {
251 SecKeyRef baseline_pubkey = SecKeyCreatePublicFromPrivate(baseline_privkey);
252
253 for(int i = 0; i < NKEYS; i++) {
254 SecKeyRef user_privkey = createTestKey(cfpassword, parameters, &error);
255 SecKeyRef user_pubkey = SecKeyCreatePublicFromPrivate(user_privkey);
256 ok(CFEqualSafe(baseline_privkey, user_privkey), "Private Keys Don't Match");
257 ok(CFEqualSafe(baseline_pubkey, user_pubkey), "Public Keys Don't Match");
258 #if TESTCOMPAT == 1
259 SecKeyRef old_privkey = createOldTestKey(cfpassword, parameters, &error);
260 SecKeyRef old_pubkey = SecKeyCreatePublicFromPrivate(old_privkey);
261 ok(CFEqualSafe(old_privkey, user_privkey), "Old/New Private Keys Don't Match");
262 ok(CFEqualSafe(old_pubkey, user_pubkey), "Old/New Public Keys Don't Match");
263 CFReleaseNull(old_privkey);
264 CFReleaseNull(old_pubkey);
265 #endif /* TESTCOMPAT */
266 CFReleaseNull(error);
267 CFReleaseNull(user_privkey);
268 CFReleaseNull(user_pubkey);
269 }
270 CFReleaseNull(baseline_pubkey);
271 }
272 CFReleaseNull(baseline_privkey);
273 CFReleaseNull(parameters);
274 }
275 CFReleaseNull(cfpassword);
276 }
277
278 int sc_25_soskeygen(int argc, char *const *argv)
279 {
280 #if TARGET_OS_WATCH
281 plan_tests(NKEYS*(4+NPARMS*4));
282 #else
283 plan_tests(850);
284 #endif
285
286 tests();
287
288 return 0;
289 }