]> git.saurik.com Git - apple/security.git/blob - libsecurity_keychain/regressions/kc-41-sececkey.c
Security-55471.tar.gz
[apple/security.git] / libsecurity_keychain / regressions / kc-41-sececkey.c
1 //
2 // si-41-sececkey.c
3 // regressions
4 //
5 // Created by Mitch Adler on 5/20/11.
6 // Copyright 2011 Apple Inc. All rights reserved.
7 //
8
9 /*
10 * si-40-seckey.c
11 * Security
12 *
13 * Created by Michael Brouwer on 1/29/07.
14 * Copyright (c) 2007-2009 Apple Inc. All Rights Reserved.
15 *
16 */
17 #include <TargetConditionals.h>
18 #include <CoreFoundation/CoreFoundation.h>
19 #include <Security/Security.h>
20 #include <Security/SecKeyPriv.h>
21
22 #if 0
23 #include <Security/SecCertificate.h>
24 #include <Security/SecCertificateInternal.h>
25 #include <Security/SecKey.h>
26 #include <Security/SecKeyPriv.h>
27 #include <Security/SecItem.h>
28 #include <Security/SecAsn1Types.h>
29 #include <Security/oidsalg.h>
30 #include <Security/SecureTransport.h>
31 #include <Security/SecRandom.h>
32 #include <CommonCrypto/CommonDigest.h>
33 #include <libDER/libDER.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #endif
37
38
39 #include "keychain_regressions.h"
40 #include "utilities/SecCFRelease.h"
41
42
43 #if TARGET_OS_IPHONE
44 static void testdigestandsignalg(SecKeyRef privKey, SecKeyRef pubKey, const SecAsn1AlgId *algId) {
45 uint8_t dataToDigest[256];
46 size_t dataToDigestLen = sizeof(dataToDigest);
47 size_t sigLen = SecKeyGetSize(privKey, kSecKeySignatureSize);
48 uint8_t sig[sigLen];
49
50 DERItem oid;
51 oid.length = algId->algorithm.Length;
52 oid.data = algId->algorithm.Data;
53
54 /* Get the oid in decimal for display purposes. */
55 CFStringRef oidStr = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, &oid);
56 char oidBuf[40];
57 CFStringGetCString(oidStr, oidBuf, sizeof(oidBuf), kCFStringEncodingUTF8);
58 CFRelease(oidStr);
59
60 SKIP: {
61 OSStatus status;
62
63 /* Time to sign. */
64 ok_status(status = SecKeyDigestAndSign(privKey, algId, dataToDigest, dataToDigestLen,
65 sig, &sigLen),
66 "digest and sign %s with %ld bit RSA key", oidBuf, sigLen * 8);
67
68 skip("SecKeyDigestAndSign failed", 3, status == errSecSuccess);
69
70 /* Verify the signature we just made. */
71 ok_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen,
72 sig, sigLen), "digest and verify");
73 /* Invalidate the signature. */
74 sig[0] ^= 0xff;
75 is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen,
76 sig, sigLen), errSSLCrypto, "digest and verify bad sig");
77 sig[0] ^= 0xff;
78 dataToDigest[0] ^= 0xff;
79 is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen,
80 sig, sigLen), errSSLCrypto, "digest and verify bad digest");
81 }
82 }
83
84 static void testdigestandsign(SecKeyRef privKey, SecKeyRef pubKey) {
85 static const SecAsn1Oid *oids[] = {
86 &CSSMOID_ECDSA_WithSHA1,
87 #if 0
88 &CSSMOID_ECDSA_WithSHA224,
89 &CSSMOID_ECDSA_WithSHA256,
90 &CSSMOID_ECDSA_WithSHA384,
91 &CSSMOID_ECDSA_WithSHA512,
92 #endif
93 };
94
95 uint32_t ix;
96 SecAsn1AlgId algId = {};
97 for (ix = 0; ix < sizeof(oids) / sizeof(*oids); ++ix) {
98 if (oids[ix]) {
99 algId.algorithm = *oids[ix];
100 } else {
101 algId.algorithm.Length = 0;
102 algId.algorithm.Data = NULL;
103 }
104
105 testdigestandsignalg(privKey, pubKey, &algId);
106 }
107 }
108 #endif
109
110
111 #if !TARGET_OS_IPHONE
112 /* This is part of Security.framework on iOS */
113
114 enum {
115 // kSecKeyKeySizeInBits = 0, // already exists on osx
116 kSecKeySignatureSize = 101,
117 kSecKeyEncryptedDataSize = 102,
118 // More might belong here, but we aren't settled on how
119 // to take into account padding and/or digest types.
120 };
121
122 static
123 size_t SecKeyGetSize(SecKeyRef key, int whichSize)
124 {
125 /* SecKeyGetBlockSize return the signature size on OS X -- smh */
126 size_t result = SecKeyGetBlockSize(key);
127
128 result = (result - 2)/2 - 3;
129
130 /* in this test, this is always an ECDSA key */
131 switch (whichSize) {
132 case kSecKeyEncryptedDataSize:
133 result = 0;
134 break;
135 case kSecKeySignatureSize:
136 result = (result >= 66 ? 9 : 8) + 2 * result;
137 break;
138 case kSecKeyKeySizeInBits:
139 if (result >= 66)
140 return 521;
141 }
142
143 if (whichSize == kSecKeyKeySizeInBits)
144 result *= 8;
145
146 return result;
147
148 }
149 #endif
150
151
152 static void testkeygen(size_t keySizeInBits) {
153 SecKeyRef pubKey = NULL, privKey = NULL;
154 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
155 CFNumberRef kzib;
156
157 kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keySizeInBits);
158 CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
159 CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC);
160 CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib);
161
162 OSStatus status;
163 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
164 "Generate %ld bit (%ld byte) EC keypair", keySizeInBits,
165 keySizeInBytes);
166 CFRelease(kzib);
167 CFRelease(kgp);
168
169 SKIP: {
170 skip("keygen failed", 8, status == errSecSuccess);
171 ok(pubKey, "pubkey returned");
172 ok(privKey, "privKey returned");
173 is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok");
174 is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok");
175
176 /* Sign something. */
177 uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
178 uint8_t sig[8+2*keySizeInBytes];
179 size_t sigLen = sizeof(sig);
180 ok_status(SecKeyRawSign(privKey, kSecPaddingNone,
181 something, sizeof(something), sig, &sigLen), "sign something");
182 ok_status(SecKeyRawVerify(pubKey, kSecPaddingNone,
183 something, sizeof(something), sig, sigLen), "verify sig on something");
184
185 #if TARGET_OS_IPHONE
186 testdigestandsign(privKey, pubKey);
187 #endif
188
189 const void *privkeys[] = {
190 kSecValueRef
191 };
192 const void *privvalues[] = {
193 privKey
194 };
195 CFDictionaryRef privitem = CFDictionaryCreate(NULL, privkeys, privvalues,
196 sizeof(privkeys) / sizeof(*privkeys), NULL, NULL);
197 #if TARGET_OS_IPHONE
198 ok_status(SecItemAdd(privitem, NULL), "add private key");
199 #endif
200 ok_status(SecItemDelete(privitem), "delete private key");
201 CFReleaseNull(privitem);
202
203 const void *pubkeys[] = {
204 kSecValueRef
205 };
206 const void *pubvalues[] = {
207 pubKey
208 };
209 CFDictionaryRef pubitem = CFDictionaryCreate(NULL, pubkeys, pubvalues,
210 sizeof(pubkeys) / sizeof(*pubkeys), NULL, NULL);
211 #if TARGET_OS_IPHONE
212 ok_status(SecItemAdd(pubitem, NULL), "add public key");
213 #endif
214 ok_status(SecItemDelete(pubitem), "delete public key");
215 CFReleaseNull(pubitem);
216
217 /* Cleanup. */
218 CFReleaseNull(pubKey);
219 CFReleaseNull(privKey);
220 }
221 }
222
223
224 static void testkeygen2(size_t keySizeInBits) {
225 SecKeyRef pubKey = NULL, privKey = NULL;
226 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
227 CFNumberRef kzib;
228
229 CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault);
230 CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID);
231 CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString);
232 CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString);
233
234 CFReleaseNull(ourUUID);
235 CFReleaseNull(uuidString);
236
237 CFStringAppend(publicName, CFSTR("-Public-41"));
238 CFStringAppend(privateName, CFSTR("-Private-41"));
239
240 CFMutableDictionaryRef pubd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
241 CFMutableDictionaryRef privd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
242 CFDictionaryAddValue(pubd, kSecAttrLabel, publicName);
243 CFDictionaryAddValue(privd, kSecAttrLabel, privateName);
244
245 kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keySizeInBits);
246 CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
247 CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC);
248 CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib);
249 CFDictionaryAddValue(kgp, kSecAttrIsPermanent, kCFBooleanTrue);
250 CFDictionaryAddValue(kgp, kSecPublicKeyAttrs, pubd);
251 CFDictionaryAddValue(kgp, kSecPrivateKeyAttrs, privd);
252
253 OSStatus status;
254 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
255 "Generate %ld bit (%ld byte) persistent RSA keypair",
256 keySizeInBits, keySizeInBytes);
257 CFRelease(kzib);
258 CFRelease(kgp);
259
260 SKIP: {
261 skip("keygen failed", 8, status == errSecSuccess);
262 ok(pubKey, "pubkey returned");
263 ok(privKey, "privKey returned");
264 is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok");
265 is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok");
266
267 SecKeyRef pubKey2, privKey2;
268 CFDictionaryAddValue(pubd, kSecClass, kSecClassKey);
269 CFDictionaryAddValue(pubd, kSecReturnRef, kCFBooleanTrue);
270 CFDictionaryAddValue(privd, kSecClass, kSecClassKey);
271 CFDictionaryAddValue(privd, kSecReturnRef, kCFBooleanTrue);
272 CFDictionaryAddValue(privd, kSecAttrCanSign, kCFBooleanTrue);
273 ok_status(SecItemCopyMatching(pubd, (CFTypeRef *)&pubKey2),
274 "retrieve pub key by label");
275 ok(pubKey2, "got valid object");
276 ok_status(SecItemCopyMatching(privd, (CFTypeRef *)&privKey2),
277 "retrieve priv key by label and kSecAttrCanSign");
278 ok(privKey2, "got valid object");
279
280 /* Sign something. */
281 uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
282 size_t sigLen = SecKeyGetSize(privKey2, kSecKeySignatureSize);
283 uint8_t sig[sigLen];
284 ok_status(SecKeyRawSign(privKey2, kSecPaddingPKCS1,
285 something, sizeof(something), sig, &sigLen), "sign something");
286 ok_status(SecKeyRawVerify(pubKey2, kSecPaddingPKCS1,
287 something, sizeof(something), sig, sigLen), "verify sig on something");
288
289 /* Cleanup. */
290 CFReleaseNull(pubKey2);
291 CFReleaseNull(privKey2);
292 }
293
294 /* delete from keychain - note: do it before releasing publicName and privateName
295 because pubd and privd have no retain/release callbacks */
296 ok_status(SecItemDelete(pubd), "delete generated pub key");
297 ok_status(SecItemDelete(privd), "delete generated priv key");
298
299 /* Cleanup. */
300 CFReleaseNull(pubKey);
301 CFReleaseNull(privKey);
302
303 CFReleaseNull(publicName);
304 CFReleaseNull(privateName);
305
306 CFRelease(pubd);
307 CFRelease(privd);
308 }
309
310
311 /* Test basic add delete update copy matching stuff. */
312 static void tests(void)
313 {
314 testkeygen(192);
315 #if TARGET_OS_IPHONE
316 testkeygen(224);
317 #endif
318 testkeygen(256);
319 testkeygen(384);
320 testkeygen(521);
321
322 testkeygen2(192);
323 #if TARGET_OS_IPHONE
324 testkeygen2(224);
325 #endif
326 testkeygen2(256);
327 testkeygen2(384);
328 testkeygen2(521);
329
330 }
331
332 int kc_41_sececkey(int argc, char *const *argv)
333 {
334 #if TARGET_OS_IPHONE
335 plan_tests(140);
336 #else
337 plan_tests(88);
338 #endif
339
340 tests();
341
342 return 0;
343 }