]> git.saurik.com Git - apple/security.git/blob - OSX/shared_regressions/si-44-seckey-gen.m
Security-59306.41.2.tar.gz
[apple/security.git] / OSX / shared_regressions / si-44-seckey-gen.m
1 /*
2 * Copyright (c) 2016 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 #import <Foundation/Foundation.h>
26
27 #include "shared_regressions.h"
28
29 static void create_random_key_worker(id keyType, int keySize, bool permPub, bool permPriv) {
30 NSDictionary *params = nil;
31 NSError *error = nil;
32
33 params = @{
34 (id)kSecAttrKeyType: keyType,
35 (id)kSecAttrKeySizeInBits: @(keySize),
36 (id)kSecAttrLabel: @"si-44-seckey-gen:0",
37 (id)kSecPublicKeyAttrs: @{
38 (id)kSecAttrIsPermanent: @(permPub),
39 },
40 (id)kSecPrivateKeyAttrs: @{
41 (id)kSecAttrIsPermanent: @(permPriv),
42 },
43 };
44
45 id privateKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)params, (void *)&error));
46 ok(privateKey != nil, "generating key (type:%@, size:%d, permPub:%d, permPriv:%d) : %@", keyType, keySize, (int)permPub, (int)permPriv, error);
47
48 id publicKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)privateKey));
49 ok(publicKey != nil, "got public key from generated private key");
50
51 error = nil;
52 NSData *pubKeyData = CFBridgingRelease(SecKeyCopyExternalRepresentation((SecKeyRef)publicKey, (void *)&error));
53 ok(pubKeyData != nil, "get public key data, error %@", error);
54
55 params = @{
56 (id)kSecClass: (id)kSecClassKey,
57 (id)kSecAttrKeyType: keyType,
58 (id)kSecAttrKeySizeInBits: @(keySize),
59 (id)kSecAttrLabel: @"si-44-seckey-gen:0",
60 (id)kSecMatchLimit: (id)kSecMatchLimitAll,
61 (id)kSecReturnAttributes: @YES,
62 };
63 NSArray *items = nil;
64 OSStatus expected = (permPub || permPriv) ? errSecSuccess : errSecItemNotFound;
65 is_status(SecItemCopyMatching((CFDictionaryRef)params, (void *)&items), expected, "keychain query for generated keys");
66 is((int)items.count, (permPub ? 1 : 0) + (permPriv ? 1 : 0), "found keys in the keychain");
67
68 if (!permPub) {
69 // Store public key into keychain explicitly.
70 NSDictionary *add = @{
71 (id)kSecValueRef: (id)publicKey,
72 (id)kSecAttrLabel: @"si-44-seckey-gen:0",
73 (id)kSecReturnPersistentRef: @YES,
74 };
75 NSData *pRef;
76 ok_status(SecItemAdd((CFDictionaryRef)add, (void *)&pRef), "Add public key");
77 ok([pRef isKindOfClass:NSData.class] || [pRef isKindOfClass:NSArray.class] , "got persistent ref");
78 } else {
79 ok(true);
80 ok(true);
81 }
82
83 if (!permPriv) {
84 // Store public key into keychain explicitly.
85 NSDictionary *add = @{
86 (id)kSecValueRef: (id)privateKey,
87 (id)kSecAttrLabel: @"si-44-seckey-gen:0",
88 (id)kSecReturnPersistentRef: @YES,
89 };
90 NSData *pRef;
91 ok_status(SecItemAdd((CFDictionaryRef)add, (void *)&pRef), "Add private key");
92 ok([pRef isKindOfClass:NSData.class] || [pRef isKindOfClass:NSArray.class] , "got persistent ref");
93 } else {
94 ok(true);
95 ok(true);
96 }
97
98 items = nil;
99 ok_status(SecItemCopyMatching((CFDictionaryRef)params, (void *)&items), "keychain query for generated keys");
100 is((int)items.count, 2, "keypair is in the keychain");
101
102 params = @{
103 (id)kSecClass: (id)kSecClassKey,
104 (id)kSecAttrKeyType: keyType,
105 (id)kSecAttrKeySizeInBits: @(keySize),
106 #if TARGET_OS_OSX
107 // Despite headerdoc and other docs, SecItemDelete on macOS deletes only first found item, we need to persuade
108 // it to delete everything passing the query. On the other hand, iOS implementation errs out when
109 // kSecMatchLimit is given, so we need to add it only for macOS.
110 (id)kSecMatchLimit: (id)kSecMatchLimitAll,
111 #endif
112 (id)kSecAttrLabel: @"si-44-seckey-gen:0",
113 };
114 ok_status(SecItemDelete((CFDictionaryRef)params), "clear generated pair from keychain");
115 }
116
117 static void test_create_random_key() {
118 create_random_key_worker((id)kSecAttrKeyTypeRSA, 1024, false, false);
119 create_random_key_worker((id)kSecAttrKeyTypeRSA, 1024, false, true);
120 create_random_key_worker((id)kSecAttrKeyTypeRSA, 1024, true, true);
121 create_random_key_worker((id)kSecAttrKeyTypeECSECPrimeRandom, 256, false, false);
122 create_random_key_worker((id)kSecAttrKeyTypeECSECPrimeRandom, 256, false, true);
123 create_random_key_worker((id)kSecAttrKeyTypeECSECPrimeRandom, 256, true, true);
124
125 // Create pair with pub-permanent&priv-nonpermanent currently does not work well, created
126 // pub key has some strange ACL which prevents it from sensible use. However, this combination
127 // also does not make sense at all from usage point of view.
128 // create_random_key_worker((id)kSecAttrKeyTypeRSA, 1024, true, false);
129 // create_random_key_worker((id)kSecAttrKeyTypeECSECPrimeRandom, 256, true, false);
130 }
131 static const int TestCountCreateRandomKey = (3 * 12) * 2;
132
133 static void test_create_key_with_attrs_run(NSDictionary *attrs) {
134 NSMutableDictionary *params = attrs.mutableCopy;
135 params[(id)kSecAttrKeyType] = (id)kSecAttrKeyTypeRSA;
136 params[(id)kSecAttrKeySizeInBits] = @1024;
137 params[(id)kSecAttrIsPermanent] = @YES;
138
139 NSError *error;
140 id privKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)params, (void *)&error));
141 ok(privKey != nil, "generatekey: %@", privKey);
142
143 id pubKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)privKey));
144 ok(pubKey != nil, "get pub key");
145
146 NSDictionary *result;
147 ok_status(SecItemCopyMatching((CFDictionaryRef)@{(id)kSecValueRef: privKey, (id)kSecReturnAttributes: @YES}, (void *)&result), "copymatching create privkey");
148 __block BOOL failed = NO;
149 [attrs enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
150 failed = failed || ![result[key] isEqual:obj];
151 }];
152 ok(!failed, "retrieved attributes differ (privkey): expected: %@ - got: %@", attrs, result);
153
154 result = nil;
155 ok_status(SecItemCopyMatching((CFDictionaryRef)@{(id)kSecValueRef: pubKey, (id)kSecReturnAttributes: @YES}, (void *)&result), "copymatching create privkey");
156 failed = NO;
157 [attrs enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
158 failed = failed || ![result[key] isEqual:obj];
159 }];
160 ok(!failed, "retrieved attributes differ (pubkey): expected: %@ - got: %@", attrs, result);
161
162 // Cleanup of the keys.
163 ok_status(SecItemDelete((CFDictionaryRef)@{(id)kSecValueRef: privKey}));
164 ok_status(SecItemDelete((CFDictionaryRef)@{(id)kSecValueRef: pubKey}));
165 }
166 static const int TestCountCreateKeyWithAttrsRun = 8;
167
168 static void test_create_key_with_attrs() {
169 test_create_key_with_attrs_run(@{(id)kSecAttrLabel:@"Label"});
170 test_create_key_with_attrs_run(@{(id)kSecAttrApplicationTag:[@"AppTag" dataUsingEncoding:NSUTF8StringEncoding]});
171 test_create_key_with_attrs_run(@{(id)kSecAttrLabel:@"Label",
172 (id)kSecAttrApplicationTag:[@"AppTag" dataUsingEncoding:NSUTF8StringEncoding]});
173 }
174 static const int TestCountCreateKeyWithAttrs = 3 * TestCountCreateKeyWithAttrsRun;
175
176 static const int TestCount =
177 TestCountCreateRandomKey +
178 TestCountCreateKeyWithAttrs
179 ;
180
181 int si_44_seckey_gen(int argc, char *const *argv) {
182 plan_tests(TestCount);
183
184 @autoreleasepool {
185 test_create_random_key();
186 test_create_key_with_attrs();
187 }
188
189 return 0;
190 }