SOSRingTypes.m
1 /* 2 * Copyright (c) 2015-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 // SOSRingTypes.c 26 // 27 28 #include "SOSRing.h" 29 #include "SOSRingTypes.h" 30 #include "SOSRingBasic.h" 31 #include "SOSRingBackup.h" 32 #include "SOSRingRecovery.h" 33 #include "keychain/SecureObjectSync/SOSAccountPriv.h" 34 #include "keychain/SecureObjectSync/SOSInternal.h" 35 #include <Security/SecureObjectSync/SOSBackupSliceKeyBag.h> 36 #include <AssertMacros.h> 37 38 // These need to track the ring type enums in SOSRingTypes.h 39 static ringFuncs ringTypes[] = { 40 &basic, // kSOSRingBase 41 &backup, // kSOSRingBackup 42 NULL, // kSOSRingPeerKeyed 43 NULL, // kSOSRingEntropyKeyed 44 NULL, // kSOSRingPKKeyed 45 &recovery, // kSOSRingRecovery 46 }; 47 static const size_t typecount = sizeof(ringTypes) / sizeof(ringFuncs); 48 49 static bool SOSRingValidType(SOSRingType type) { 50 if(type >= typecount || ringTypes[type] == NULL) return false; 51 return true; 52 } 53 54 // MARK: Exported Functions 55 56 57 SOSRingRef SOSRingCreate(CFStringRef name, CFStringRef myPeerID, SOSRingType type, CFErrorRef *error) { 58 if(!SOSRingValidType(type)){ 59 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); 60 return NULL; 61 } 62 if(!(ringTypes[type]->sosRingCreate)){ 63 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); 64 return NULL; 65 } 66 return ringTypes[type]->sosRingCreate(name, myPeerID, error); 67 } 68 69 bool SOSRingResetToEmpty(SOSRingRef ring, CFStringRef myPeerID, CFErrorRef *error) { 70 SOSRingAssertStable(ring); 71 SOSRingType type = SOSRingGetType(ring); 72 if(!SOSRingValidType(type)){ 73 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); 74 return false; 75 } 76 if(!ringTypes[type]->sosRingResetToEmpty){ 77 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); 78 return false; 79 } 80 return ringTypes[type]->sosRingResetToEmpty(ring, myPeerID, error); 81 } 82 83 bool SOSRingGenerationSign(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) { 84 SOSRingAssertStable(ring); 85 SOSRingType type = SOSRingGetType(ring); 86 if(!(SOSRingValidType(type))){ 87 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); 88 return false; 89 } 90 if(!(ringTypes[type]->sosRingGenerationSign)){ 91 return true; 92 } 93 return ringTypes[type]->sosRingGenerationSign(ring, user_privkey, requestor, error); 94 } 95 96 bool SOSRingConcordanceSign(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFErrorRef *error) { 97 SOSRingAssertStable(ring); 98 SOSRingType type = SOSRingGetType(ring); 99 if(!(SOSRingValidType(type))){ 100 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); 101 return false; 102 } 103 if(!(ringTypes[type]->sosRingConcordanceSign)){ 104 return true; 105 } 106 return ringTypes[type]->sosRingConcordanceSign(ring, requestor, error); 107 } 108 109 SOSConcordanceStatus SOSRingConcordanceTrust(SOSFullPeerInfoRef me, CFSetRef peers, 110 SOSRingRef knownRing, SOSRingRef proposedRing, 111 SecKeyRef knownPubkey, SecKeyRef userPubkey, 112 CFStringRef excludePeerID, CFErrorRef *error) { 113 SOSRingAssertStable(knownRing); 114 SOSRingAssertStable(proposedRing); 115 SOSRingType type1 = SOSRingGetType(knownRing); 116 SOSRingType type2 = SOSRingGetType(proposedRing); 117 if(!(SOSRingValidType(type1))){ 118 return kSOSConcordanceError; 119 } 120 if(!(SOSRingValidType(type2))){ 121 return kSOSConcordanceError; 122 } 123 if((type1 != type2)){ 124 return kSOSConcordanceError; 125 } 126 127 secnotice("ring", "concordance trust (%s)", ringTypes[type1]->typeName); 128 secnotice("ring", " knownRing: %@", knownRing); 129 secnotice("ring", " proposedRing: %@", proposedRing); 130 CFStringRef knownKeyID = SOSCopyIDOfKeyWithLength(knownPubkey, 8, NULL); 131 CFStringRef userKeyID = SOSCopyIDOfKeyWithLength(userPubkey, 8, NULL); 132 CFStringRef mypeerSPID = CFStringCreateTruncatedCopy(excludePeerID, 8); 133 134 secnotice("ring", "knownkey: %@ userkey: %@ myPeerID: %@", knownKeyID, userKeyID, mypeerSPID); 135 CFReleaseNull(knownKeyID); 136 CFReleaseNull(userKeyID); 137 CFReleaseNull(mypeerSPID); 138 139 if(!(ringTypes[type1]->sosRingConcordanceTrust)){ 140 return kSOSConcordanceError; 141 } 142 return ringTypes[type1]->sosRingConcordanceTrust(me, peers, knownRing, proposedRing, knownPubkey, userPubkey, excludePeerID, error); 143 } 144 145 bool SOSRingAccept(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) { 146 SOSRingAssertStable(ring); 147 SOSRingType type = SOSRingGetType(ring); 148 if(!(SOSRingValidType(type))){ 149 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); 150 return false; 151 } 152 if(!(ringTypes[type]->sosRingAccept)){ 153 return true; 154 } 155 return ringTypes[type]->sosRingAccept(ring, user_privkey, requestor, error); 156 } 157 158 bool SOSRingReject(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) { 159 SOSRingAssertStable(ring); 160 SOSRingType type = SOSRingGetType(ring); 161 if(!(SOSRingValidType(type))){ 162 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); 163 return false; 164 } 165 if(!(ringTypes[type]->sosRingReject)){ 166 return true; 167 } 168 return ringTypes[type]->sosRingReject(ring, user_privkey, requestor, error); 169 } 170 171 bool SOSRingSetPayload(SOSRingRef ring, SecKeyRef user_privkey, CFDataRef payload, SOSFullPeerInfoRef requestor, CFErrorRef *error) { 172 SOSRingAssertStable(ring); 173 SOSRingType type = SOSRingGetType(ring); 174 if(!(SOSRingValidType(type))){ 175 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); 176 return false; 177 } 178 if(!(ringTypes[type]->sosRingSetPayload)){ 179 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); 180 return false; 181 } 182 return ringTypes[type]->sosRingSetPayload(ring, user_privkey, payload, requestor, error); 183 } 184 185 CFDataRef SOSRingGetPayload(SOSRingRef ring, CFErrorRef *error) { 186 SOSRingAssertStable(ring); 187 SOSRingType type = SOSRingGetType(ring); 188 if(!SOSRingValidType(type)){ 189 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); 190 return NULL; 191 } 192 if(!ringTypes[type]->sosRingGetPayload){ 193 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); 194 return NULL; 195 }; 196 return ringTypes[type]->sosRingGetPayload(ring, error); 197 } 198 199 CFSetRef SOSRingGetBackupViewset(SOSRingRef ring, CFErrorRef *error) { 200 SOSRingAssertStable(ring); 201 SOSRingType type = SOSRingGetType(ring); 202 if(kSOSRingBackup != type){ 203 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not backup ring type"), NULL, error); 204 return NULL; 205 } 206 return SOSRingGetBackupViewset_Internal(ring); 207 } 208 209 // This returns one string with the view for the ring - we never used multi-view rings 210 CFStringRef SOSRingGetBackupView(SOSRingRef ring, CFErrorRef *error) { 211 __block CFStringRef result = NULL; 212 CFSetRef allTheViews = SOSRingGetBackupViewset(ring, error); 213 if(allTheViews) { 214 if(CFSetGetCount(allTheViews) == 1) { 215 CFSetForEach(allTheViews, ^(const void *value) { 216 result = asString(value, error); 217 }); 218 } 219 } else { 220 SOSCreateError(kSOSErrorParam, CFSTR("Wrong set count for one return"), NULL, error); 221 } 222 return result; 223 } 224 225 static bool isBackupRing(SOSRingRef ring, CFErrorRef *error) { 226 SOSRingType type = SOSRingGetType(ring); 227 if(kSOSRingBackup != type){ 228 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not backup ring type"), NULL, error); 229 return false; 230 } 231 return true; 232 } 233 234 bool SOSRingSetBackupKeyBag(SOSRingRef ring, SOSFullPeerInfoRef fpi, CFSetRef viewSet, SOSBackupSliceKeyBagRef bskb, CFErrorRef *error) { 235 SOSRingAssertStable(ring); 236 CFDataRef bskb_as_data = NULL; 237 bool result = false; 238 if(!isBackupRing(ring, error)){ 239 CFReleaseNull(bskb_as_data); 240 return result; 241 } 242 243 bskb_as_data = SOSBSKBCopyEncoded(bskb, error); 244 result = bskb_as_data && 245 SOSRingSetBackupViewset_Internal(ring, viewSet) && 246 SOSRingSetPayload(ring, NULL, bskb_as_data, fpi, error); 247 CFReleaseNull(bskb_as_data); 248 return result; 249 } 250 251 SOSBackupSliceKeyBagRef SOSRingCopyBackupSliceKeyBag(SOSRingRef ring, CFErrorRef *error) { 252 SOSRingAssertStable(ring); 253 254 CFDataRef bskb_as_data = NULL; 255 SOSBackupSliceKeyBagRef result = NULL; 256 if(!isBackupRing(ring, error)){ 257 return result; 258 } 259 260 bskb_as_data = SOSRingGetPayload(ring, error); 261 if(!bskb_as_data){ 262 return result; 263 } 264 result = SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault, bskb_as_data, error); 265 return result; 266 } 267 268 bool SOSRingPKTrusted(SOSRingRef ring, SecKeyRef pubkey, CFErrorRef *error) { 269 SOSRingAssertStable(ring); 270 SOSRingType type = SOSRingGetType(ring); 271 if(!(SOSRingValidType(type))){ 272 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); 273 return false; 274 }; 275 return SOSRingVerify(ring, pubkey, error); 276 } 277 278 bool SOSRingPeerTrusted(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFErrorRef *error) { 279 bool retval = false; 280 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(requestor); 281 SecKeyRef pubkey = SOSPeerInfoCopyPubKey(pi, error); 282 require_quiet(pubkey, exit); 283 retval = SOSRingPKTrusted(ring, pubkey, error); 284 exit: 285 CFReleaseNull(pubkey); 286 return retval; 287 }