]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/Regressions/secitem/si-40-seckey.c
Security-59306.41.2.tar.gz
[apple/security.git] / OSX / sec / Security / Regressions / secitem / si-40-seckey.c
1 /*
2 * Copyright (c) 2007-2009,2012-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 <CoreFoundation/CoreFoundation.h>
26 #include <Security/SecCertificate.h>
27 #include <Security/SecCertificateInternal.h>
28 #include <Security/SecKey.h>
29 #include <Security/SecKeyPriv.h>
30 #include <Security/SecItem.h>
31 #include <Security/SecAsn1Types.h>
32 #include <Security/oidsalg.h>
33 #include <Security/SecureTransport.h>
34 #include <Security/SecRandom.h>
35 #include <utilities/array_size.h>
36 #include <utilities/SecCFWrappers.h>
37 #include <CommonCrypto/CommonDigest.h>
38 #include <libDER/libDER.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <corecrypto/ccsha1.h>
42 #include <corecrypto/ccsha2.h>
43
44 #include "Security_regressions.h"
45
46 #include "utilities/SecCFRelease.h"
47
48 static void testdigestandsignalg(SecKeyRef privKey, SecKeyRef pubKey, const SecAsn1AlgId *algId) {
49 uint8_t dataToDigest[256] = {0,};
50 size_t dataToDigestLen = sizeof(dataToDigest);
51 size_t sigLen = SecKeyGetSize(privKey, kSecKeySignatureSize);
52 uint8_t sig[sigLen];
53
54 DERItem oid;
55 oid.length = algId->algorithm.Length;
56 oid.data = algId->algorithm.Data;
57
58 /* Get the oid in decimal for display purposes. */
59 CFStringRef oidStr = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, &oid);
60 char oidBuf[40];
61 CFStringGetCString(oidStr, oidBuf, sizeof(oidBuf), kCFStringEncodingUTF8);
62 CFRelease(oidStr);
63
64 SKIP: {
65 OSStatus status;
66
67 /* Time to sign. */
68 ok_status(status = SecKeyDigestAndSign(privKey, algId, dataToDigest, dataToDigestLen,
69 sig, &sigLen), "digest and sign %s with %ld bit RSA key", oidBuf, sigLen * 8);
70
71 skip("SecKeyDigestAndSign failed", 3, status == errSecSuccess);
72
73 /* Verify the signature we just made. */
74 ok_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen,
75 sig, sigLen), "digest and verify");
76 /* Invalidate the signature. */
77 /* Tweak the least-significant bit to avoid putting the signature out of range. */
78 sig[sigLen-1] ^= 1;
79 is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen,
80 sig, sigLen), errSSLCrypto, "digest and verify bad sig");
81 sig[sigLen-1] ^= 1;
82 dataToDigest[0] ^= 0xff;
83 is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen,
84 sig, sigLen), errSSLCrypto, "digest and verify bad digest");
85 }
86 }
87
88 static void testdigestandsign(SecKeyRef privKey, SecKeyRef pubKey) {
89 static const SecAsn1Oid *oids[] = {
90 &CSSMOID_SHA1WithRSA,
91 &CSSMOID_SHA224WithRSA,
92 &CSSMOID_SHA256WithRSA,
93 &CSSMOID_SHA384WithRSA,
94 &CSSMOID_SHA512WithRSA,
95 #if 0
96 &CSSMOID_SHA1WithRSA_OIW,
97 &CSSMOID_SHA1WithDSA, // BSAFE
98 &CSSMOID_SHA1WithDSA_CMS, // X509/CMS
99 &CSSMOID_SHA1WithDSA_JDK, // JDK 1.1
100 #endif
101 };
102
103
104 uint32_t ix;
105 SecAsn1AlgId algId = {};
106 for (ix = 0; ix < array_size(oids); ++ix) {
107 if (oids[ix]) {
108 algId.algorithm = *oids[ix];
109 } else {
110 algId.algorithm.Length = 0;
111 algId.algorithm.Data = NULL;
112 }
113
114 testdigestandsignalg(privKey, pubKey, &algId);
115 }
116 }
117
118 #if 0
119 static void dump_bytes(uint8_t* bytes, size_t amount)
120 {
121 while (amount > 0) {
122 printf("0x%02x ", *bytes);
123 ++bytes;
124 --amount;
125 }
126 }
127 #endif
128
129 #define kEncryptDecryptTestCount 6
130 static void test_encrypt_decrypt(SecKeyRef pubKey, SecKeyRef privKey, uint32_t padding, size_t keySizeInBytes)
131 {
132 SKIP: {
133 size_t max_len = keySizeInBytes;
134 switch (padding) {
135 case kSecPaddingNone: max_len = keySizeInBytes; break;
136 case kSecPaddingOAEP: max_len = keySizeInBytes - 2 - 2 * CC_SHA1_DIGEST_LENGTH; break;
137 case kSecPaddingPKCS1: max_len = keySizeInBytes - 11; break;
138 default: skip("what is the max_len for this padding?", 5, false);
139 }
140
141 uint8_t secret[max_len + 2], encrypted_secret[keySizeInBytes], decrypted_secret[keySizeInBytes];
142 uint8_t *secret_ptr = secret;
143 size_t secret_len = max_len;
144 size_t encrypted_secret_len = sizeof(encrypted_secret);
145 size_t decrypted_secret_len = sizeof(decrypted_secret);
146 memset(decrypted_secret, 0xff, decrypted_secret_len);
147 ok_status(SecRandomCopyBytes(kSecRandomDefault, sizeof(secret), secret),"rng");
148
149 // zero pad, no accidental second zero byte
150 if (padding == kSecPaddingNone) {
151 secret[0] = 0;
152 secret[1] = 128;
153 }
154
155 is_status(SecKeyEncrypt(pubKey, padding,
156 secret, sizeof(secret),
157 encrypted_secret, &encrypted_secret_len), errSecParam, "encrypt secret (overflow)");
158 ok_status(SecKeyEncrypt(pubKey, padding,
159 secret, secret_len,
160 encrypted_secret, &encrypted_secret_len), "encrypt secret");
161
162 ok_status(SecKeyDecrypt(privKey, padding,
163 encrypted_secret, encrypted_secret_len,
164 decrypted_secret, &decrypted_secret_len), "decrypt secret");
165
166 // zero padding is removed on decode
167 if (padding == kSecPaddingNone) {
168 secret_len--;
169 secret_ptr++;
170 }
171
172 ok(decrypted_secret_len == secret_len, "correct length");
173 ok_status(memcmp(secret_ptr, decrypted_secret, secret_len), "verify secret");
174 }
175 }
176
177 #define kKeyGenTestCount (50 + (3*kEncryptDecryptTestCount))
178 static void testkeygen(size_t keySizeInBits) {
179 SecKeyRef pubKey = NULL, privKey = NULL;
180 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
181 CFNumberRef kzib;
182
183 int32_t iKeySizeInBits = (int32_t) keySizeInBits;
184 kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &iKeySizeInBits);
185 CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
186 CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA);
187 CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib);
188
189 OSStatus status;
190 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
191 "Generate %ld bit (%ld byte) RSA keypair", keySizeInBits,
192 keySizeInBytes);
193 CFRelease(kzib);
194 CFRelease(kgp);
195
196 SKIP: {
197 skip("keygen failed", 8, status == errSecSuccess);
198 ok(pubKey, "pubkey returned");
199 ok(privKey, "privKey returned");
200 is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok");
201 is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok");
202
203 /* Sign something. */
204 uint8_t something[keySizeInBytes];
205 size_t something_len = keySizeInBytes - 11;
206 ok_status(SecRandomCopyBytes(kSecRandomDefault, sizeof(something), something),"rng");
207 uint8_t sig[keySizeInBytes];
208 size_t sigLen = sizeof(sig);
209 if (privKey != NULL && pubKey != NULL) {
210 is_status(SecKeyRawSign(privKey, kSecPaddingPKCS1,
211 something, something_len + 1, sig, &sigLen),
212 errSecParam, "sign overflow");
213 ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1,
214 something, something_len, sig, &sigLen), "sign something");
215 ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1,
216 something, something_len, sig, sigLen), "verify sig on something");
217
218 // Torture test ASN.1 encoder by setting high bit to 1.
219 uint8_t digest[CC_SHA512_DIGEST_LENGTH] = {
220 0x80, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
221 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
222 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
223 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
224 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
225 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
226 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
227 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
228 };
229 //CC_MD2(something, sizeof(something), digest);
230 ok_status(!SecKeyRawSign(privKey, kSecPaddingPKCS1MD2,
231 digest, CC_MD2_DIGEST_LENGTH, sig, &sigLen),
232 "don't sign md2 digest");
233 ok_status(!SecKeyRawVerify(pubKey, kSecPaddingPKCS1MD2,
234 digest, CC_MD2_DIGEST_LENGTH, sig, sigLen),
235 "verify sig on md2 digest fails");
236
237 //CC_MD5(something, sizeof(something), digest);
238 sigLen = sizeof(sig);
239 ok_status(!SecKeyRawSign(privKey, kSecPaddingPKCS1MD5,
240 digest, CC_MD5_DIGEST_LENGTH, sig, &sigLen),
241 "don't sign md5 digest");
242 ok_status(!SecKeyRawVerify(pubKey, kSecPaddingPKCS1MD5,
243 digest, CC_MD5_DIGEST_LENGTH, sig, sigLen),
244 "verify sig on md5 digest fails");
245
246 //CCDigest(kCCDigestSHA1, something, sizeof(something), digest);
247 sigLen = sizeof(sig);
248 ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA1,
249 digest, CC_SHA1_DIGEST_LENGTH, sig, &sigLen),
250 "sign sha1 digest");
251 ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA1,
252 digest, CC_SHA1_DIGEST_LENGTH, sig, sigLen),
253 "verify sig on sha1 digest");
254
255 uint8_t signature[keySizeInBytes], *ptr = signature;
256 size_t signature_len = sizeof(signature);
257 ok_status(SecKeyDecrypt(pubKey, kSecPaddingNone, sig, sigLen, signature, &signature_len), "inspect signature");
258 is(signature_len, keySizeInBytes - 1, "got signature");
259 while(*ptr && ((size_t)(ptr - signature) < signature_len)) ptr++;
260 is(signature + signature_len - ptr, 16 /* length(\0 || OID_SHA1) */ + CC_SHA1_DIGEST_LENGTH, "successful decode");
261
262 /* PKCS1 padding is 00 01 PAD * 8 or more 00 data.
263 data is SEQ { SEQ { OID NULL } BIT STRING 00 DIGEST }
264 So min data + pad overhead is 11 + 9 + oidlen
265 oidlen = 11 for the sha2 family of oids, so we have 29 bytes; or
266 232 bits of minimum overhead. */
267 const size_t pkcs1Overhead = 232;
268 if (keySizeInBits > 224 + pkcs1Overhead) {
269 //CC_SHA224(something, sizeof(something), digest);
270 sigLen = sizeof(sig);
271 ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA224,
272 digest, CC_SHA224_DIGEST_LENGTH, sig, &sigLen),
273 "sign sha224 digest");
274 ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA224,
275 digest, CC_SHA224_DIGEST_LENGTH, sig, sigLen),
276 "verify sig on sha224 digest");
277 }
278
279 if (keySizeInBits > 256 + pkcs1Overhead) {
280 //CC_SHA256(something, sizeof(something), digest);
281 sigLen = sizeof(sig);
282 ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA256,
283 digest, CC_SHA256_DIGEST_LENGTH, sig, &sigLen),
284 "sign sha256 digest");
285 ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA256,
286 digest, CC_SHA256_DIGEST_LENGTH, sig, sigLen),
287 "verify sig on sha256 digest");
288 }
289
290 if (keySizeInBits > 384 + pkcs1Overhead) {
291 //CC_SHA384(something, sizeof(something), digest);
292 sigLen = sizeof(sig);
293 ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA384,
294 digest, CC_SHA384_DIGEST_LENGTH, sig, &sigLen),
295 "sign sha384 digest");
296 ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA384,
297 digest, CC_SHA384_DIGEST_LENGTH, sig, sigLen),
298 "verify sig on sha384 digest");
299 }
300
301 if (keySizeInBits > 512 + pkcs1Overhead) {
302 //CC_SHA512(something, sizeof(something), digest);
303 sigLen = sizeof(sig);
304 ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA512,
305 digest, CC_SHA512_DIGEST_LENGTH, sig, &sigLen),
306 "sign sha512 digest");
307 ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA512,
308 digest, CC_SHA512_DIGEST_LENGTH, sig, sigLen),
309 "verify sig on sha512 digest");
310 }
311 }
312
313 test_encrypt_decrypt(pubKey, privKey, kSecPaddingNone, keySizeInBytes);
314 test_encrypt_decrypt(pubKey, privKey, kSecPaddingPKCS1, keySizeInBytes);
315 test_encrypt_decrypt(pubKey, privKey, kSecPaddingOAEP, keySizeInBytes);
316
317 testdigestandsign(privKey, pubKey);
318
319 const void *privkeys[] = {
320 kSecValueRef
321 };
322 const void *privvalues[] = {
323 privKey
324 };
325 CFDictionaryRef privitem = CFDictionaryCreate(NULL, privkeys, privvalues,
326 array_size(privkeys), NULL, NULL);
327 ok_status(SecItemAdd(privitem, NULL), "add private key");
328 ok_status(SecItemDelete(privitem), "delete private key");
329 CFReleaseNull(privitem);
330
331 const void *pubkeys[] = {
332 kSecValueRef
333 };
334 const void *pubvalues[] = {
335 pubKey
336 };
337 CFDictionaryRef pubitem = CFDictionaryCreate(NULL, pubkeys, pubvalues,
338 array_size(pubkeys), NULL, NULL);
339 ok_status(SecItemAdd(pubitem, NULL), "add public key");
340 ok_status(SecItemDelete(pubitem), "delete public key");
341 CFReleaseNull(pubitem);
342
343 /* Cleanup. */
344 CFReleaseNull(pubKey);
345 CFReleaseNull(privKey);
346 }
347 }
348
349 #define kKeyGen2TestCount 12
350 static void testkeygen2(size_t keySizeInBits) {
351 SecKeyRef pubKey = NULL, privKey = NULL;
352 int32_t keySizeInBytes = (int32_t)((keySizeInBits + 7) / 8);
353 CFNumberRef kzib;
354
355 CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault);
356 CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID);
357 CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString);
358 CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString);
359
360 CFReleaseNull(ourUUID);
361 CFReleaseNull(uuidString);
362
363 CFStringAppend(publicName, CFSTR("-Public-40"));
364 CFStringAppend(privateName, CFSTR("-Private-40"));
365 CFMutableDictionaryRef pubd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
366 CFMutableDictionaryRef privd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
367
368 CFDictionaryAddValue(pubd, kSecAttrLabel, publicName);
369 CFDictionaryAddValue(privd, kSecAttrLabel, privateName);
370
371 int32_t iKeySizeInBits = (int32_t) keySizeInBits;
372 kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &iKeySizeInBits);
373 CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
374 CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA);
375 CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib);
376 CFDictionaryAddValue(kgp, kSecAttrIsPermanent, kCFBooleanTrue);
377 CFDictionaryAddValue(kgp, kSecPublicKeyAttrs, pubd);
378 CFDictionaryAddValue(kgp, kSecPrivateKeyAttrs, privd);
379
380 OSStatus status;
381 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
382 "Generate %d bit (%d byte) persistent RSA keypair",
383 (int)keySizeInBits, (int)keySizeInBytes);
384 CFRelease(kzib);
385 CFRelease(kgp);
386
387 SKIP: {
388 skip("keygen failed", 8, status == errSecSuccess);
389 ok(pubKey, "pubkey returned");
390 ok(privKey, "privKey returned");
391 is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok");
392 is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok");
393
394 SecKeyRef pubKey2, privKey2;
395 CFDictionaryAddValue(pubd, kSecClass, kSecClassKey);
396 CFDictionaryAddValue(pubd, kSecReturnRef, kCFBooleanTrue);
397 CFDictionaryAddValue(privd, kSecClass, kSecClassKey);
398 CFDictionaryAddValue(privd, kSecReturnRef, kCFBooleanTrue);
399 CFDictionaryAddValue(privd, kSecAttrCanSign, kCFBooleanTrue);
400 ok_status(SecItemCopyMatching(pubd, (CFTypeRef *)&pubKey2),
401 "retrieve pub key by label");
402 ok_status(SecItemCopyMatching(privd, (CFTypeRef *)&privKey2),
403 "retrieve priv key by label and kSecAttrCanSign");
404
405 /* Sign something. */
406 uint8_t something[50] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
407 uint8_t sig[keySizeInBytes];
408 size_t sigLen = keySizeInBytes;
409 ok_status(SecKeyRawSign(privKey2, kSecPaddingPKCS1,
410 something, sizeof(something), sig, &sigLen), "sign something");
411 ok_status(SecKeyRawVerify(pubKey2, kSecPaddingPKCS1,
412 something, sizeof(something), sig, sigLen), "verify sig on something");
413
414 sigLen = keySizeInBytes;
415 is_status(SecKeyEncrypt(pubKey2, kSecPaddingPKCS1SHA1,
416 something, sizeof(something), sig, &sigLen), errSecParam,
417 "encrypt something with invalid padding");
418
419 /* Cleanup. */
420 CFReleaseNull(pubKey2);
421 CFReleaseNull(privKey2);
422
423 /* delete from keychain - note: do it before releasing publicName and privateName
424 because pubd and privd have no retain/release callbacks */
425 ok_status(SecItemDelete(pubd), "delete generated pub key");
426 ok_status(SecItemDelete(privd), "delete generated priv key");
427 }
428
429 /* Cleanup. */
430 CFReleaseNull(pubKey);
431 CFReleaseNull(privKey);
432
433 CFReleaseNull(publicName);
434 CFReleaseNull(privateName);
435
436 CFRelease(pubd);
437 CFRelease(privd);
438 }
439
440 static const int kTestSupportedCount = 3 + (4 * 11) + 2 + (4 * 5);
441 static void testsupportedalgos(size_t keySizeInBits)
442 {
443 SecKeyRef pubKey = NULL, privKey = NULL;
444 int32_t keySizeInBytes = (int)((keySizeInBits + 7) / 8);
445 CFNumberRef kzib;
446
447 int32_t iKeySizeInBits = (int32_t) keySizeInBits;
448 kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &iKeySizeInBits);
449 CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
450 CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA);
451 CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib);
452
453 OSStatus status;
454 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
455 "Generate %d bit (%d byte) persistent RSA keypair",
456 (int)keySizeInBits, (int)keySizeInBytes);
457 CFRelease(kzib);
458 CFRelease(kgp);
459
460 is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok");
461 is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok");
462
463 const SecKeyAlgorithm sign[] = {
464 kSecKeyAlgorithmRSASignatureRaw,
465 kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1,
466 kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1,
467 kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224,
468 kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224,
469 kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256,
470 kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256,
471 kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384,
472 kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384,
473 kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512,
474 kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512,
475 };
476
477 for (size_t i = 0; i < array_size(sign); i++) {
478 ok(SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeSign, sign[i]),
479 "privKey supports sign algorithm %@", sign[i]);
480 ok(SecKeyIsAlgorithmSupported(pubKey, kSecKeyOperationTypeVerify, sign[i]),
481 "pubKey supports verify algorithm %@", sign[i]);
482 // Our privKey actually supports even verify operation because it is adapter over decrypt...
483 ok(SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeVerify, sign[i]),
484 "privKey supports verify algorithm %@", sign[i]);
485 ok(!SecKeyIsAlgorithmSupported(pubKey, kSecKeyOperationTypeSign, sign[i]),
486 "pubKey doesn't support verify algorithm %@", sign[i]);
487 }
488 ok(!SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeSign, kSecKeyAlgorithmECDSASignatureDigestX962),
489 "RSA privKey does not support ECDSA algorithm");
490 ok(!SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeVerify, kSecKeyAlgorithmECDSASignatureDigestX962),
491 "RSA pubKey does not support ECDSA algorithm");
492
493 const SecKeyAlgorithm crypt[] = {
494 kSecKeyAlgorithmRSAEncryptionRaw,
495 kSecKeyAlgorithmRSAEncryptionPKCS1,
496 kSecKeyAlgorithmRSAEncryptionOAEPSHA1,
497 kSecKeyAlgorithmRSAEncryptionOAEPSHA224,
498 kSecKeyAlgorithmRSAEncryptionOAEPSHA256,
499 // kSecKeyAlgorithmRSAEncryptionOAEPSHA384,
500 // kSecKeyAlgorithmRSAEncryptionOAEPSHA512,
501 };
502 for (size_t i = 0; i < array_size(crypt); i++) {
503 ok(SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeDecrypt, crypt[i]),
504 "privKey supports decrypt algorithm %@", crypt[i]);
505 ok(SecKeyIsAlgorithmSupported(pubKey, kSecKeyOperationTypeEncrypt, crypt[i]),
506 "pubKey supports encrypt algorithm %@", crypt[i]);
507 ok(!SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeEncrypt, crypt[i]),
508 "privKey doesn't supports encrypt algorithm %@", crypt[i]);
509 ok(SecKeyIsAlgorithmSupported(pubKey, kSecKeyOperationTypeDecrypt, crypt[i]),
510 "pubKey supports decrypt algorithm %@", crypt[i]);
511 }
512
513 /* Cleanup. */
514 CFReleaseNull(pubKey);
515 CFReleaseNull(privKey);
516 }
517
518 #define kCreateWithDataTestCount 13
519 static void testcreatewithdata(unsigned long keySizeInBits)
520 {
521 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
522 int32_t keysz32 = (int32_t)keySizeInBits;
523
524 CFNumberRef kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32);
525 CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
526 kSecAttrKeyType, kSecAttrKeyTypeRSA,
527 kSecAttrKeySizeInBits, kzib,
528 kSecAttrIsPermanent, kCFBooleanFalse,
529 NULL);
530 SecKeyRef pubKey = NULL, privKey = NULL;
531 OSStatus status;
532 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
533 "Generate %ld bit (%ld byte) RSA keypair (status = %d)",
534 keySizeInBits, keySizeInBytes, (int)status);
535 CFReleaseNull(kgp);
536
537 CFMutableDictionaryRef kcwd = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault,
538 kSecAttrKeyType, kSecAttrKeyTypeRSA,
539 kSecAttrKeySizeInBits, kzib,
540 kSecAttrIsPermanent, kCFBooleanFalse,
541 NULL);
542 CFReleaseNull(kzib);
543
544 CFErrorRef error = NULL;
545 CFDataRef privExternalData = NULL, pubExternalData = NULL;
546 SecKeyRef dataKey = NULL;
547
548 { // privKey
549 privExternalData = SecKeyCopyExternalRepresentation(privKey, &error);
550 ok(privExternalData && CFGetTypeID(privExternalData) == CFDataGetTypeID(),
551 "priv key SecKeyCopyExternalRepresentation failed");
552 CFReleaseNull(error);
553
554 SKIP: {
555 skip("invalid priv key external data", 4, privExternalData);
556
557 CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPrivate);
558 dataKey = SecKeyCreateWithData(privExternalData, kcwd, &error);
559 ok(dataKey, "priv key SecKeyCreateWithData failed");
560 CFReleaseNull(error);
561
562 eq_cf(privKey, dataKey, "priv keys differ");
563 CFReleaseNull(dataKey);
564
565 CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPublic);
566 dataKey = SecKeyCreateWithData(privExternalData, kcwd, &error);
567 ok(!dataKey, "priv key SecKeyCreateWithData succeeded with invalid kSecAttrKeyClass");
568 CFReleaseNull(error);
569 CFReleaseNull(dataKey);
570
571 CFMutableDataRef modifiedExternalData = CFDataCreateMutable(kCFAllocatorDefault, 0);
572 CFDataAppend(modifiedExternalData, privExternalData);
573 *CFDataGetMutableBytePtr(modifiedExternalData) ^= 0xff;
574
575 CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPrivate);
576 dataKey = SecKeyCreateWithData(modifiedExternalData, kcwd, &error);
577 ok(!dataKey, "priv key SecKeyCreateWithData succeeded with invalid external data");
578 CFReleaseNull(error);
579 CFReleaseNull(dataKey);
580
581 CFReleaseNull(modifiedExternalData);
582 }
583 }
584
585 { // pubKey
586 pubExternalData = SecKeyCopyExternalRepresentation(pubKey, &error);
587 ok(pubExternalData && CFGetTypeID(pubExternalData) == CFDataGetTypeID(),
588 "pub key SecKeyCopyExternalRepresentation failed");
589 CFReleaseNull(error);
590
591 SKIP: {
592 skip("invalid pub key external data", 4, pubExternalData);
593
594 CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPublic);
595 dataKey = SecKeyCreateWithData(pubExternalData, kcwd, &error);
596 ok(dataKey, "pub key SecKeyCreateWithData failed");
597 CFReleaseNull(error);
598
599 eq_cf(pubKey, dataKey, "pub keys differ");
600 CFReleaseNull(dataKey);
601
602 CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPrivate);
603 dataKey = SecKeyCreateWithData(pubExternalData, kcwd, &error);
604 ok(!dataKey, "pub key SecKeyCreateWithData succeeded with invalid kSecAttrKeyClass");
605 CFReleaseNull(error);
606 CFReleaseNull(dataKey);
607
608 CFMutableDataRef modifiedExternalData = CFDataCreateMutable(kCFAllocatorDefault, 0);
609 CFDataAppend(modifiedExternalData, pubExternalData);
610 *CFDataGetMutableBytePtr(modifiedExternalData) ^= 0xff;
611
612 CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPublic);
613 dataKey = SecKeyCreateWithData(modifiedExternalData, kcwd, &error);
614 ok(!dataKey, "pub key SecKeyCreateWithData succeeded with invalid external data");
615 CFReleaseNull(error);
616 CFReleaseNull(dataKey);
617
618 CFReleaseNull(modifiedExternalData);
619 }
620 }
621
622 SKIP: {
623 skip("invalid pub key external data", 1, pubExternalData);
624
625 CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPrivate);
626 dataKey = SecKeyCreateWithData(pubExternalData, kcwd, &error);
627 ok(!dataKey, "priv key SecKeyCreateWithData succeeded with public external data");
628 CFReleaseNull(error);
629 CFReleaseNull(dataKey);
630
631 CFReleaseNull(pubExternalData);
632 }
633
634 SKIP: {
635 skip("invalid priv key external data", 1, privExternalData);
636
637 CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPublic);
638 dataKey = SecKeyCreateWithData(privExternalData, kcwd, &error);
639 ok(!dataKey, "pub key SecKeyCreateWithData succeeded with private external data");
640 CFReleaseNull(error);
641 CFReleaseNull(dataKey);
642
643 CFReleaseNull(privExternalData);
644 }
645
646 CFReleaseNull(kcwd);
647 CFReleaseNull(pubKey);
648 CFReleaseNull(privKey);
649 }
650
651 #define kCopyAttributesTestCount 20
652 static void testcopyattributes(unsigned long keySizeInBits)
653 {
654 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
655 int32_t keysz32 = (int32_t)keySizeInBits;
656
657 CFNumberRef kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32);
658 CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
659 kSecAttrKeyType, kSecAttrKeyTypeRSA,
660 kSecAttrKeySizeInBits, kzib,
661 kSecAttrIsPermanent, kCFBooleanFalse,
662 NULL);
663 SecKeyRef pubKey = NULL, privKey = NULL;
664 OSStatus status;
665 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
666 "Generate %ld bit (%ld byte) RSA keypair (status = %d)",
667 keySizeInBits, keySizeInBytes, (int)status);
668 CFReleaseNull(kgp);
669
670 CFDictionaryRef attributes;
671 CFTypeRef attrValue = NULL, privAppLabel = NULL, pubAppLabel = NULL;
672
673 { // privKey
674 attributes = SecKeyCopyAttributes(privKey);
675 ok(attributes && CFGetTypeID(attributes) == CFDictionaryGetTypeID(),
676 "priv key SecKeyCopyAttributes failed");
677
678 SKIP: {
679 skip("invalid attributes", 8, attributes);
680
681 attrValue = CFDictionaryGetValue(attributes, kSecAttrCanEncrypt);
682 eq_cf(attrValue, kCFBooleanFalse, "invalid priv key kSecAttrCanEncrypt");
683
684 attrValue = CFDictionaryGetValue(attributes, kSecAttrCanDecrypt);
685 eq_cf(attrValue, kCFBooleanTrue, "invalid priv key kSecAttrCanDecrypt");
686
687 attrValue = CFDictionaryGetValue(attributes, kSecAttrCanDerive);
688 eq_cf(attrValue, kCFBooleanFalse, "invalid priv key kSecAttrCanDerive");
689
690 attrValue = CFDictionaryGetValue(attributes, kSecAttrCanSign);
691 eq_cf(attrValue, kCFBooleanTrue, "invalid priv key kSecAttrCanSign");
692
693 attrValue = CFDictionaryGetValue(attributes, kSecAttrCanVerify);
694 eq_cf(attrValue, kCFBooleanFalse, "invalid priv key kSecAttrCanVerify");
695
696 attrValue = CFDictionaryGetValue(attributes, kSecAttrKeyClass);
697 eq_cf(attrValue, kSecAttrKeyClassPrivate, "priv key invalid kSecAttrKeyClass");
698
699 attrValue = CFDictionaryGetValue(attributes, kSecAttrKeyType);
700 eq_cf(attrValue, kSecAttrKeyTypeRSA, "invalid priv key kSecAttrKeyType");
701
702 attrValue = CFDictionaryGetValue(attributes, kSecAttrKeySizeInBits);
703 eq_cf(attrValue, kzib, "invalid priv key kSecAttrKeySizeInBits");
704
705 privAppLabel = CFDictionaryGetValue(attributes, kSecAttrApplicationLabel);
706 CFRetainSafe(privAppLabel);
707
708 CFReleaseNull(attributes);
709 }
710 }
711
712 { // pubKey
713 attributes = SecKeyCopyAttributes(pubKey);
714 ok(attributes && CFGetTypeID(attributes) == CFDictionaryGetTypeID(),
715 "pub key SecKeyCopyAttributes failed");
716
717 SKIP: {
718 skip("invalid attributes", 8, attributes);
719
720 attrValue = CFDictionaryGetValue(attributes, kSecAttrCanEncrypt);
721 eq_cf(attrValue, kCFBooleanTrue, "pub key invalid kSecAttrCanEncrypt");
722
723 // Although unusual, our RSA public key can even decrypt.
724 attrValue = CFDictionaryGetValue(attributes, kSecAttrCanDecrypt);
725 eq_cf(attrValue, kCFBooleanTrue, "pub key invalid kSecAttrCanDecrypt");
726
727 attrValue = CFDictionaryGetValue(attributes, kSecAttrCanDerive);
728 eq_cf(attrValue, kCFBooleanFalse, "pub key invalid kSecAttrCanDerive");
729
730 attrValue = CFDictionaryGetValue(attributes, kSecAttrCanSign);
731 eq_cf(attrValue, kCFBooleanFalse, "pub key invalid kSecAttrCanSign");
732
733 attrValue = CFDictionaryGetValue(attributes, kSecAttrCanVerify);
734 eq_cf(attrValue, kCFBooleanTrue, "pub key invalid kSecAttrCanVerify");
735
736 attrValue = CFDictionaryGetValue(attributes, kSecAttrKeyClass);
737 eq_cf(attrValue, kSecAttrKeyClassPublic, "pub key invalid kSecAttrKeyClass");
738
739 attrValue = CFDictionaryGetValue(attributes, kSecAttrKeyType);
740 eq_cf(attrValue, kSecAttrKeyTypeRSA, "pub key invalid kSecAttrKeyType");
741
742 attrValue = CFDictionaryGetValue(attributes, kSecAttrKeySizeInBits);
743 eq_cf(attrValue, kzib, "pub key invalid kSecAttrKeySizeInBits");
744
745 pubAppLabel = CFDictionaryGetValue(attributes, kSecAttrApplicationLabel);
746 CFRetainSafe(pubAppLabel);
747
748 CFReleaseNull(attributes);
749 }
750 }
751
752 eq_cf(privAppLabel, pubAppLabel, "priv key and pub key kSecAttrApplicationLabel differ");
753
754 CFReleaseNull(privAppLabel);
755 CFReleaseNull(pubAppLabel);
756 CFReleaseNull(kzib);
757 CFReleaseNull(pubKey);
758 CFReleaseNull(privKey);
759 }
760
761 #define kCopyPublicKeyTestCount 5
762 static void testcopypublickey(unsigned long keySizeInBits)
763 {
764 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
765 int32_t keysz32 = (int32_t)keySizeInBits;
766
767 CFNumberRef kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32);
768 CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
769 kSecAttrKeyType, kSecAttrKeyTypeRSA,
770 kSecAttrKeySizeInBits, kzib,
771 kSecAttrIsPermanent, kCFBooleanFalse,
772 NULL);
773 CFReleaseNull(kzib);
774
775 SecKeyRef pubKey = NULL, privKey = NULL;
776 OSStatus status;
777 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
778 "Generate %ld bit (%ld byte) RSA keypair (status = %d)",
779 keySizeInBits, keySizeInBytes, (int)status);
780 CFReleaseNull(kgp);
781
782 SecKeyRef pubKeyCopy = NULL;
783
784 { // privKey
785 pubKeyCopy = SecKeyCopyPublicKey(privKey);
786 ok(pubKeyCopy, "priv key SecKeyCopyPublicKey failed");
787 eq_cf(pubKeyCopy, pubKey, "pub key from priv key SecKeyCopyPublicKey and pub key differ");
788 CFReleaseNull(pubKeyCopy);
789 }
790
791 { // pubKey
792 pubKeyCopy = SecKeyCopyPublicKey(pubKey);
793 ok(pubKeyCopy, "pub key SecKeyCopyPublicKey failed");
794 eq_cf(pubKeyCopy, pubKey, "pub key from pub key SecKeyCopyPublicKey and pub key differ");
795 CFReleaseNull(pubKeyCopy);
796 }
797
798 CFReleaseNull(pubKey);
799 CFReleaseNull(privKey);
800 }
801
802 #define kSignAndVerifyTestCount 84
803 static void testsignverify(unsigned long keySizeInBits)
804 {
805 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
806 int32_t keysz32 = (int32_t)keySizeInBits;
807
808 CFNumberRef kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32);
809 CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
810 kSecAttrKeyType, kSecAttrKeyTypeRSA,
811 kSecAttrKeySizeInBits, kzib,
812 kSecAttrIsPermanent, kCFBooleanFalse,
813 NULL);
814 CFReleaseNull(kzib);
815
816 SecKeyRef pubKey = NULL, privKey = NULL;
817 OSStatus status;
818 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
819 "Generate %ld bit (%ld byte) RSA keypair (status = %d)",
820 keySizeInBits, keySizeInBytes, (int)status);
821 CFReleaseNull(kgp);
822
823 SecKeyAlgorithm algorithms[] = {
824 kSecKeyAlgorithmRSASignatureRaw,
825 kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1,
826 kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224,
827 kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256,
828 kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384,
829 kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512,
830 kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1,
831 kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224,
832 kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256,
833 kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384,
834 kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512,
835 };
836
837 CFDataRef testData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, CFSTR("test"), kCFStringEncodingUTF8, 0);
838 ok(testData, "creating test data failed");
839
840 SKIP: {
841 skip("invalid test data", 71, testData);
842
843 CFErrorRef error = NULL;
844
845 for (uint32_t ix = 0; ix < array_size(algorithms); ++ix) {
846 SecKeyAlgorithm algorithm = algorithms[ix];
847 SecKeyAlgorithm incompatibleAlgorithm = (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureRaw)) ?
848 kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1 : kSecKeyAlgorithmRSASignatureRaw;
849
850 CFDataRef dataToSign = NULL;
851 if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1)) {
852 dataToSign = CFDataCreateWithHash(kCFAllocatorDefault, ccsha1_di(),
853 CFDataGetBytePtr(testData), CFDataGetLength(testData));
854 ok(dataToSign, "creating digest failed for algorithm %@", algorithm);
855 }
856 else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224)) {
857 dataToSign = CFDataCreateWithHash(kCFAllocatorDefault, ccsha224_di(),
858 CFDataGetBytePtr(testData), CFDataGetLength(testData));
859 ok(dataToSign, "creating digest failed for algorithm %@", algorithm);
860 }
861 else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256)) {
862 dataToSign = CFDataCreateWithHash(kCFAllocatorDefault, ccsha256_di(),
863 CFDataGetBytePtr(testData), CFDataGetLength(testData));
864 ok(dataToSign, "creating digest failed for algorithm %@", algorithm);
865 }
866 else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384)) {
867 dataToSign = CFDataCreateWithHash(kCFAllocatorDefault, ccsha384_di(),
868 CFDataGetBytePtr(testData), CFDataGetLength(testData));
869 ok(dataToSign, "creating digest failed for algorithm %@", algorithm);
870 }
871 else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512)) {
872 dataToSign = CFDataCreateWithHash(kCFAllocatorDefault, ccsha512_di(),
873 CFDataGetBytePtr(testData), CFDataGetLength(testData));
874 ok(dataToSign, "creating digest failed for algorithm %@", algorithm);
875 }
876 else {
877 CFRetainAssign(dataToSign, testData);
878 }
879 CFReleaseNull(error);
880
881 SKIP: {
882 skip("invalid data to sign", 7, dataToSign);
883
884 CFDataRef signature = SecKeyCreateSignature(pubKey, algorithm, dataToSign, &error);
885 ok(!signature, "SecKeyCopySignature succeeded with pub key for algorithm %@", algorithm);
886 CFReleaseNull(error);
887 CFReleaseNull(signature);
888
889 signature = SecKeyCreateSignature(privKey, algorithm, dataToSign, &error);
890 ok(signature, "SecKeyCopySignature failed for algorithm %@", algorithm);
891 CFReleaseNull(error);
892
893 SKIP: {
894 skip("invalid signature", 4, signature);
895
896 ok(!SecKeyVerifySignature(privKey, algorithm, dataToSign, signature, &error),
897 "SecKeyVerifySignature succeeded with priv key for algorithm %@", algorithm);
898 CFReleaseNull(error);
899
900 ok(!SecKeyVerifySignature(pubKey, incompatibleAlgorithm, dataToSign, signature, &error),
901 "SecKeyVerifySignature succeeded with wrong algorithm for algorithm %@", algorithm);
902 CFReleaseNull(error);
903
904 ok(SecKeyVerifySignature(pubKey, algorithm, dataToSign, signature, &error),
905 "SecKeyVerifySignature failed for algorithm %@", algorithm);
906 CFReleaseNull(error);
907
908 CFMutableDataRef modifiedSignature = CFDataCreateMutable(kCFAllocatorDefault, 0);
909 CFDataAppend(modifiedSignature, signature);
910 *CFDataGetMutableBytePtr(modifiedSignature) ^= 0xff;
911
912 ok(!SecKeyVerifySignature(pubKey, algorithm, dataToSign, modifiedSignature, &error),
913 "SecKeyVerifySignature succeeded with bad signature for algorithm %@", algorithm);
914 CFReleaseNull(error);
915
916 CFMutableDataRef modifiedDataToSign = CFDataCreateMutable(kCFAllocatorDefault, 0);
917 CFDataAppend(modifiedDataToSign, dataToSign);
918 *CFDataGetMutableBytePtr(modifiedDataToSign) ^= 0xff;
919
920 ok(!SecKeyVerifySignature(pubKey, algorithm, modifiedDataToSign, signature, &error),
921 "SecKeyVerifySignature succeeded with bad data for algorithm %@", algorithm);
922 CFReleaseNull(error);
923
924 CFReleaseNull(modifiedDataToSign);
925 CFReleaseNull(modifiedSignature);
926 CFReleaseNull(signature);
927 }
928 CFReleaseNull(dataToSign);
929 }
930 }
931 CFReleaseNull(testData);
932 }
933
934 CFReleaseNull(pubKey);
935 CFReleaseNull(privKey);
936 }
937
938
939 #define kSPKITestCount 4
940 static void testspki(CFStringRef keytype, size_t keySizeInBits)
941 {
942 SecKeyRef pubKey = NULL, privKey = NULL, pubKey2 = NULL;
943 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
944 CFNumberRef kzib;
945 int32_t keysz32 = (int32_t)keySizeInBits;
946 CFDataRef spki = NULL;
947
948 kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32);
949 CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
950 CFDictionaryAddValue(kgp, kSecAttrKeyType, keytype);
951 CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib);
952
953 OSStatus status;
954 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
955 "Generate %ld bit (%ld byte) keypair", keySizeInBits, keySizeInBytes);
956 CFRelease(kzib);
957 CFRelease(kgp);
958
959 spki = SecKeyCopySubjectPublicKeyInfo(pubKey);
960 ok(spki, "failed to create SPKI");
961
962 pubKey2 = SecKeyCreateFromSubjectPublicKeyInfoData(NULL, spki);
963 ok(pubKey2, "failed to create key from SPKI");
964
965 eq_cf(pubKey, pubKey2, "public not same after going though SPKI");
966
967 CFReleaseNull(pubKey);
968 CFReleaseNull(pubKey2);
969 CFReleaseNull(privKey);
970 CFReleaseNull(spki);
971 }
972
973
974 /* Test basic add delete update copy matching stuff. */
975 #define kTestCount ((3 * kKeyGenTestCount) + kKeyGen2TestCount + kTestSupportedCount + kCreateWithDataTestCount \
976 + kCopyAttributesTestCount + kCopyPublicKeyTestCount + kSignAndVerifyTestCount + ((3 + 3) * kSPKITestCount))
977 static void tests(void)
978 {
979 /* Comment out lines below for testing generating all common key sizes,
980 disabled now for speed reasons. */
981 //testkeygen(512);
982 testkeygen(768);
983 testkeygen(1024);
984 testkeygen(2056); // Stranged sized for edge cases in padding.
985 //testkeygen(2048);
986 //testkeygen(4096);
987
988 testkeygen2(768);
989
990 testsupportedalgos(768);
991 testcreatewithdata(768);
992 testcopyattributes(768);
993 testcopypublickey(768);
994 testsignverify(768);
995
996 testspki(kSecAttrKeyTypeRSA, 1024);
997 testspki(kSecAttrKeyTypeRSA, 2048);
998 testspki(kSecAttrKeyTypeRSA, 4096);
999
1000 testspki(kSecAttrKeyTypeEC, 256);
1001 testspki(kSecAttrKeyTypeEC, 384);
1002 testspki(kSecAttrKeyTypeEC, 521);
1003 }
1004
1005 int si_40_seckey(int argc, char *const *argv)
1006 {
1007 plan_tests(kTestCount);
1008
1009 tests();
1010
1011 return 0;
1012 }