]> git.saurik.com Git - apple/security.git/blob - keychain/ot/OTIdentity.m
Security-58286.251.4.tar.gz
[apple/security.git] / keychain / ot / OTIdentity.m
1 /*
2 * Copyright (c) 2017 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 #if OCTAGON
24
25 #import "OTIdentity.h"
26
27 #import <SecurityFoundation/SFKey.h>
28 #import <SecurityFoundation/SFKey_Private.h>
29 #import "keychain/ot/OTDefines.h"
30
31 #import <Security/SecureObjectSync/SOSAccountTransaction.h>
32 #pragma clang diagnostic push
33 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
34 #import <Security/SecureObjectSync/SOSAccount.h>
35 #pragma clang diagnostic pop
36
37 @interface OTIdentity ()
38
39 @property (nonatomic, strong) NSString* peerID;
40 @property (nonatomic, strong) NSString* spID;
41 @property (nonatomic, strong) SFECKeyPair* peerSigningKey;
42 @property (nonatomic, strong) SFECKeyPair* peerEncryptionKey;
43
44 @end
45
46 @implementation OTIdentity
47
48 - (instancetype) initWithPeerID:(nullable NSString*)peerID
49 spID:(nullable NSString*)spID
50 peerSigningKey:(SFECKeyPair*)peerSigningKey
51 peerEncryptionkey:(SFECKeyPair*)peerEncryptionKey
52 error:(NSError**)error
53 {
54 self = [super init];
55 if (self) {
56 _peerID = peerID;
57 _spID = spID;
58 _peerSigningKey = peerSigningKey;
59 _peerEncryptionKey = peerEncryptionKey;
60 }
61 return self;
62 }
63
64 + (nullable instancetype) currentIdentityFromSOS:(NSError**)error
65 {
66 CFErrorRef circleCheckError = NULL;
67 SOSCCStatus circleStatus = SOSCCThisDeviceIsInCircle(&circleCheckError);
68 if(circleStatus != kSOSCCInCircle){
69 if(circleCheckError){
70 secerror("octagon: cannot retrieve octagon keys from SOS, not in circle, error: %@", circleCheckError);
71 if(error){
72 *error = (__bridge NSError*)circleCheckError;
73 }
74 }
75 secerror("octagon: current circle status: %d",circleStatus);
76 return nil;
77 }
78 __block NSString* sosPeerID = nil;
79 __block NSError* sosPeerIDError = nil;
80
81 SOSCCPerformWithPeerID(^(CFStringRef peerID, CFErrorRef error) {
82 sosPeerID = (__bridge NSString *)(peerID);
83 if(error){
84 secerror("octagon: retrieving sos peer id error: %@", error);
85 sosPeerIDError = CFBridgingRelease(error);
86 }
87 });
88
89 if(sosPeerID == nil || sosPeerIDError != nil){
90 secerror("octagon: cannot retrieve peer id from SOS, error: %@", sosPeerIDError);
91 if(error){
92 *error = sosPeerIDError;
93 }
94 return nil;
95 }
96
97 __block SFECKeyPair *peerEncryptionKey;
98 __block SFECKeyPair *peerSigningKey;
99 __block NSError* localError = nil;
100
101 SOSCCPerformWithAllOctagonKeys(^(SecKeyRef octagonEncryptionKey, SecKeyRef octagonSigningKey, CFErrorRef cferror) {
102 if(cferror) {
103 localError = (__bridge NSError*)cferror;
104 return;
105 }
106 if (!cferror && octagonEncryptionKey && octagonSigningKey) {
107 peerSigningKey = [[SFECKeyPair alloc] initWithSecKey:octagonSigningKey];
108 peerEncryptionKey = [[SFECKeyPair alloc] initWithSecKey:octagonEncryptionKey];
109
110 }
111 });
112
113 if(!peerEncryptionKey || !peerSigningKey || localError != nil){
114 secerror("octagon: failed to retrieve octagon keys from sos: %@", localError);
115 if(error){
116 *error = localError;
117 }
118 return nil;
119 }
120 return [[OTIdentity alloc] initWithPeerID:nil
121 spID:sosPeerID
122 peerSigningKey:peerSigningKey
123 peerEncryptionkey:peerEncryptionKey
124 error:error];
125 }
126
127 -(BOOL)isEqual:(OTIdentity*)identity
128 {
129 return [self.peerID isEqualToString:identity.peerID] &&
130 [self.spID isEqualToString:identity.spID] &&
131 [self.peerSigningKey isEqual:identity.peerSigningKey] &&
132 [self.peerEncryptionKey isEqual:identity.peerEncryptionKey];
133 }
134
135 + (BOOL) setKeyMaterialInKeychain:(NSDictionary*)query error:(NSError* __autoreleasing *)error
136 {
137 BOOL result = NO;
138
139 CFTypeRef results = NULL;
140 OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, &results);
141
142 NSError* localerror = nil;
143
144 if(status == errSecDuplicateItem || status == errSecSuccess) {
145 result = YES;
146 } else {
147 localerror = [NSError errorWithDomain:@"securityd"
148 code:status
149 userInfo:nil];
150 }
151 if(status != errSecSuccess) {
152 CFReleaseNull(results);
153
154 if(error) {
155 *error = localerror;
156 }
157 }
158
159 return result;
160 }
161
162 + (BOOL)storeOtagonKey:(NSData*)keyData
163 octagonKeyType:(OctagonKeyType)octagonKeyType
164 restoredPeerID:(NSString*)restoredPeerID
165 escrowSigningPubKeyHash:(NSString*)escrowSigningPubKeyHash
166 error:(NSError**)error
167 {
168 NSNumber *keyType = [[NSNumber alloc]initWithInt:octagonKeyType];
169
170 NSDictionary* query = @{
171 (id)kSecClass : (id)kSecClassInternetPassword,
172 (id)kSecAttrAccessible: (id)kSecAttrAccessibleWhenUnlocked,
173 (id)kSecAttrNoLegacy : @YES,
174 (id)kSecAttrLabel : escrowSigningPubKeyHash,
175 (id)kSecAttrAccount : restoredPeerID,
176 (id)kSecAttrType : keyType,
177 (id)kSecAttrServer : (octagonKeyType == 1) ? @"Octagon Signing Key" : @"Octagon Encryption Key",
178 (id)kSecAttrAccessGroup: @"com.apple.security.ckks",
179 (id)kSecAttrSynchronizable : (id)kCFBooleanFalse,
180 (id)kSecValueData : keyData,
181 };
182 return [OTIdentity setKeyMaterialInKeychain:query error:error];
183
184 }
185
186 +(BOOL) storeOctagonIdentityIntoKeychain:(_SFECKeyPair *)restoredSigningKey
187 restoredEncryptionKey:(_SFECKeyPair *)restoredEncryptionKey
188 escrowSigningPubKeyHash:(NSString *)escrowSigningPubKeyHash
189 restoredPeerID:(NSString *)peerID
190 error:(NSError**)error
191 {
192 NSError* localError = nil;
193
194 BOOL result = [OTIdentity storeOtagonKey:[restoredSigningKey keyData] octagonKeyType:OctagonSigningKey restoredPeerID:peerID escrowSigningPubKeyHash:escrowSigningPubKeyHash error:&localError];
195 if(!result || localError){
196 secerror("octagon: could not store octagon signing key in keychain:%@", localError);
197 if(error){
198 *error = localError;
199 }
200 return NO;
201 }
202 result = [OTIdentity storeOtagonKey:[restoredEncryptionKey keyData] octagonKeyType:OctagonEncryptionKey restoredPeerID:peerID escrowSigningPubKeyHash:escrowSigningPubKeyHash error:&localError];
203 if(!result || localError){
204 secerror("octagon: could not store octagon encryption key in keychain:%@", localError);
205 if(error){
206 *error = localError;
207 }
208 return NO;
209 }
210 return result;
211 }
212
213 @end
214 #endif