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