]> git.saurik.com Git - apple/security.git/blame - sec/Security/Regressions/secitem/si-41-sececkey.c
Security-55471.tar.gz
[apple/security.git] / sec / Security / Regressions / secitem / si-41-sececkey.c
CommitLineData
427c49bc
A
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
18#include <CoreFoundation/CoreFoundation.h>
19#include <Security/SecCertificate.h>
20#include <Security/SecCertificateInternal.h>
21#include <Security/SecKey.h>
22#include <Security/SecKeyPriv.h>
23#include <Security/SecItem.h>
24#include <Security/SecAsn1Types.h>
25#include <Security/oidsalg.h>
26#include <Security/SecureTransport.h>
27#include <Security/SecRandom.h>
28#include <utilities/array_size.h>
29#include <CommonCrypto/CommonDigest.h>
30#include <libDER/libDER.h>
31#include <stdlib.h>
32#include <unistd.h>
33
34#include "Security_regressions.h"
35
36#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) { (CF) = NULL; CFRelease(_cf); } }
37
38
39static void testdigestandsignalg(SecKeyRef privKey, SecKeyRef pubKey, const SecAsn1AlgId *algId) {
40 uint8_t dataToDigest[256] = {0,};
41 size_t dataToDigestLen = sizeof(dataToDigest);
42 size_t sigLen = SecKeyGetSize(privKey, kSecKeySignatureSize);
43 uint8_t sig[sigLen];
44
45 DERItem oid;
46 oid.length = algId->algorithm.Length;
47 oid.data = algId->algorithm.Data;
48
49 /* Get the oid in decimal for display purposes. */
50 CFStringRef oidStr = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, &oid);
51 char oidBuf[40];
52 CFStringGetCString(oidStr, oidBuf, sizeof(oidBuf), kCFStringEncodingUTF8);
53 CFRelease(oidStr);
54
55SKIP: {
56 OSStatus status;
57
58 /* Time to sign. */
59 ok_status(status = SecKeyDigestAndSign(privKey, algId, dataToDigest, dataToDigestLen,
60 sig, &sigLen),
61 "digest and sign %s with %ld bit RSA key", oidBuf, sigLen * 8);
62
63 skip("SecKeyDigestAndSign failed", 3, status == errSecSuccess);
64
65 /* Verify the signature we just made. */
66 ok_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen,
67 sig, sigLen), "digest and verify");
68 /* Invalidate the signature. */
69 sig[0] ^= 0xff;
70 is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen,
71 sig, sigLen), errSSLCrypto, "digest and verify bad sig");
72 sig[0] ^= 0xff;
73 dataToDigest[0] ^= 0xff;
74 is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen,
75 sig, sigLen), errSSLCrypto, "digest and verify bad digest");
76}
77}
78
79static void testdigestandsign(SecKeyRef privKey, SecKeyRef pubKey) {
80 static const SecAsn1Oid *oids[] = {
81 &CSSMOID_ECDSA_WithSHA1,
82#if 0
83 &CSSMOID_ECDSA_WithSHA224,
84 &CSSMOID_ECDSA_WithSHA256,
85 &CSSMOID_ECDSA_WithSHA384,
86 &CSSMOID_ECDSA_WithSHA512,
87#endif
88 };
89
90 uint32_t ix;
91 SecAsn1AlgId algId = {};
92 for (ix = 0; ix < array_size(oids); ++ix) {
93 if (oids[ix]) {
94 algId.algorithm = *oids[ix];
95 } else {
96 algId.algorithm.Length = 0;
97 algId.algorithm.Data = NULL;
98 }
99
100 testdigestandsignalg(privKey, pubKey, &algId);
101 }
102}
103
104static void testkeygen(size_t keySizeInBits) {
105 SecKeyRef pubKey = NULL, privKey = NULL;
106 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
107 CFNumberRef kzib;
108 int32_t keysz32 = (int32_t)keySizeInBits;
109
110 kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32);
111 CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
112 CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC);
113 CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib);
114
115 OSStatus status;
116 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
117 "Generate %ld bit (%ld byte) EC keypair", keySizeInBits,
118 keySizeInBytes);
119 CFRelease(kzib);
120 CFRelease(kgp);
121
122SKIP: {
123 skip("keygen failed", 8, status == errSecSuccess);
124 ok(pubKey, "pubkey returned");
125 ok(privKey, "privKey returned");
126 is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok");
127 is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok");
128
129 /* Sign something. */
130 uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
131 uint8_t sig[8+2*keySizeInBytes];
132 size_t sigLen = sizeof(sig);
133 ok_status(SecKeyRawSign(privKey, kSecPaddingNone,
134 something, sizeof(something), sig, &sigLen), "sign something");
135 ok_status(SecKeyRawVerify(pubKey, kSecPaddingNone,
136 something, sizeof(something), sig, sigLen), "verify sig on something");
137
138 testdigestandsign(privKey, pubKey);
139
140 const void *privkeys[] = {
141 kSecValueRef
142 };
143 const void *privvalues[] = {
144 privKey
145 };
146 CFDictionaryRef privitem = CFDictionaryCreate(NULL, privkeys, privvalues,
147 array_size(privkeys), NULL, NULL);
148 ok_status(SecItemAdd(privitem, NULL), "add private key");
149 ok_status(SecItemDelete(privitem), "delete public key");
150 CFReleaseNull(privitem);
151
152 const void *pubkeys[] = {
153 kSecValueRef
154 };
155 const void *pubvalues[] = {
156 pubKey
157 };
158 CFDictionaryRef pubitem = CFDictionaryCreate(NULL, pubkeys, pubvalues,
159 array_size(pubkeys), NULL, NULL);
160 ok_status(SecItemAdd(pubitem, NULL), "add public key");
161 ok_status(SecItemDelete(pubitem), "delete public key");
162 CFReleaseNull(pubitem);
163
164 /* Cleanup. */
165 CFReleaseNull(pubKey);
166 CFReleaseNull(privKey);
167}
168}
169
170
171static void testkeygen2(size_t keySizeInBits) {
172 SecKeyRef pubKey = NULL, privKey = NULL;
173 size_t keySizeInBytes = (keySizeInBits + 7) / 8;
174 CFNumberRef kzib;
175 int32_t keysz32 = (int32_t)keySizeInBits;
176
177 CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault);
178 CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID);
179 CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString);
180 CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString);
181
182 CFReleaseNull(ourUUID);
183 CFReleaseNull(uuidString);
184
185 CFStringAppend(publicName, CFSTR("-Public-41"));
186 CFStringAppend(privateName, CFSTR("-Private-41"));
187
188 CFMutableDictionaryRef pubd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
189 CFMutableDictionaryRef privd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
190 CFDictionaryAddValue(pubd, kSecAttrLabel, publicName);
191 CFDictionaryAddValue(privd, kSecAttrLabel, privateName);
192
193 kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32);
194 CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
195 CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC);
196 CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib);
197 CFDictionaryAddValue(kgp, kSecAttrIsPermanent, kCFBooleanTrue);
198 CFDictionaryAddValue(kgp, kSecPublicKeyAttrs, pubd);
199 CFDictionaryAddValue(kgp, kSecPrivateKeyAttrs, privd);
200
201 OSStatus status;
202 ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
203 "Generate %ld bit (%ld byte) persistent RSA keypair",
204 keySizeInBits, keySizeInBytes);
205 CFRelease(kzib);
206 CFRelease(kgp);
207
208SKIP: {
209 skip("keygen failed", 8, status == errSecSuccess);
210 ok(pubKey, "pubkey returned");
211 ok(privKey, "privKey returned");
212 is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok");
213 is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok");
214
215 SecKeyRef pubKey2, privKey2;
216 CFDictionaryAddValue(pubd, kSecClass, kSecClassKey);
217 CFDictionaryAddValue(pubd, kSecReturnRef, kCFBooleanTrue);
218 CFDictionaryAddValue(privd, kSecClass, kSecClassKey);
219 CFDictionaryAddValue(privd, kSecReturnRef, kCFBooleanTrue);
220 CFDictionaryAddValue(privd, kSecAttrCanSign, kCFBooleanTrue);
221 ok_status(SecItemCopyMatching(pubd, (CFTypeRef *)&pubKey2),
222 "retrieve pub key by label");
223 ok(pubKey2, "got valid object");
224 ok_status(SecItemCopyMatching(privd, (CFTypeRef *)&privKey2),
225 "retrieve priv key by label and kSecAttrCanSign");
226 ok(privKey2, "got valid object");
227
228 /* Sign something. */
229 uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
230 size_t sigLen = SecKeyGetSize(privKey2, kSecKeySignatureSize);
231 uint8_t sig[sigLen];
232 ok_status(SecKeyRawSign(privKey2, kSecPaddingPKCS1,
233 something, sizeof(something), sig, &sigLen), "sign something");
234 ok_status(SecKeyRawVerify(pubKey2, kSecPaddingPKCS1,
235 something, sizeof(something), sig, sigLen), "verify sig on something");
236
237 /* Cleanup. */
238 CFReleaseNull(pubKey2);
239 CFReleaseNull(privKey2);
240}
241
242 /* delete from keychain - note: do it before releasing publicName and privateName
243 because pubd and privd have no retain/release callbacks */
244 ok_status(SecItemDelete(pubd), "delete generated pub key");
245 ok_status(SecItemDelete(privd), "delete generated priv key");
246
247 /* Cleanup. */
248 CFReleaseNull(pubKey);
249 CFReleaseNull(privKey);
250
251 CFReleaseNull(publicName);
252 CFReleaseNull(privateName);
253
254 CFRelease(pubd);
255 CFRelease(privd);
256}
257
258
259/* Test basic add delete update copy matching stuff. */
260static void tests(void)
261{
262 testkeygen(192);
263 testkeygen(224);
264 testkeygen(256);
265 testkeygen(384);
266 testkeygen(521);
267
268 testkeygen2(192);
269 testkeygen2(224);
270 testkeygen2(256);
271 testkeygen2(384);
272 testkeygen2(521);
273
274}
275
276int si_41_sececkey(int argc, char *const *argv)
277{
278 plan_tests(140);
279
280 tests();
281
282 return 0;
283}