]>
Commit | Line | Data |
---|---|---|
866f8763 A |
1 | // |
2 | // Copyright 2016 Apple. All rights reserved. | |
3 | // | |
4 | ||
5 | #import <Foundation/Foundation.h> | |
6 | #import <Security/Security.h> | |
7 | #import <Security/SecItemPriv.h> | |
8 | #import <Security/SecKeyPriv.h> | |
9 | #if !TARGET_OS_OSX | |
10 | #import "MobileGestalt.h" | |
79b9da22 A |
11 | #else |
12 | #import <RemoteServiceDiscovery/RemoteServiceDiscovery.h> | |
866f8763 A |
13 | #endif |
14 | ||
15 | #import "shared_regressions.h" | |
16 | ||
0e1db9d1 A |
17 | static id generateKey(id keyType, CFStringRef protection) { |
18 | id accessControl = (__bridge_transfer id)SecAccessControlCreateWithFlags(NULL, protection, kSecAccessControlPrivateKeyUsage, NULL); | |
866f8763 A |
19 | NSDictionary *keyAttributes = @{ (id)kSecAttrTokenID : (id)kSecAttrTokenIDAppleKeyStore, |
20 | (id)kSecAttrKeyType : keyType, | |
21 | (id)kSecAttrAccessControl : accessControl, | |
22 | (id)kSecAttrIsPermanent : @NO }; | |
23 | NSError *error; | |
24 | id key = (__bridge_transfer id)SecKeyCreateRandomKey((CFDictionaryRef)keyAttributes, (void *)&error); | |
25 | ok(key, "failed to create random key %@", error); | |
26 | return key; | |
27 | } | |
28 | ||
29 | static void secKeySepTest(BOOL testPKA) { | |
30 | NSArray *keyTypes; | |
31 | if (testPKA) { | |
32 | keyTypes = @[(id)kSecAttrKeyTypeECSECPrimeRandom, (id)kSecAttrKeyTypeECSECPrimeRandomPKA, (id)kSecAttrKeyTypeSecureEnclaveAttestation]; | |
33 | } else { | |
34 | keyTypes = @[(id)kSecAttrKeyTypeECSECPrimeRandom, (id)kSecAttrKeyTypeSecureEnclaveAttestation]; | |
35 | } | |
36 | for (id keyType in keyTypes) { | |
0e1db9d1 | 37 | id privateKey = generateKey((id)keyType, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly); |
866f8763 A |
38 | ok(privateKey, "failed to create key '%@'", keyType); |
39 | id publicKey = (__bridge_transfer id)SecKeyCopyPublicKey((SecKeyRef)privateKey); | |
40 | ||
41 | NSArray *attestaionKeyTypes = @[@(kSecKeyAttestationKeyTypeSIK), @(kSecKeyAttestationKeyTypeGID)]; | |
42 | for (NSNumber *attestationKeyType in attestaionKeyTypes) { | |
43 | id attestationKey = (__bridge_transfer id)SecKeyCopyAttestationKey([attestationKeyType unsignedIntValue], NULL); | |
44 | ok(attestationKey, "failed to create attestaion key '%@'", attestationKeyType); | |
45 | NSError *error; | |
46 | if (![keyType isEqual:(id)kSecAttrKeyTypeSecureEnclaveAttestation]) { | |
47 | const char rawData[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; | |
48 | NSData *dataToSign = [NSData dataWithBytes:rawData length:sizeof(rawData)]; | |
49 | NSData *signedData = (__bridge_transfer NSData*)SecKeyCreateSignature((SecKeyRef)privateKey, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, (__bridge CFDataRef)dataToSign, (void *)&error); | |
50 | ok(signedData, "failed to sign data, error %@", error); | |
51 | error = nil; | |
52 | ok(SecKeyVerifySignature((SecKeyRef)publicKey, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, (__bridge CFDataRef)dataToSign, (__bridge CFDataRef)signedData, (void *)&error), | |
53 | "failed to verify data '%@'", error); | |
54 | ||
55 | // Try signing large data. | |
56 | dataToSign = [NSMutableData dataWithLength:10 * 1024 * 1024]; | |
57 | error = nil; | |
58 | signedData = (__bridge_transfer NSData*)SecKeyCreateSignature((SecKeyRef)privateKey, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, (__bridge CFDataRef)dataToSign, (void *)&error); | |
59 | ok(signedData, "failed to sign data, error %@", error); | |
60 | error = nil; | |
61 | ok(SecKeyVerifySignature((SecKeyRef)publicKey, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, (__bridge CFDataRef)dataToSign, (__bridge CFDataRef)signedData, (void *)&error), | |
62 | "failed to verify data '%@'", error); | |
63 | } | |
64 | NSData *attestationData = (__bridge_transfer NSData *)SecKeyCreateAttestation((__bridge SecKeyRef)attestationKey, (__bridge SecKeyRef)privateKey, (void *)&error); | |
65 | ok(attestationData, "failed to attest key '%@'", error); | |
66 | } | |
67 | ||
68 | NSDictionary *keyAttrs = (__bridge_transfer NSDictionary *)SecKeyCopyAttributes((SecKeyRef)privateKey); | |
69 | NSData *keyBlob = keyAttrs[(id)kSecAttrTokenOID]; | |
70 | ||
71 | NSDictionary *params = @{ (id)kSecAttrTokenID : (id)kSecAttrTokenIDAppleKeyStore, | |
72 | (id)kSecAttrTokenOID : keyBlob, | |
73 | (id)kSecReturnRef : @YES }; | |
74 | ||
75 | privateKey = nil; | |
76 | NSError *error; | |
77 | privateKey = (__bridge_transfer id)SecKeyCreateWithData((__bridge CFDataRef)keyBlob, (__bridge CFDictionaryRef)params, (void *)&error); | |
78 | ok(privateKey, "failed to create key with data '%@'", error); | |
79 | // <rdar://problem/30651629> SecItemAdd fails to create SecKey from aks key blob | |
80 | // | |
81 | // ok_status(SecItemAdd((__bridge CFDictionaryRef)params, (void *)&privateKey), "failed to create key from aks blob"); | |
82 | // ok_status(SecItemDelete((__bridge CFDictionaryRef) @{(id)kSecValueRef : privateKey}), "failed to delete key from aks blob"); | |
83 | } | |
84 | } | |
85 | ||
0e1db9d1 | 86 | static void attestationTest(CFStringRef protection) { |
866f8763 | 87 | NSError *error; |
0e1db9d1 A |
88 | id privKey = generateKey((id)kSecAttrKeyTypeECSECPrimeRandom, protection); |
89 | id uik = generateKey((id)kSecAttrKeyTypeSecureEnclaveAttestation, protection); | |
866f8763 | 90 | id sik = CFBridgingRelease(SecKeyCopyAttestationKey(kSecKeyAttestationKeyTypeSIK, (void *)&error)); |
0e1db9d1 | 91 | ok(sik != nil, "get SIK key: %@", error); |
866f8763 | 92 | |
79b9da22 A |
93 | id pubSIK = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sik)); |
94 | ok(pubSIK != nil, "get SIK pubkey"); | |
95 | ||
866f8763 A |
96 | error = nil; |
97 | NSData *attSIKPlain = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)uik, (void *)&error)); | |
98 | ok(attSIKPlain != nil, "SIK attesting UIK, no nonce: %@", error); | |
99 | ||
100 | error = nil; | |
101 | NSData *attUIKPlain = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)uik, (__bridge SecKeyRef)privKey, (void *)&error)); | |
102 | ok(attUIKPlain != nil, "UIK attesting privKey, no nonce: %@", error); | |
103 | ||
104 | error = nil; | |
105 | NSData *nonce = [@"TESTnonce" dataUsingEncoding:NSUTF8StringEncoding]; | |
106 | ok(SecKeySetParameter((__bridge SecKeyRef)sik, kSecKeyParameterSETokenAttestationNonce, (__bridge CFPropertyListRef)nonce, (void *)&error), "Set nonce to SIK: %@", error); | |
107 | NSData *attSIKNonce = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)uik, (void *)&error)); | |
108 | ok(attSIKNonce != nil, "SIK attesting UIK, with nonce: %@", error); | |
866f8763 A |
109 | |
110 | error = nil; | |
111 | ok(SecKeySetParameter((__bridge SecKeyRef)uik, kSecKeyParameterSETokenAttestationNonce, (__bridge CFPropertyListRef)nonce, (void *)&error), "Set nonce to UIK: %@", error); | |
112 | NSData *attUIKNonce = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)uik, (__bridge SecKeyRef)privKey, (void *)&error)); | |
113 | ok(attUIKNonce != nil, "SIK attesting UIK, with nonce: %@", error); | |
79b9da22 A |
114 | |
115 | error = nil; | |
116 | id sysUikC = CFBridgingRelease(SecKeyCopyAttestationKey(kSecKeyAttestationKeyTypeUIKCommitted, (void *)&error)); | |
117 | if (sysUikC == nil) { | |
118 | // Platform does not support system UIK, so just fake test rounds to avoid testplan counting failures. | |
119 | for (int i = 0; i < 19; i++) { | |
120 | ok(true); | |
121 | } | |
122 | } else { | |
123 | ok(sysUikC != nil, "get UIK-committed key, error: %@", error); | |
124 | error = nil; | |
125 | id sysUikP = CFBridgingRelease(SecKeyCopyAttestationKey(kSecKeyAttestationKeyTypeUIKProposed, (void *)&error)); | |
126 | ok(sysUikP != nil, "get UIK-proposed key: %@", error); | |
127 | ||
128 | error = nil; | |
129 | NSData *attUIKC = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikC, (__bridge SecKeyRef)privKey, (void *)&error)); | |
130 | ok(attUIKC != nil, "Sys-UIK-committed attesting privKey: %@", error); | |
131 | ||
132 | error = nil; | |
133 | NSData *attUIKP = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikP, (__bridge SecKeyRef)privKey, (void *)&error)); | |
134 | ok(attUIKP != nil, "Sys-UIK-proposed attesting privKey: %@", error); | |
135 | ||
136 | id pubUIKP = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysUikP)); | |
137 | ok(pubUIKP != nil, "Sys-UIK-proposed copy public key"); | |
138 | id pubUIKC = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysUikC)); | |
139 | ok(pubUIKC != nil, "Sys-UIK-proposed copy public key"); | |
140 | ok([pubUIKP isEqual:pubUIKC], "Sys-UIK proposed and committed are same before bump"); | |
141 | ||
142 | BOOL res = SecKeyControlLifetime((__bridge SecKeyRef)sysUikC, kSecKeyControlLifetimeTypeBump, (void *)&error); | |
143 | ok(res, "bumping sys-uik: %@", error); | |
144 | ||
145 | error = nil; | |
146 | NSData *attUIKCN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikC, (__bridge SecKeyRef)privKey, (void *)&error)); | |
147 | ok(attUIKCN != nil, "Sys-UIK-committed attesting privKey: %@", error); | |
148 | ||
149 | error = nil; | |
150 | NSData *attUIKPN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikP, (__bridge SecKeyRef)privKey, (void *)&error)); | |
151 | ok(attUIKPN != nil, "Sys-UIK-proposed attesting privKey: %@", error); | |
152 | ||
153 | id pubUIKPN = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysUikP)); | |
154 | ok(pubUIKPN != nil, "Sys-UIK-proposed copy public key"); | |
155 | ok(![pubUIKPN isEqual:pubUIKC], "Sys-UIK proposed and committed differ after bump"); | |
156 | ||
157 | res = SecKeyControlLifetime((__bridge SecKeyRef)sysUikP, kSecKeyControlLifetimeTypeCommit, (void *)&error); | |
158 | ok(res, "committing sys-uik: %@", error); | |
159 | ||
160 | error = nil; | |
161 | NSData *attUIKCNN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikC, (__bridge SecKeyRef)privKey, (void *)&error)); | |
162 | ok(attUIKCNN != nil, "Sys-UIK-committed attesting privKey: %@", error); | |
163 | ||
164 | error = nil; | |
165 | NSData *attUIKPNN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikP, (__bridge SecKeyRef)privKey, (void *)&error)); | |
166 | ok(attUIKPNN != nil, "Sys-UIK-proposed attesting privKey: %@", error); | |
167 | ||
168 | id pubUIKCN = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysUikC)); | |
169 | ok(pubUIKCN != nil, "Sys-UIK-committed copy public key"); | |
170 | ok([pubUIKPN isEqual:pubUIKC], "Sys-UIK proposed and committed same after commit"); | |
171 | ||
172 | // Attest system-UIK with SIK | |
173 | NSData *attSIKUIKP = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)sysUikP, (void *)&error)); | |
174 | ok(attSIKUIKP != nil, "SIK attesting Sys-UIK-proposed, error: %@", error); | |
175 | ||
176 | NSData *attSIKUIKC = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)sysUikC, (void *)&error)); | |
177 | ok(attSIKUIKC != nil, "SIK attesting Sys-UIK-committed, error: %@", error); | |
178 | } | |
866f8763 A |
179 | } |
180 | ||
181 | int si_44_seckey_aks(int argc, char *const *argv) { | |
182 | @autoreleasepool { | |
183 | BOOL testPKA = YES; | |
184 | #if !TARGET_OS_OSX | |
79b9da22 A |
185 | NSNumber *hasPKA = (__bridge_transfer id)MGCopyAnswer(kMGQHasPKA, NULL); |
186 | if(![hasPKA isKindOfClass:NSNumber.class] || ![hasPKA boolValue]) { | |
866f8763 A |
187 | testPKA = NO; |
188 | } | |
189 | #else | |
79b9da22 A |
190 | if (remote_device_copy_unique_of_type(REMOTE_DEVICE_TYPE_EOS) == nil && remote_device_copy_unique_of_type(REMOTE_DEVICE_TYPE_BRIDGE_COPROC) == nil) { |
191 | // macOS without SEP cannot run attestations at all. | |
192 | plan_tests(1); | |
193 | ok(true); | |
194 | return 0; | |
195 | } | |
196 | ||
866f8763 A |
197 | testPKA = NO; |
198 | #endif | |
0e1db9d1 | 199 | plan_tests(testPKA ? 95 : 80); |
866f8763 | 200 | secKeySepTest(testPKA); |
0e1db9d1 A |
201 | attestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly); |
202 | attestationTest(kSecAttrAccessibleUntilReboot); | |
866f8763 A |
203 | return 0; |
204 | } | |
205 | } |