2 * Copyright (c) 2015-2016 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
29 #include "SOSRingTypes.h"
30 #include "SOSRingBasic.h"
31 #include "SOSRingBackup.h"
32 #include "SOSRingRecovery.h"
33 #include <Security/SecureObjectSync/SOSAccountPriv.h>
34 #include <Security/SecureObjectSync/SOSBackupSliceKeyBag.h>
36 // These need to track the ring type enums in SOSRingTypes.h
37 static ringFuncs ringTypes
[] = {
38 &basic
, // kSOSRingBase
39 &backup
, // kSOSRingBackup
40 NULL
, // kSOSRingPeerKeyed
41 NULL
, // kSOSRingEntropyKeyed
42 NULL
, // kSOSRingPKKeyed
43 &recovery
, // kSOSRingRecovery
45 static const size_t typecount
= sizeof(ringTypes
) / sizeof(ringFuncs
);
47 static bool SOSRingValidType(SOSRingType type
) {
48 if(type
>= typecount
|| ringTypes
[type
] == NULL
) return false;
52 // MARK: Exported Functions
55 SOSRingRef
SOSRingCreate(CFStringRef name
, CFStringRef myPeerID
, SOSRingType type
, CFErrorRef
*error
) {
56 require(SOSRingValidType(type
), errOut
);
57 require(ringTypes
[type
]->sosRingCreate
, errOut
);
58 return ringTypes
[type
]->sosRingCreate(name
, myPeerID
, error
);
60 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Not valid ring type"), NULL
, error
);
64 bool SOSRingResetToEmpty(SOSRingRef ring
, CFStringRef myPeerID
, CFErrorRef
*error
) {
65 SOSRingAssertStable(ring
);
66 SOSRingType type
= SOSRingGetType(ring
);
67 require(SOSRingValidType(type
), errOut
);
68 require(ringTypes
[type
]->sosRingResetToEmpty
, errOut
);
69 return ringTypes
[type
]->sosRingResetToEmpty(ring
, myPeerID
, error
);
71 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Not valid ring type"), NULL
, error
);
75 bool SOSRingResetToOffering(SOSRingRef ring
, SecKeyRef user_privkey
, SOSFullPeerInfoRef requestor
, CFErrorRef
*error
) {
76 SOSRingAssertStable(ring
);
77 SOSRingType type
= SOSRingGetType(ring
);
78 require(SOSRingValidType(type
), errOut
);
79 require(ringTypes
[type
]->sosRingResetToOffering
, errOut
);
80 return ringTypes
[type
]->sosRingResetToOffering(ring
, user_privkey
, requestor
, error
);
82 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Not valid ring type"), NULL
, error
);
86 SOSRingStatus
SOSRingDeviceIsInRing(SOSRingRef ring
, CFStringRef peerID
) {
87 SOSRingAssertStable(ring
);
88 SOSRingType type
= SOSRingGetType(ring
);
89 require(SOSRingValidType(type
), errOut
);
90 require(ringTypes
[type
]->sosRingDeviceIsInRing
, errOut
);
91 return ringTypes
[type
]->sosRingDeviceIsInRing(ring
, peerID
);
96 bool SOSRingApply(SOSRingRef ring
, SecKeyRef user_pubkey
, SOSFullPeerInfoRef fpi
, CFErrorRef
*error
) {
97 SOSRingAssertStable(ring
);
98 SOSRingType type
= SOSRingGetType(ring
);
99 require(SOSRingValidType(type
), errOut
);
100 require(ringTypes
[type
]->sosRingApply
, shortCircuit
);
101 require_quiet(SOSPeerInfoApplicationVerify(SOSFullPeerInfoGetPeerInfo(fpi
), user_pubkey
, error
), errOut2
);
103 return ringTypes
[type
]->sosRingApply(ring
, user_pubkey
, fpi
, error
);
105 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Not valid ring type"), NULL
, error
);
108 SOSCreateError(kSOSErrorBadSignature
, CFSTR("FullPeerInfo fails userkey signature check"), NULL
, error
);
114 bool SOSRingWithdraw(SOSRingRef ring
, SecKeyRef user_privkey
, SOSFullPeerInfoRef requestor
, CFErrorRef
*error
) {
115 SOSRingAssertStable(ring
);
116 SOSRingType type
= SOSRingGetType(ring
);
117 require(SOSRingValidType(type
), errOut
);
118 require(ringTypes
[type
]->sosRingWithdraw
, shortCircuit
);
119 return ringTypes
[type
]->sosRingWithdraw(ring
, user_privkey
, requestor
, error
);
121 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Not valid ring type"), NULL
, error
);
127 bool SOSRingGenerationSign(SOSRingRef ring
, SecKeyRef user_privkey
, SOSFullPeerInfoRef requestor
, CFErrorRef
*error
) {
128 SOSRingAssertStable(ring
);
129 SOSRingType type
= SOSRingGetType(ring
);
130 require(SOSRingValidType(type
), errOut
);
131 require(ringTypes
[type
]->sosRingGenerationSign
, shortCircuit
);
132 return ringTypes
[type
]->sosRingGenerationSign(ring
, user_privkey
, requestor
, error
);
134 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Not valid ring type"), NULL
, error
);
140 bool SOSRingConcordanceSign(SOSRingRef ring
, SOSFullPeerInfoRef requestor
, CFErrorRef
*error
) {
141 SOSRingAssertStable(ring
);
142 SOSRingType type
= SOSRingGetType(ring
);
143 require(SOSRingValidType(type
), errOut
);
144 require(ringTypes
[type
]->sosRingConcordanceSign
, shortCircuit
);
145 return ringTypes
[type
]->sosRingConcordanceSign(ring
, requestor
, error
);
147 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Not valid ring type"), NULL
, error
);
153 SOSConcordanceStatus
SOSRingConcordanceTrust(SOSFullPeerInfoRef me
, CFSetRef peers
,
154 SOSRingRef knownRing
, SOSRingRef proposedRing
,
155 SecKeyRef knownPubkey
, SecKeyRef userPubkey
,
156 CFStringRef excludePeerID
, CFErrorRef
*error
) {
157 SOSRingAssertStable(knownRing
);
158 SOSRingAssertStable(proposedRing
);
159 SOSRingType type1
= SOSRingGetType(knownRing
);
160 SOSRingType type2
= SOSRingGetType(proposedRing
);
161 require(SOSRingValidType(type1
), errOut
);
162 require(SOSRingValidType(type2
), errOut
);
163 require(type1
== type2
, errOut
);
165 secnotice("ring", "concordance trust (%s) knownRing: %@ proposedRing: %@ knownkey: %@ userkey: %@ excluded: %@",
166 ringTypes
[type1
]->typeName
, knownRing
, proposedRing
, knownPubkey
, userPubkey
, excludePeerID
);
168 require(ringTypes
[type1
]->sosRingConcordanceTrust
, errOut
);
169 return ringTypes
[type1
]->sosRingConcordanceTrust(me
, peers
, knownRing
, proposedRing
, knownPubkey
, userPubkey
, excludePeerID
, error
);
171 return kSOSConcordanceError
;
174 bool SOSRingAccept(SOSRingRef ring
, SecKeyRef user_privkey
, SOSFullPeerInfoRef requestor
, CFErrorRef
*error
) {
175 SOSRingAssertStable(ring
);
176 SOSRingType type
= SOSRingGetType(ring
);
177 require(SOSRingValidType(type
), errOut
);
178 require(ringTypes
[type
]->sosRingAccept
, shortCircuit
);
179 return ringTypes
[type
]->sosRingAccept(ring
, user_privkey
, requestor
, error
);
181 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Not valid ring type"), NULL
, error
);
187 bool SOSRingReject(SOSRingRef ring
, SecKeyRef user_privkey
, SOSFullPeerInfoRef requestor
, CFErrorRef
*error
) {
188 SOSRingAssertStable(ring
);
189 SOSRingType type
= SOSRingGetType(ring
);
190 require(SOSRingValidType(type
), errOut
);
191 require(ringTypes
[type
]->sosRingReject
, shortCircuit
);
192 return ringTypes
[type
]->sosRingReject(ring
, user_privkey
, requestor
, error
);
194 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Not valid ring type"), NULL
, error
);
200 bool SOSRingSetPayload(SOSRingRef ring
, SecKeyRef user_privkey
, CFDataRef payload
, SOSFullPeerInfoRef requestor
, CFErrorRef
*error
) {
201 SOSRingAssertStable(ring
);
202 SOSRingType type
= SOSRingGetType(ring
);
203 require(SOSRingValidType(type
), errOut
);
204 require(ringTypes
[type
]->sosRingSetPayload
, errOut
);
205 return ringTypes
[type
]->sosRingSetPayload(ring
, user_privkey
, payload
, requestor
, error
);
207 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Not valid ring type"), NULL
, error
);
211 CFDataRef
SOSRingGetPayload(SOSRingRef ring
, CFErrorRef
*error
) {
212 SOSRingAssertStable(ring
);
213 SOSRingType type
= SOSRingGetType(ring
);
214 require(SOSRingValidType(type
), errOut
);
215 require(ringTypes
[type
]->sosRingGetPayload
, errOut
);
216 return ringTypes
[type
]->sosRingGetPayload(ring
, error
);
218 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Not valid ring type"), NULL
, error
);
222 CFSetRef
SOSRingGetBackupViewset(SOSRingRef ring
, CFErrorRef
*error
) {
223 SOSRingAssertStable(ring
);
224 SOSRingType type
= SOSRingGetType(ring
);
225 require(kSOSRingBackup
== type
, errOut
);
226 return SOSRingGetBackupViewset_Internal(ring
);
228 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Not backup ring type"), NULL
, error
);
232 static bool isBackupRing(SOSRingRef ring
, CFErrorRef
*error
) {
233 SOSRingType type
= SOSRingGetType(ring
);
234 require_quiet(kSOSRingBackup
== type
, errOut
);
237 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Not backup ring type"), NULL
, error
);
241 bool SOSRingSetBackupKeyBag(SOSRingRef ring
, SOSFullPeerInfoRef fpi
, CFSetRef viewSet
, SOSBackupSliceKeyBagRef bskb
, CFErrorRef
*error
) {
242 SOSRingAssertStable(ring
);
243 CFDataRef bskb_as_data
= NULL
;
245 require_quiet(isBackupRing(ring
, error
), errOut
);
247 bskb_as_data
= SOSBSKBCopyEncoded(bskb
, error
);
248 result
= bskb_as_data
&&
249 SOSRingSetBackupViewset_Internal(ring
, viewSet
) &&
250 SOSRingSetPayload(ring
, NULL
, bskb_as_data
, fpi
, error
);
252 CFReleaseNull(bskb_as_data
);
256 SOSBackupSliceKeyBagRef
SOSRingCopyBackupSliceKeyBag(SOSRingRef ring
, CFErrorRef
*error
) {
257 SOSRingAssertStable(ring
);
259 CFDataRef bskb_as_data
= NULL
;
260 SOSBackupSliceKeyBagRef result
= NULL
;
261 require_quiet(isBackupRing(ring
, error
), errOut
);
263 bskb_as_data
= SOSRingGetPayload(ring
, error
);
264 require_quiet(bskb_as_data
, errOut
);
266 result
= SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault
, bskb_as_data
, error
);
273 bool SOSRingPKTrusted(SOSRingRef ring
, SecKeyRef pubkey
, CFErrorRef
*error
) {
274 SOSRingAssertStable(ring
);
275 SOSRingType type
= SOSRingGetType(ring
);
276 require(SOSRingValidType(type
), errOut
);
277 return SOSRingVerify(ring
, pubkey
, error
);
279 SOSCreateError(kSOSErrorUnexpectedType
, CFSTR("Not valid ring type"), NULL
, error
);
283 bool SOSRingPeerTrusted(SOSRingRef ring
, SOSFullPeerInfoRef requestor
, CFErrorRef
*error
) {
285 SOSPeerInfoRef pi
= SOSFullPeerInfoGetPeerInfo(requestor
);
286 SecKeyRef pubkey
= SOSPeerInfoCopyPubKey(pi
, error
);
287 require_quiet(pubkey
, exit
);
288 retval
= SOSRingPKTrusted(ring
, pubkey
, error
);
290 CFReleaseNull(pubkey
);