]>
Commit | Line | Data |
---|---|---|
d8f41ccd A |
1 | /* |
2 | * Copyright (c) 2011-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 | ||
427c49bc A |
24 | |
25 | /* | |
26 | * si-40-seckey.c | |
27 | * Security | |
28 | * | |
d8f41ccd | 29 | * Copyright (c) 2007-2009,2012-2014 Apple Inc. All Rights Reserved. |
427c49bc A |
30 | * |
31 | */ | |
32 | ||
33 | #include <CoreFoundation/CoreFoundation.h> | |
34 | #include <Security/SecCertificate.h> | |
35 | #include <Security/SecCertificateInternal.h> | |
36 | #include <Security/SecKey.h> | |
5c19dc3a | 37 | #include <Security/SecECKey.h> |
427c49bc A |
38 | #include <Security/SecKeyPriv.h> |
39 | #include <Security/SecItem.h> | |
40 | #include <Security/SecAsn1Types.h> | |
41 | #include <Security/oidsalg.h> | |
42 | #include <Security/SecureTransport.h> | |
43 | #include <Security/SecRandom.h> | |
44 | #include <utilities/array_size.h> | |
d8f41ccd A |
45 | #include <utilities/SecCFRelease.h> |
46 | #include <utilities/SecCFWrappers.h> | |
427c49bc A |
47 | #include <CommonCrypto/CommonDigest.h> |
48 | #include <libDER/libDER.h> | |
49 | #include <stdlib.h> | |
50 | #include <unistd.h> | |
fa7225c8 | 51 | #include <corecrypto/ccsha2.h> |
427c49bc A |
52 | |
53 | #include "Security_regressions.h" | |
54 | ||
427c49bc A |
55 | static void testdigestandsignalg(SecKeyRef privKey, SecKeyRef pubKey, const SecAsn1AlgId *algId) { |
56 | uint8_t dataToDigest[256] = {0,}; | |
57 | size_t dataToDigestLen = sizeof(dataToDigest); | |
58 | size_t sigLen = SecKeyGetSize(privKey, kSecKeySignatureSize); | |
59 | uint8_t sig[sigLen]; | |
60 | ||
61 | DERItem oid; | |
62 | oid.length = algId->algorithm.Length; | |
63 | oid.data = algId->algorithm.Data; | |
64 | ||
65 | /* Get the oid in decimal for display purposes. */ | |
66 | CFStringRef oidStr = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, &oid); | |
67 | char oidBuf[40]; | |
68 | CFStringGetCString(oidStr, oidBuf, sizeof(oidBuf), kCFStringEncodingUTF8); | |
69 | CFRelease(oidStr); | |
70 | ||
71 | SKIP: { | |
72 | OSStatus status; | |
73 | ||
74 | /* Time to sign. */ | |
75 | ok_status(status = SecKeyDigestAndSign(privKey, algId, dataToDigest, dataToDigestLen, | |
76 | sig, &sigLen), | |
77 | "digest and sign %s with %ld bit RSA key", oidBuf, sigLen * 8); | |
78 | ||
79 | skip("SecKeyDigestAndSign failed", 3, status == errSecSuccess); | |
80 | ||
81 | /* Verify the signature we just made. */ | |
82 | ok_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, | |
83 | sig, sigLen), "digest and verify"); | |
84 | /* Invalidate the signature. */ | |
85 | sig[0] ^= 0xff; | |
86 | is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, | |
87 | sig, sigLen), errSSLCrypto, "digest and verify bad sig"); | |
88 | sig[0] ^= 0xff; | |
89 | dataToDigest[0] ^= 0xff; | |
90 | is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, | |
91 | sig, sigLen), errSSLCrypto, "digest and verify bad digest"); | |
92 | } | |
93 | } | |
94 | ||
95 | static void testdigestandsign(SecKeyRef privKey, SecKeyRef pubKey) { | |
96 | static const SecAsn1Oid *oids[] = { | |
97 | &CSSMOID_ECDSA_WithSHA1, | |
98 | #if 0 | |
99 | &CSSMOID_ECDSA_WithSHA224, | |
100 | &CSSMOID_ECDSA_WithSHA256, | |
101 | &CSSMOID_ECDSA_WithSHA384, | |
102 | &CSSMOID_ECDSA_WithSHA512, | |
103 | #endif | |
104 | }; | |
105 | ||
106 | uint32_t ix; | |
107 | SecAsn1AlgId algId = {}; | |
108 | for (ix = 0; ix < array_size(oids); ++ix) { | |
109 | if (oids[ix]) { | |
110 | algId.algorithm = *oids[ix]; | |
111 | } else { | |
112 | algId.algorithm.Length = 0; | |
113 | algId.algorithm.Data = NULL; | |
114 | } | |
115 | ||
116 | testdigestandsignalg(privKey, pubKey, &algId); | |
117 | } | |
118 | } | |
119 | ||
120 | static void testkeygen(size_t keySizeInBits) { | |
121 | SecKeyRef pubKey = NULL, privKey = NULL; | |
122 | size_t keySizeInBytes = (keySizeInBits + 7) / 8; | |
123 | CFNumberRef kzib; | |
124 | int32_t keysz32 = (int32_t)keySizeInBits; | |
125 | ||
126 | kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); | |
127 | CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); | |
128 | CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC); | |
129 | CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib); | |
130 | ||
131 | OSStatus status; | |
132 | ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), | |
133 | "Generate %ld bit (%ld byte) EC keypair", keySizeInBits, | |
134 | keySizeInBytes); | |
135 | CFRelease(kzib); | |
136 | CFRelease(kgp); | |
137 | ||
138 | SKIP: { | |
139 | skip("keygen failed", 8, status == errSecSuccess); | |
140 | ok(pubKey, "pubkey returned"); | |
141 | ok(privKey, "privKey returned"); | |
142 | is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok"); | |
143 | is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok"); | |
144 | ||
145 | /* Sign something. */ | |
146 | uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; | |
147 | uint8_t sig[8+2*keySizeInBytes]; | |
148 | size_t sigLen = sizeof(sig); | |
149 | ok_status(SecKeyRawSign(privKey, kSecPaddingNone, | |
150 | something, sizeof(something), sig, &sigLen), "sign something"); | |
151 | ok_status(SecKeyRawVerify(pubKey, kSecPaddingNone, | |
152 | something, sizeof(something), sig, sigLen), "verify sig on something"); | |
153 | ||
154 | testdigestandsign(privKey, pubKey); | |
155 | ||
156 | const void *privkeys[] = { | |
157 | kSecValueRef | |
158 | }; | |
159 | const void *privvalues[] = { | |
160 | privKey | |
161 | }; | |
162 | CFDictionaryRef privitem = CFDictionaryCreate(NULL, privkeys, privvalues, | |
163 | array_size(privkeys), NULL, NULL); | |
164 | ok_status(SecItemAdd(privitem, NULL), "add private key"); | |
165 | ok_status(SecItemDelete(privitem), "delete public key"); | |
166 | CFReleaseNull(privitem); | |
167 | ||
168 | const void *pubkeys[] = { | |
169 | kSecValueRef | |
170 | }; | |
171 | const void *pubvalues[] = { | |
172 | pubKey | |
173 | }; | |
174 | CFDictionaryRef pubitem = CFDictionaryCreate(NULL, pubkeys, pubvalues, | |
175 | array_size(pubkeys), NULL, NULL); | |
176 | ok_status(SecItemAdd(pubitem, NULL), "add public key"); | |
177 | ok_status(SecItemDelete(pubitem), "delete public key"); | |
178 | CFReleaseNull(pubitem); | |
179 | ||
180 | /* Cleanup. */ | |
181 | CFReleaseNull(pubKey); | |
182 | CFReleaseNull(privKey); | |
183 | } | |
184 | } | |
185 | ||
186 | ||
187 | static void testkeygen2(size_t keySizeInBits) { | |
188 | SecKeyRef pubKey = NULL, privKey = NULL; | |
189 | size_t keySizeInBytes = (keySizeInBits + 7) / 8; | |
190 | CFNumberRef kzib; | |
191 | int32_t keysz32 = (int32_t)keySizeInBits; | |
192 | ||
193 | CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault); | |
194 | CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID); | |
195 | CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); | |
196 | CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); | |
197 | ||
198 | CFReleaseNull(ourUUID); | |
199 | CFReleaseNull(uuidString); | |
200 | ||
201 | CFStringAppend(publicName, CFSTR("-Public-41")); | |
202 | CFStringAppend(privateName, CFSTR("-Private-41")); | |
203 | ||
d8f41ccd A |
204 | CFMutableDictionaryRef pubd = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, |
205 | kSecAttrLabel, publicName, | |
206 | NULL); | |
207 | CFMutableDictionaryRef privd = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, | |
208 | kSecAttrLabel, privateName, | |
209 | NULL); | |
427c49bc A |
210 | |
211 | kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); | |
d8f41ccd A |
212 | CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, |
213 | kSecAttrKeyType, kSecAttrKeyTypeEC, | |
214 | kSecAttrKeySizeInBits, kzib, | |
215 | kSecAttrIsPermanent, kCFBooleanTrue, | |
216 | kSecPublicKeyAttrs, pubd, | |
217 | kSecPrivateKeyAttrs, privd, | |
218 | NULL); | |
219 | ||
220 | CFReleaseNull(kzib); | |
427c49bc A |
221 | |
222 | OSStatus status; | |
223 | ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), | |
224 | "Generate %ld bit (%ld byte) persistent RSA keypair", | |
225 | keySizeInBits, keySizeInBytes); | |
d8f41ccd A |
226 | |
227 | CFReleaseNull(kgp); | |
427c49bc A |
228 | |
229 | SKIP: { | |
230 | skip("keygen failed", 8, status == errSecSuccess); | |
231 | ok(pubKey, "pubkey returned"); | |
232 | ok(privKey, "privKey returned"); | |
233 | is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok"); | |
234 | is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok"); | |
235 | ||
236 | SecKeyRef pubKey2, privKey2; | |
237 | CFDictionaryAddValue(pubd, kSecClass, kSecClassKey); | |
238 | CFDictionaryAddValue(pubd, kSecReturnRef, kCFBooleanTrue); | |
239 | CFDictionaryAddValue(privd, kSecClass, kSecClassKey); | |
240 | CFDictionaryAddValue(privd, kSecReturnRef, kCFBooleanTrue); | |
241 | CFDictionaryAddValue(privd, kSecAttrCanSign, kCFBooleanTrue); | |
242 | ok_status(SecItemCopyMatching(pubd, (CFTypeRef *)&pubKey2), | |
243 | "retrieve pub key by label"); | |
244 | ok(pubKey2, "got valid object"); | |
245 | ok_status(SecItemCopyMatching(privd, (CFTypeRef *)&privKey2), | |
246 | "retrieve priv key by label and kSecAttrCanSign"); | |
247 | ok(privKey2, "got valid object"); | |
248 | ||
249 | /* Sign something. */ | |
250 | uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; | |
251 | size_t sigLen = SecKeyGetSize(privKey2, kSecKeySignatureSize); | |
252 | uint8_t sig[sigLen]; | |
fa7225c8 A |
253 | if (privKey2 != NULL && pubKey2 != NULL) { |
254 | ok_status(SecKeyRawSign(privKey2, kSecPaddingPKCS1, | |
255 | something, sizeof(something), sig, &sigLen), "sign something"); | |
256 | ok_status(SecKeyRawVerify(pubKey2, kSecPaddingPKCS1, | |
257 | something, sizeof(something), sig, sigLen), "verify sig on something"); | |
258 | } | |
427c49bc A |
259 | |
260 | /* Cleanup. */ | |
261 | CFReleaseNull(pubKey2); | |
262 | CFReleaseNull(privKey2); | |
263 | } | |
264 | ||
265 | /* delete from keychain - note: do it before releasing publicName and privateName | |
266 | because pubd and privd have no retain/release callbacks */ | |
267 | ok_status(SecItemDelete(pubd), "delete generated pub key"); | |
268 | ok_status(SecItemDelete(privd), "delete generated priv key"); | |
269 | ||
270 | /* Cleanup. */ | |
271 | CFReleaseNull(pubKey); | |
272 | CFReleaseNull(privKey); | |
273 | ||
274 | CFReleaseNull(publicName); | |
275 | CFReleaseNull(privateName); | |
276 | ||
d8f41ccd A |
277 | CFReleaseNull(pubd); |
278 | CFReleaseNull(privd); | |
279 | } | |
280 | ||
281 | static void testkeywrap(unsigned long keySizeInBits, CFTypeRef alg) | |
282 | { | |
283 | SecKeyRef pubKey = NULL, privKey = NULL; | |
284 | size_t keySizeInBytes = (keySizeInBits + 7) / 8; | |
285 | CFNumberRef kzib; | |
286 | int32_t keysz32 = (int32_t)keySizeInBits; | |
287 | ||
288 | CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault); | |
289 | CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID); | |
290 | CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); | |
291 | CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); | |
292 | ||
293 | CFReleaseNull(ourUUID); | |
294 | CFReleaseNull(uuidString); | |
295 | ||
296 | CFStringAppend(publicName, CFSTR("-Public-41")); | |
297 | CFStringAppend(privateName, CFSTR("-Private-41")); | |
298 | ||
299 | CFDictionaryRef pubd = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, | |
300 | kSecAttrLabel, publicName, | |
301 | NULL); | |
302 | CFDictionaryRef privd = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, | |
303 | kSecAttrLabel, privateName, | |
304 | NULL); | |
305 | ||
306 | CFReleaseNull(publicName); | |
307 | CFReleaseNull(privateName); | |
308 | ||
309 | kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); | |
310 | CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, | |
311 | kSecAttrKeyType, kSecAttrKeyTypeEC, | |
312 | kSecAttrKeySizeInBits, kzib, | |
313 | kSecAttrIsPermanent, kCFBooleanFalse, | |
314 | kSecPublicKeyAttrs, pubd, | |
315 | kSecPrivateKeyAttrs, privd, | |
316 | NULL); | |
317 | CFReleaseNull(pubd); | |
318 | CFReleaseNull(privd); | |
319 | CFReleaseNull(kzib); | |
320 | ||
321 | OSStatus status; | |
322 | ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), | |
323 | "Generate %ld bit (%ld byte) persistent RSA keypair (status = %d)", | |
324 | keySizeInBits, keySizeInBytes, (int)status); | |
325 | CFReleaseNull(kgp); | |
326 | ||
5c19dc3a | 327 | CFErrorRef localError = NULL; |
d8f41ccd A |
328 | |
329 | CFDataRef secret = CFDataCreate(NULL, (void *)"0123456789012345", 16); | |
330 | ok(secret, "secret"); | |
331 | ||
332 | CFDataRef fp = CFDataCreate(NULL, (void *)"01234567890123456789", 20); | |
333 | ok(fp, "fingerprint"); | |
334 | ||
335 | ||
336 | int8_t sym_alg_data = 8; | |
337 | CFNumberRef symalg = CFNumberCreate(NULL, kCFNumberSInt8Type, &sym_alg_data); | |
338 | CFDictionaryRef param = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, | |
339 | _kSecKeyWrapPGPWrapAlg, alg, | |
340 | _kSecKeyWrapPGPSymAlg, symalg, | |
341 | _kSecKeyWrapPGPFingerprint, fp, | |
342 | NULL); | |
343 | ||
344 | CFDataRef wrapped = _SecKeyCopyWrapKey(pubKey, kSecKeyWrapPublicKeyPGP, secret, param, NULL, &localError); | |
345 | ok(wrapped, "wrap key: %@", localError); | |
346 | ||
347 | CFDataRef unwrapped = _SecKeyCopyUnwrapKey(privKey, kSecKeyWrapPublicKeyPGP, wrapped, param, NULL, &localError); | |
348 | ok(unwrapped, "unwrap key: %@", localError); | |
349 | ||
350 | CFReleaseNull(symalg); | |
351 | ||
352 | ok(CFEqual(unwrapped, secret), "keys still same"); | |
353 | ||
354 | CFReleaseNull(fp); | |
355 | CFReleaseNull(secret); | |
356 | CFReleaseNull(unwrapped); | |
357 | CFReleaseNull(wrapped); | |
358 | CFReleaseNull(param); | |
359 | CFReleaseNull(privKey); | |
360 | CFReleaseNull(pubKey); | |
427c49bc A |
361 | } |
362 | ||
5c19dc3a A |
363 | const uint8_t EC_P256_KeyDER[]={ |
364 | 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20, 0x86, 0x87, 0x79, 0x59, 0xd1, | |
365 | 0xc6, 0x3c, 0x50, 0x24, 0x30, 0xa4, 0xaf, 0x89, 0x1d, 0xd1, 0x94, 0x23, | |
366 | 0x56, 0x79, 0x46, 0x93, 0x72, 0x31, 0x39, 0x24, 0xe6, 0x01, 0x96, 0xc8, | |
367 | 0xeb, 0xf3, 0x88, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x8c, 0xfa, 0xd7, | |
368 | 0x8a, 0xf1, 0xb9, 0xad, 0xd7, 0x3a, 0x33, 0xb5, 0x9a, 0xad, 0x52, 0x0d, | |
369 | 0x14, 0xd6, 0x6b, 0x35, 0x56, 0x79, 0xd6, 0x74, 0x2a, 0x37, 0x7e, 0x2f, | |
370 | 0x33, 0xa6, 0xab, 0xee, 0x35, 0x00, 0x70, 0x82, 0x89, 0x9c, 0xfc, 0x97, | |
371 | 0xc4, 0x89, 0x5c, 0x16, 0x50, 0xad, 0x60, 0x55, 0xa6, 0x70, 0xee, 0x07, | |
372 | 0x1b, 0xfe, 0xe4, 0xf0, 0xa0, 0x63, 0xc0, 0x73, 0x24, 0x97, 0x92, 0x04, | |
373 | 0xc7}; | |
374 | ||
375 | const uint8_t EC_P256_SigDER[]={ | |
376 | 0x30, 0x45, 0x02, 0x20, 0x4b, 0x37, 0x7f, 0x45, 0xd0, 0x5d, 0xa6, 0x53, | |
377 | 0xb3, 0x62, 0x6f, 0x32, 0xdb, 0xfc, 0xf6, 0x3b, 0x84, 0xfa, 0x5a, 0xd9, | |
378 | 0x17, 0x67, 0x03, 0x73, 0x48, 0x0c, 0xad, 0x89, 0x13, 0x69, 0x61, 0xb3, | |
379 | 0x02, 0x21, 0x00, 0xd6, 0x23, 0xaf, 0xd9, 0x7d, 0x72, 0xba, 0x3b, 0x90, | |
380 | 0xc1, 0x23, 0x7d, 0xdb, 0x2c, 0xd1, 0x0d, 0xbb, 0xb4, 0x0f, 0x67, 0x26, | |
381 | 0xff, 0x3f, 0xa6, 0x47, 0xa4, 0x13, 0x0d, 0xe0, 0x45, 0xd5, 0x6b}; | |
382 | ||
383 | const uint8_t EC_P256_SigRaw[]= { | |
384 | 0x4b, 0x37, 0x7f, 0x45, 0xd0, 0x5d, 0xa6, 0x53, 0xb3, 0x62, 0x6f, 0x32, | |
385 | 0xdb, 0xfc, 0xf6, 0x3b, 0x84, 0xfa, 0x5a, 0xd9, 0x17, 0x67, 0x03, 0x73, | |
386 | 0x48, 0x0c, 0xad, 0x89, 0x13, 0x69, 0x61, 0xb3, 0xd6, 0x23, 0xaf, 0xd9, | |
387 | 0x7d, 0x72, 0xba, 0x3b, 0x90, 0xc1, 0x23, 0x7d, 0xdb, 0x2c, 0xd1, 0x0d, | |
388 | 0xbb, 0xb4, 0x0f, 0x67, 0x26, 0xff, 0x3f, 0xa6, 0x47, 0xa4, 0x13, 0x0d, | |
389 | 0xe0, 0x45, 0xd5, 0x6b}; | |
390 | ||
391 | const uint8_t EC_SigDigest[24] = "012345678912345678901234"; | |
392 | ||
393 | static void testsignformat(void) | |
394 | { | |
395 | SecKeyRef pkey = NULL; | |
396 | SecKeyRef pubkey = NULL; | |
397 | CFDataRef pubdata = NULL; | |
398 | uint8_t EC_signature_DER[72]; | |
399 | uint8_t EC_signature_RAW[64]; | |
400 | size_t EC_signature_DER_size=sizeof(EC_signature_DER); | |
401 | size_t EC_signature_RAW_size=sizeof(EC_signature_RAW); | |
402 | ||
403 | ok((pkey = SecKeyCreateECPrivateKey(kCFAllocatorDefault, | |
404 | EC_P256_KeyDER, sizeof(EC_P256_KeyDER), | |
405 | kSecKeyEncodingPkcs1)) != NULL, "import privkey"); | |
406 | ||
407 | ok_status(SecKeyCopyPublicBytes(pkey, &pubdata), "pub key from priv key"); | |
408 | ||
409 | ok((pubkey = SecKeyCreateECPublicKey(kCFAllocatorDefault, | |
410 | CFDataGetBytePtr(pubdata), CFDataGetLength(pubdata), | |
411 | kSecKeyEncodingBytes))!=NULL, | |
412 | "recreate seckey"); | |
413 | ||
fa7225c8 A |
414 | if (pubkey != NULL && pkey != NULL) { |
415 | // Verify fixed signature | |
416 | ok_status(SecKeyRawVerify(pubkey, kSecPaddingPKCS1, | |
417 | EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigDER, sizeof(EC_P256_SigDER)), "verify DER sig on something"); | |
5c19dc3a | 418 | |
fa7225c8 A |
419 | ok_status(SecKeyRawVerify(pubkey, kSecPaddingSigRaw, |
420 | EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigRaw, sizeof(EC_P256_SigRaw)), "verify RAW sig on something"); | |
5c19dc3a | 421 | |
fa7225c8 A |
422 | // Verify signature with mismatching format |
423 | ok_status(!SecKeyRawVerify(pubkey, kSecPaddingSigRaw, | |
424 | EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigDER, sizeof(EC_P256_SigDER)), "verify DER sig with RAW option"); | |
427c49bc | 425 | |
fa7225c8 A |
426 | ok_status(!SecKeyRawVerify(pubkey, kSecPaddingPKCS1, |
427 | EC_SigDigest, sizeof(EC_SigDigest), EC_P256_SigRaw, sizeof(EC_P256_SigRaw)), "verify RAW sig with DER something"); | |
d8f41ccd | 428 | |
fa7225c8 A |
429 | // Sign something in each format |
430 | ok_status(SecKeyRawSign(pkey, kSecPaddingPKCS1, | |
431 | EC_SigDigest, sizeof(EC_SigDigest), EC_signature_DER, &EC_signature_DER_size), "sign DER sig on something"); | |
5c19dc3a | 432 | |
fa7225c8 A |
433 | ok_status(SecKeyRawSign(pkey, kSecPaddingSigRaw, |
434 | EC_SigDigest, sizeof(EC_SigDigest), EC_signature_RAW, &EC_signature_RAW_size), "sign RAW sig on something"); | |
5c19dc3a | 435 | |
fa7225c8 A |
436 | // Verify expecting that verification does the right thing. |
437 | ok_status(SecKeyRawVerify(pubkey, kSecPaddingPKCS1, | |
438 | EC_SigDigest, sizeof(EC_SigDigest), EC_signature_DER, EC_signature_DER_size), "verify DER sig on something"); | |
5c19dc3a | 439 | |
fa7225c8 A |
440 | ok_status(SecKeyRawVerify(pubkey, kSecPaddingSigRaw, |
441 | EC_SigDigest, sizeof(EC_SigDigest), EC_signature_RAW, EC_signature_RAW_size), "verify RAW sig on something"); | |
442 | } | |
5c19dc3a A |
443 | |
444 | CFReleaseNull(pkey); | |
445 | CFReleaseNull(pubkey); | |
446 | CFReleaseNull(pubdata); | |
447 | } | |
d8f41ccd | 448 | |
fa7225c8 A |
449 | static void testkeyexchange(unsigned long keySizeInBits) |
450 | { | |
451 | size_t keySizeInBytes = (keySizeInBits + 7) / 8; | |
452 | CFNumberRef kzib; | |
453 | int32_t keysz32 = (int32_t)keySizeInBits; | |
454 | ||
455 | kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); | |
456 | CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, | |
457 | kSecAttrKeyType, kSecAttrKeyTypeEC, | |
458 | kSecAttrKeySizeInBits, kzib, | |
459 | kSecAttrIsPermanent, kCFBooleanFalse, | |
460 | NULL); | |
461 | CFReleaseNull(kzib); | |
462 | ||
463 | SecKeyRef pubKey1 = NULL, privKey1 = NULL; | |
464 | SecKeyRef pubKey2 = NULL, privKey2 = NULL; | |
465 | ||
466 | OSStatus status; | |
467 | ok_status(status = SecKeyGeneratePair(kgp, &pubKey1, &privKey1), | |
468 | "Generate %ld bit (%ld byte) EC keypair (status = %d)", | |
469 | keySizeInBits, keySizeInBytes, (int)status); | |
470 | ok_status(status = SecKeyGeneratePair(kgp, &pubKey2, &privKey2), | |
471 | "Generate %ld bit (%ld byte) EC keypair (status = %d)", | |
472 | keySizeInBits, keySizeInBytes, (int)status); | |
473 | CFReleaseNull(kgp); | |
474 | ||
475 | const SecKeyAlgorithm algos[] = { | |
476 | kSecKeyAlgorithmECDHKeyExchangeStandard, | |
477 | kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1, | |
478 | kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA224, | |
479 | kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256, | |
480 | kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA384, | |
481 | kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA512, | |
482 | kSecKeyAlgorithmECDHKeyExchangeCofactor, | |
483 | kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1, | |
484 | kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA224, | |
485 | kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA256, | |
486 | kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA384, | |
487 | kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA512, | |
488 | }; | |
489 | ||
490 | // Strange size to test borderline conditions. | |
491 | CFIndex rs = 273; | |
492 | CFNumberRef requestedSize = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &rs); | |
493 | CFDataRef sharedInfo = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)"sharedInput", 11); | |
494 | CFDictionaryRef params = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, | |
495 | kSecKeyKeyExchangeParameterRequestedSize, requestedSize, | |
496 | kSecKeyKeyExchangeParameterSharedInfo, sharedInfo, | |
497 | NULL); | |
498 | CFRelease(requestedSize); | |
499 | CFRelease(sharedInfo); | |
500 | ||
501 | for (size_t ix = 0; ix < array_size(algos); ++ix) { | |
502 | CFErrorRef error = NULL; | |
503 | ||
504 | CFDataRef secret1 = SecKeyCopyKeyExchangeResult(privKey1, algos[ix], pubKey2, params, &error); | |
505 | ok(secret1 != NULL && CFGetTypeID(secret1) == CFDataGetTypeID()); | |
506 | CFReleaseNull(error); | |
507 | ||
508 | CFDataRef secret2 = SecKeyCopyKeyExchangeResult(privKey2, algos[ix], pubKey1, params, &error); | |
509 | ok(secret2 != NULL && CFGetTypeID(secret1) == CFDataGetTypeID()); | |
510 | CFReleaseNull(error); | |
511 | ||
512 | eq_cf(secret1, secret2, "results of key exchange are equal"); | |
513 | if (algos[ix] != kSecKeyAlgorithmECDHKeyExchangeCofactor && algos[ix] != kSecKeyAlgorithmECDHKeyExchangeStandard) { | |
514 | is(CFDataGetLength(secret1), rs, "generated response has expected length"); | |
515 | } | |
516 | ||
517 | CFReleaseNull(secret1); | |
518 | CFReleaseNull(secret2); | |
519 | } | |
520 | ||
521 | CFReleaseNull(privKey1); | |
522 | CFReleaseNull(pubKey1); | |
523 | CFReleaseNull(privKey2); | |
524 | CFReleaseNull(pubKey2); | |
525 | CFReleaseNull(params); | |
526 | } | |
527 | ||
528 | static void testsupportedalgos(size_t keySizeInBits) | |
529 | { | |
530 | size_t keySizeInBytes = (keySizeInBits + 7) / 8; | |
531 | CFNumberRef kzib; | |
532 | int32_t keysz32 = (int32_t)keySizeInBits; | |
533 | ||
534 | kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); | |
535 | CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, | |
536 | kSecAttrKeyType, kSecAttrKeyTypeEC, | |
537 | kSecAttrKeySizeInBits, kzib, | |
538 | kSecAttrIsPermanent, kCFBooleanFalse, | |
539 | NULL); | |
540 | CFReleaseNull(kzib); | |
541 | ||
542 | SecKeyRef pubKey = NULL, privKey = NULL; | |
543 | ||
544 | OSStatus status; | |
545 | ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), | |
546 | "Generate %ld bit (%ld byte) EC keypair (status = %d)", | |
547 | keySizeInBits, keySizeInBytes, (int)status); | |
548 | ||
549 | const SecKeyAlgorithm sign[] = { | |
550 | kSecKeyAlgorithmECDSASignatureRFC4754, | |
551 | kSecKeyAlgorithmECDSASignatureDigestX962, | |
552 | kSecKeyAlgorithmECDSASignatureDigestX962SHA1, | |
553 | kSecKeyAlgorithmECDSASignatureDigestX962SHA224, | |
554 | kSecKeyAlgorithmECDSASignatureDigestX962SHA256, | |
555 | kSecKeyAlgorithmECDSASignatureDigestX962SHA384, | |
556 | kSecKeyAlgorithmECDSASignatureDigestX962SHA512, | |
557 | kSecKeyAlgorithmECDSASignatureMessageX962SHA1, | |
558 | kSecKeyAlgorithmECDSASignatureMessageX962SHA224, | |
559 | kSecKeyAlgorithmECDSASignatureMessageX962SHA256, | |
560 | kSecKeyAlgorithmECDSASignatureMessageX962SHA384, | |
561 | kSecKeyAlgorithmECDSASignatureMessageX962SHA512, | |
562 | }; | |
563 | ||
564 | for (size_t i = 0; i < array_size(sign); i++) { | |
565 | ok(SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeSign, sign[i]), | |
566 | "privKey supports sign algorithm %@", sign[i]); | |
567 | ok(SecKeyIsAlgorithmSupported(pubKey, kSecKeyOperationTypeVerify, sign[i]), | |
568 | "pubKey supports verify algorithm %@", sign[i]); | |
569 | ok(!SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeVerify, sign[i]), | |
570 | "privKey doesn't supports verify algorithm %@", sign[i]); | |
571 | ok(!SecKeyIsAlgorithmSupported(pubKey, kSecKeyOperationTypeSign, sign[i]), | |
572 | "pubKey doesn't support verify algorithm %@", sign[i]); | |
573 | } | |
574 | ||
575 | const SecKeyAlgorithm keyexchange[] = { | |
576 | kSecKeyAlgorithmECDHKeyExchangeStandard, | |
577 | kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1, | |
578 | kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA224, | |
579 | kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256, | |
580 | kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA384, | |
581 | kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA512, | |
582 | kSecKeyAlgorithmECDHKeyExchangeCofactor, | |
583 | kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1, | |
584 | kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA224, | |
585 | kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA256, | |
586 | kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA384, | |
587 | kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA512, | |
588 | }; | |
589 | for (size_t i = 0; i < array_size(crypt); i++) { | |
590 | ok(SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeKeyExchange, keyexchange[i]), | |
591 | "privKey supports keyexchange algorithm %@", keyexchange[i]); | |
592 | ok(!SecKeyIsAlgorithmSupported(pubKey, kSecKeyOperationTypeKeyExchange, keyexchange[i]), | |
593 | "pubKey doesn't support keyexchange algorithm %@", keyexchange[i]); | |
594 | } | |
595 | ||
596 | /* Cleanup. */ | |
597 | CFReleaseNull(kgp); | |
598 | CFReleaseNull(pubKey); | |
599 | CFReleaseNull(privKey); | |
600 | } | |
601 | ||
602 | static void testcreatewithdata(unsigned long keySizeInBits) | |
603 | { | |
604 | size_t keySizeInBytes = (keySizeInBits + 7) / 8; | |
605 | int32_t keysz32 = (int32_t)keySizeInBits; | |
606 | ||
607 | CFNumberRef kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); | |
608 | CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, | |
609 | kSecAttrKeyType, kSecAttrKeyTypeEC, | |
610 | kSecAttrKeySizeInBits, kzib, | |
611 | kSecAttrIsPermanent, kCFBooleanFalse, | |
612 | NULL); | |
613 | SecKeyRef pubKey = NULL, privKey = NULL; | |
614 | OSStatus status; | |
615 | ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), | |
616 | "Generate %ld bit (%ld byte) EC keypair (status = %d)", | |
617 | keySizeInBits, keySizeInBytes, (int)status); | |
618 | CFReleaseNull(kgp); | |
619 | ||
620 | CFMutableDictionaryRef kcwd = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, | |
621 | kSecAttrKeyType, kSecAttrKeyTypeEC, | |
622 | kSecAttrKeySizeInBits, kzib, | |
623 | kSecAttrIsPermanent, kCFBooleanFalse, | |
624 | NULL); | |
625 | CFReleaseNull(kzib); | |
626 | ||
627 | CFErrorRef error = NULL; | |
628 | CFDataRef privExternalData = NULL, pubExternalData = NULL; | |
629 | SecKeyRef dataKey = NULL; | |
630 | ||
631 | { // privKey | |
632 | privExternalData = SecKeyCopyExternalRepresentation(privKey, &error); | |
633 | ok(privExternalData && CFGetTypeID(privExternalData) == CFDataGetTypeID(), | |
634 | "priv key SecKeyCopyExternalRepresentation failed"); | |
635 | CFReleaseNull(error); | |
636 | ||
637 | SKIP: { | |
638 | skip("invalid priv key external data", 4, privExternalData); | |
639 | ||
640 | CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPrivate); | |
641 | dataKey = SecKeyCreateWithData(privExternalData, kcwd, &error); | |
642 | ok(dataKey, "priv key SecKeyCreateWithData failed"); | |
643 | CFReleaseNull(error); | |
644 | ||
645 | eq_cf(privKey, dataKey, "priv keys differ"); | |
646 | CFReleaseNull(dataKey); | |
647 | ||
648 | CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPublic); | |
649 | dataKey = SecKeyCreateWithData(privExternalData, kcwd, &error); | |
650 | ok(!dataKey, "priv key SecKeyCreateWithData succeeded with invalid kSecAttrKeyClass"); | |
651 | CFReleaseNull(error); | |
652 | CFReleaseNull(dataKey); | |
653 | ||
654 | CFMutableDataRef modifiedExternalData = CFDataCreateMutable(kCFAllocatorDefault, 0); | |
655 | CFDataAppend(modifiedExternalData, privExternalData); | |
656 | *CFDataGetMutableBytePtr(modifiedExternalData) ^= 0xff; | |
657 | ||
658 | CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPrivate); | |
659 | dataKey = SecKeyCreateWithData(modifiedExternalData, kcwd, &error); | |
660 | ok(!dataKey, "priv key SecKeyCreateWithData succeeded with invalid external data"); | |
661 | CFReleaseNull(error); | |
662 | CFReleaseNull(dataKey); | |
663 | ||
664 | CFReleaseNull(modifiedExternalData); | |
665 | } | |
666 | } | |
667 | ||
668 | { // pubKey | |
669 | pubExternalData = SecKeyCopyExternalRepresentation(pubKey, &error); | |
670 | ok(pubExternalData && CFGetTypeID(pubExternalData) == CFDataGetTypeID(), | |
671 | "pub key SecKeyCopyExternalRepresentation failed"); | |
672 | CFReleaseNull(error); | |
673 | ||
674 | SKIP: { | |
675 | skip("invalid pub key external data", 4, pubExternalData); | |
676 | ||
677 | CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPublic); | |
678 | dataKey = SecKeyCreateWithData(pubExternalData, kcwd, &error); | |
679 | ok(dataKey, "pub key SecKeyCreateWithData failed"); | |
680 | CFReleaseNull(error); | |
681 | ||
682 | eq_cf(pubKey, dataKey, "pub keys differ"); | |
683 | CFReleaseNull(dataKey); | |
684 | ||
685 | CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPrivate); | |
686 | dataKey = SecKeyCreateWithData(pubExternalData, kcwd, &error); | |
687 | ok(!dataKey, "pub key SecKeyCreateWithData succeeded with invalid kSecAttrKeyClass"); | |
688 | CFReleaseNull(error); | |
689 | CFReleaseNull(dataKey); | |
690 | ||
691 | CFMutableDataRef modifiedExternalData = CFDataCreateMutable(kCFAllocatorDefault, 0); | |
692 | CFDataAppend(modifiedExternalData, pubExternalData); | |
693 | *CFDataGetMutableBytePtr(modifiedExternalData) ^= 0xff; | |
694 | ||
695 | CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPublic); | |
696 | dataKey = SecKeyCreateWithData(modifiedExternalData, kcwd, &error); | |
697 | ok(!dataKey, "pub key SecKeyCreateWithData succeeded with invalid external data"); | |
698 | CFReleaseNull(error); | |
699 | CFReleaseNull(dataKey); | |
700 | ||
701 | CFReleaseNull(modifiedExternalData); | |
702 | } | |
703 | } | |
704 | ||
705 | SKIP: { | |
706 | skip("invalid pub key external data", 1, pubExternalData); | |
707 | ||
708 | CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPrivate); | |
709 | dataKey = SecKeyCreateWithData(pubExternalData, kcwd, &error); | |
710 | ok(!dataKey, "priv key SecKeyCreateWithData succeeded with public external data"); | |
711 | CFReleaseNull(error); | |
712 | CFReleaseNull(dataKey); | |
713 | ||
714 | CFReleaseNull(pubExternalData); | |
715 | } | |
716 | ||
717 | SKIP: { | |
718 | skip("invalid priv key external data", 1, privExternalData); | |
719 | ||
720 | CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPublic); | |
721 | dataKey = SecKeyCreateWithData(privExternalData, kcwd, &error); | |
722 | ok(!dataKey, "pub key SecKeyCreateWithData succeeded with private external data"); | |
723 | CFReleaseNull(error); | |
724 | CFReleaseNull(dataKey); | |
725 | ||
726 | CFReleaseNull(privExternalData); | |
727 | } | |
728 | ||
729 | CFReleaseNull(kcwd); | |
730 | CFReleaseNull(pubKey); | |
731 | CFReleaseNull(privKey); | |
732 | } | |
733 | ||
734 | static void testcopyattributes(unsigned long keySizeInBits) | |
735 | { | |
736 | size_t keySizeInBytes = (keySizeInBits + 7) / 8; | |
737 | int32_t keysz32 = (int32_t)keySizeInBits; | |
738 | ||
739 | CFNumberRef kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); | |
740 | CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, | |
741 | kSecAttrKeyType, kSecAttrKeyTypeEC, | |
742 | kSecAttrKeySizeInBits, kzib, | |
743 | kSecAttrIsPermanent, kCFBooleanFalse, | |
744 | NULL); | |
745 | SecKeyRef pubKey = NULL, privKey = NULL; | |
746 | OSStatus status; | |
747 | ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), | |
748 | "Generate %ld bit (%ld byte) EC keypair (status = %d)", | |
749 | keySizeInBits, keySizeInBytes, (int)status); | |
750 | CFReleaseNull(kgp); | |
751 | ||
752 | CFDictionaryRef attributes; | |
753 | CFTypeRef attrValue = NULL, privAppLabel = NULL, pubAppLabel = NULL; | |
754 | ||
755 | { // privKey | |
756 | attributes = SecKeyCopyAttributes(privKey); | |
757 | ok(attributes && CFGetTypeID(attributes) == CFDictionaryGetTypeID(), | |
758 | "priv key SecKeyCopyAttributes failed"); | |
759 | ||
760 | SKIP: { | |
761 | skip("invalid attributes", 8, attributes); | |
762 | ||
763 | attrValue = CFDictionaryGetValue(attributes, kSecAttrCanEncrypt); | |
764 | eq_cf(attrValue, kCFBooleanFalse, "invalid priv key kSecAttrCanEncrypt"); | |
765 | ||
766 | attrValue = CFDictionaryGetValue(attributes, kSecAttrCanDecrypt); | |
767 | eq_cf(attrValue, kCFBooleanTrue, "invalid priv key kSecAttrCanDecrypt"); | |
768 | ||
769 | attrValue = CFDictionaryGetValue(attributes, kSecAttrCanDerive); | |
770 | eq_cf(attrValue, kCFBooleanTrue, "invalid priv key kSecAttrCanDerive"); | |
771 | ||
772 | attrValue = CFDictionaryGetValue(attributes, kSecAttrCanSign); | |
773 | eq_cf(attrValue, kCFBooleanTrue, "invalid priv key kSecAttrCanSign"); | |
774 | ||
775 | attrValue = CFDictionaryGetValue(attributes, kSecAttrCanVerify); | |
776 | eq_cf(attrValue, kCFBooleanFalse, "invalid priv key kSecAttrCanVerify"); | |
777 | ||
778 | attrValue = CFDictionaryGetValue(attributes, kSecAttrKeyClass); | |
779 | eq_cf(attrValue, kSecAttrKeyClassPrivate, "priv key invalid kSecAttrKeyClass"); | |
780 | ||
781 | attrValue = CFDictionaryGetValue(attributes, kSecAttrKeyType); | |
782 | eq_cf(attrValue, kSecAttrKeyTypeEC, "invalid priv key kSecAttrKeyType"); | |
783 | ||
784 | attrValue = CFDictionaryGetValue(attributes, kSecAttrKeySizeInBits); | |
785 | eq_cf(attrValue, kzib, "invalid priv key kSecAttrKeySizeInBits"); | |
786 | ||
787 | privAppLabel = CFDictionaryGetValue(attributes, kSecAttrApplicationLabel); | |
788 | CFRetainSafe(privAppLabel); | |
789 | ||
790 | CFReleaseNull(attributes); | |
791 | } | |
792 | } | |
793 | ||
794 | { // pubKey | |
795 | attributes = SecKeyCopyAttributes(pubKey); | |
796 | ok(attributes && CFGetTypeID(attributes) == CFDictionaryGetTypeID(), | |
797 | "pub key SecKeyCopyAttributes failed"); | |
798 | ||
799 | SKIP: { | |
800 | skip("invalid attributes", 8, attributes); | |
801 | ||
802 | attrValue = CFDictionaryGetValue(attributes, kSecAttrCanEncrypt); | |
803 | eq_cf(attrValue, kCFBooleanTrue, "pub key invalid kSecAttrCanEncrypt"); | |
804 | ||
805 | attrValue = CFDictionaryGetValue(attributes, kSecAttrCanDecrypt); | |
806 | eq_cf(attrValue, kCFBooleanFalse, "pub key invalid kSecAttrCanDecrypt"); | |
807 | ||
808 | attrValue = CFDictionaryGetValue(attributes, kSecAttrCanDerive); | |
809 | eq_cf(attrValue, kCFBooleanFalse, "pub key invalid kSecAttrCanDerive"); | |
810 | ||
811 | attrValue = CFDictionaryGetValue(attributes, kSecAttrCanSign); | |
812 | eq_cf(attrValue, kCFBooleanFalse, "pub key invalid kSecAttrCanSign"); | |
813 | ||
814 | attrValue = CFDictionaryGetValue(attributes, kSecAttrCanVerify); | |
815 | eq_cf(attrValue, kCFBooleanTrue, "pub key invalid kSecAttrCanVerify"); | |
816 | ||
817 | attrValue = CFDictionaryGetValue(attributes, kSecAttrKeyClass); | |
818 | eq_cf(attrValue, kSecAttrKeyClassPublic, "pub key invalid kSecAttrKeyClass"); | |
819 | ||
820 | attrValue = CFDictionaryGetValue(attributes, kSecAttrKeyType); | |
821 | eq_cf(attrValue, kSecAttrKeyTypeEC, "pub key invalid kSecAttrKeyType"); | |
822 | ||
823 | attrValue = CFDictionaryGetValue(attributes, kSecAttrKeySizeInBits); | |
824 | eq_cf(attrValue, kzib, "pub key invalid kSecAttrKeySizeInBits"); | |
825 | ||
826 | pubAppLabel = CFDictionaryGetValue(attributes, kSecAttrApplicationLabel); | |
827 | CFRetainSafe(pubAppLabel); | |
828 | ||
829 | CFReleaseNull(attributes); | |
830 | } | |
831 | } | |
832 | ||
833 | eq_cf(privAppLabel, pubAppLabel, "priv key and pub key kSecAttrApplicationLabel differ"); | |
834 | ||
835 | CFReleaseNull(privAppLabel); | |
836 | CFReleaseNull(pubAppLabel); | |
837 | CFReleaseNull(kzib); | |
838 | CFReleaseNull(pubKey); | |
839 | CFReleaseNull(privKey); | |
840 | } | |
841 | ||
842 | static void testcopypublickey(unsigned long keySizeInBits) | |
843 | { | |
844 | size_t keySizeInBytes = (keySizeInBits + 7) / 8; | |
845 | int32_t keysz32 = (int32_t)keySizeInBits; | |
846 | ||
847 | CFNumberRef kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); | |
848 | CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, | |
849 | kSecAttrKeyType, kSecAttrKeyTypeEC, | |
850 | kSecAttrKeySizeInBits, kzib, | |
851 | kSecAttrIsPermanent, kCFBooleanFalse, | |
852 | NULL); | |
853 | CFReleaseNull(kzib); | |
854 | ||
855 | SecKeyRef pubKey = NULL, privKey = NULL; | |
856 | OSStatus status; | |
857 | ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), | |
858 | "Generate %ld bit (%ld byte) EC keypair (status = %d)", | |
859 | keySizeInBits, keySizeInBytes, (int)status); | |
860 | CFReleaseNull(kgp); | |
861 | ||
862 | SecKeyRef pubKeyCopy = NULL; | |
863 | ||
864 | { // privKey | |
865 | pubKeyCopy = SecKeyCopyPublicKey(privKey); | |
866 | ok(pubKeyCopy, "priv key SecKeyCopyPublicKey failed"); | |
867 | eq_cf(pubKeyCopy, pubKey, "pub key from priv key SecKeyCopyPublicKey and pub key differ"); | |
868 | CFReleaseNull(pubKeyCopy); | |
869 | } | |
870 | ||
871 | { // pubKey | |
872 | pubKeyCopy = SecKeyCopyPublicKey(pubKey); | |
873 | ok(pubKeyCopy, "pub key SecKeyCopyPublicKey failed"); | |
874 | eq_cf(pubKeyCopy, pubKey, "pub key from pub key SecKeyCopyPublicKey and pub key differ"); | |
875 | CFReleaseNull(pubKeyCopy); | |
876 | } | |
877 | ||
878 | CFReleaseNull(pubKey); | |
879 | CFReleaseNull(privKey); | |
880 | } | |
881 | ||
882 | static void testsignverify(unsigned long keySizeInBits) | |
883 | { | |
884 | size_t keySizeInBytes = (keySizeInBits + 7) / 8; | |
885 | int32_t keysz32 = (int32_t)keySizeInBits; | |
886 | ||
887 | CFNumberRef kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); | |
888 | CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, | |
889 | kSecAttrKeyType, kSecAttrKeyTypeEC, | |
890 | kSecAttrKeySizeInBits, kzib, | |
891 | kSecAttrIsPermanent, kCFBooleanFalse, | |
892 | NULL); | |
893 | CFReleaseNull(kzib); | |
894 | ||
895 | SecKeyRef pubKey = NULL, privKey = NULL; | |
896 | OSStatus status; | |
897 | ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), | |
898 | "Generate %ld bit (%ld byte) EC keypair (status = %d)", | |
899 | keySizeInBits, keySizeInBytes, (int)status); | |
900 | CFReleaseNull(kgp); | |
901 | ||
902 | SecKeyAlgorithm algorithms[] = { | |
903 | kSecKeyAlgorithmECDSASignatureRFC4754, | |
904 | kSecKeyAlgorithmECDSASignatureDigestX962, | |
905 | kSecKeyAlgorithmECDSASignatureMessageX962SHA1, | |
906 | kSecKeyAlgorithmECDSASignatureMessageX962SHA224, | |
907 | kSecKeyAlgorithmECDSASignatureMessageX962SHA256, | |
908 | kSecKeyAlgorithmECDSASignatureMessageX962SHA384, | |
909 | kSecKeyAlgorithmECDSASignatureMessageX962SHA512 | |
910 | }; | |
911 | ||
912 | CFDataRef testData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, CFSTR("test"), kCFStringEncodingUTF8, 0); | |
913 | ok(testData, "creating test data failed"); | |
914 | ||
915 | SKIP: { | |
916 | skip("invalid test data", 51, status == errSecSuccess && testData); | |
917 | ||
918 | CFErrorRef error = NULL; | |
919 | ||
920 | for (uint32_t ix = 0; ix < array_size(algorithms); ++ix) { | |
921 | SecKeyAlgorithm algorithm = algorithms[ix]; | |
922 | SecKeyAlgorithm incompatibleAlgorithm = CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureRFC4754) ? | |
923 | kSecKeyAlgorithmECDSASignatureDigestX962 : kSecKeyAlgorithmECDSASignatureRFC4754; | |
924 | ||
925 | CFDataRef dataToSign = NULL; | |
926 | if (CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureRFC4754) || | |
927 | CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureDigestX962)) { | |
928 | dataToSign = CFDataCreateWithHash(kCFAllocatorDefault, ccsha256_di(), | |
929 | CFDataGetBytePtr(testData), CFDataGetLength(testData)); | |
930 | ok(dataToSign, "creating digest failed for algorithm %d", (int)algorithm); | |
931 | CFReleaseNull(error); | |
932 | } | |
933 | else { | |
934 | CFRetainAssign(dataToSign, testData); | |
935 | } | |
936 | ||
937 | SKIP: { | |
938 | skip("invalid data to sign", 7, dataToSign != NULL); | |
939 | ||
940 | CFDataRef signature = SecKeyCreateSignature(pubKey, algorithm, dataToSign, &error); | |
941 | ok(!signature, "SecKeyCopySignature succeeded with pub key for algorithm %d", (int)algorithm); | |
942 | CFReleaseNull(error); | |
943 | CFReleaseNull(signature); | |
944 | ||
945 | signature = SecKeyCreateSignature(privKey, algorithm, dataToSign, &error); | |
946 | ok(signature, "SecKeyCopySignature failed for algorithm %d", (int)algorithm); | |
947 | CFReleaseNull(error); | |
948 | ||
949 | SKIP: { | |
950 | skip("invalid signature", 5, signature != NULL); | |
951 | ||
952 | ok(!SecKeyVerifySignature(privKey, algorithm, dataToSign, signature, &error), | |
953 | "SecKeyVerifySignature succeeded with priv key for %d", (int)algorithm); | |
954 | CFReleaseNull(error); | |
955 | ||
956 | ok(!SecKeyVerifySignature(pubKey, incompatibleAlgorithm, dataToSign, signature, &error), | |
957 | "SecKeyVerifySignature succeeded with wrong algorithm for %d", (int)algorithm); | |
958 | CFReleaseNull(error); | |
959 | ||
960 | ok(SecKeyVerifySignature(pubKey, algorithm, dataToSign, signature, &error), | |
961 | "SecKeyVerifySignature failed for algorithm %d", (int)algorithm); | |
962 | CFReleaseNull(error); | |
963 | ||
964 | CFMutableDataRef modifiedSignature = CFDataCreateMutable(kCFAllocatorDefault, 0); | |
965 | CFDataAppend(modifiedSignature, signature); | |
966 | *CFDataGetMutableBytePtr(modifiedSignature) ^= 0xff; | |
967 | ||
968 | ok(!SecKeyVerifySignature(pubKey, algorithm, dataToSign, modifiedSignature, &error), | |
969 | "SecKeyVerifySignature succeeded with bad signature for algorithm %d", (int)algorithm); | |
970 | CFReleaseNull(error); | |
971 | ||
972 | CFMutableDataRef modifiedDataToSign = CFDataCreateMutable(kCFAllocatorDefault, 0); | |
973 | CFDataAppend(modifiedDataToSign, dataToSign); | |
974 | *CFDataGetMutableBytePtr(modifiedDataToSign) ^= 0xff; | |
975 | ||
976 | ok(!SecKeyVerifySignature(pubKey, algorithm, modifiedDataToSign, signature, &error), | |
977 | "SecKeyVerifySignature succeeded with bad data for %d", (int)algorithm); | |
978 | CFReleaseNull(error); | |
979 | ||
980 | CFReleaseNull(modifiedDataToSign); | |
981 | CFReleaseNull(modifiedSignature); | |
982 | ||
983 | CFReleaseNull(signature); | |
984 | } | |
985 | CFReleaseNull(dataToSign); | |
986 | } | |
987 | } | |
988 | } | |
989 | ||
990 | CFReleaseNull(testData); | |
991 | CFReleaseNull(pubKey); | |
992 | CFReleaseNull(privKey); | |
993 | } | |
994 | ||
427c49bc A |
995 | /* Test basic add delete update copy matching stuff. */ |
996 | static void tests(void) | |
997 | { | |
5c19dc3a A |
998 | testsignformat(); |
999 | ||
427c49bc A |
1000 | testkeygen(192); |
1001 | testkeygen(224); | |
1002 | testkeygen(256); | |
1003 | testkeygen(384); | |
1004 | testkeygen(521); | |
1005 | ||
1006 | testkeygen2(192); | |
1007 | testkeygen2(224); | |
1008 | testkeygen2(256); | |
1009 | testkeygen2(384); | |
1010 | testkeygen2(521); | |
1011 | ||
d8f41ccd A |
1012 | testkeywrap(256, _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128); |
1013 | testkeywrap(521, _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128); | |
1014 | testkeywrap(256, _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256); | |
1015 | testkeywrap(521, _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256); | |
1016 | ||
fa7225c8 A |
1017 | testkeyexchange(192); |
1018 | testkeyexchange(224); | |
1019 | testkeyexchange(256); | |
1020 | testkeyexchange(384); | |
1021 | testkeyexchange(521); | |
1022 | ||
1023 | testsupportedalgos(192); | |
1024 | testcreatewithdata(192); | |
1025 | testcopyattributes(192); | |
1026 | testcopypublickey(192); | |
1027 | testsignverify(192); | |
427c49bc A |
1028 | } |
1029 | ||
1030 | int si_41_sececkey(int argc, char *const *argv) | |
1031 | { | |
fa7225c8 | 1032 | plan_tests(557); |
427c49bc A |
1033 | |
1034 | tests(); | |
1035 | ||
1036 | return 0; | |
1037 | } |