2 * Copyright (c) 2017 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@
26 #include <AssertMacros.h>
28 #import <Foundation/Foundation.h>
29 #import <Foundation/NSKeyedArchiver_Private.h>
33 #include <utilities/SecDb.h>
34 #include "keychain/securityd/SecDbItem.h"
35 #include "keychain/securityd/SecItemSchema.h"
37 #import <CloudKit/CloudKit.h>
40 @implementation CKKSCKRecordHolder
42 - (instancetype) initWithCKRecord: (CKRecord*) record {
43 if(self = [super init]) {
44 _zoneID = record.recordID.zoneID;
45 [self setFromCKRecord:record];
50 - (instancetype)initWithCKRecordType: (NSString*) recordType encodedCKRecord: (NSData*) encodedCKRecord zoneID:(CKRecordZoneID*)zoneID {
51 if(self = [super init]) {
53 _ckRecordType = recordType;
54 _encodedCKRecord = encodedCKRecord;
56 if(self.encodedCKRecord && ![self.storedCKRecord.recordID.zoneID isEqual: self.zoneID]) {
57 secerror("ckks: mismatching zone ids in a single record: %@ and %@", self.zoneID, self.storedCKRecord.recordID.zoneID);
63 - (CKRecord*) storedCKRecord {
64 if(!_encodedCKRecord) {
67 NSKeyedUnarchiver *coder = [[NSKeyedUnarchiver alloc] initForReadingFromData:_encodedCKRecord error:nil];
68 CKRecord* ckRecord = [[CKRecord alloc] initWithCoder:coder];
69 [coder finishDecoding];
74 - (void) setStoredCKRecord: (CKRecord*) ckRecord {
76 _encodedCKRecord = nil;
79 self.zoneID = ckRecord.recordID.zoneID;
80 self.ckRecordType = ckRecord.recordType;
82 NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES];
83 [ckRecord encodeWithCoder:archiver];
84 _encodedCKRecord = archiver.encodedData;
87 - (CKRecord*) CKRecordWithZoneID: (CKRecordZoneID*) zoneID {
88 CKRecordID* recordID = [[CKRecordID alloc] initWithRecordName: [self CKRecordName] zoneID: zoneID];
89 CKRecord* record = nil;
91 if(self.encodedCKRecord == nil) {
92 record = [[CKRecord alloc] initWithRecordType:self.ckRecordType recordID:recordID];
94 record = self.storedCKRecord;
97 [self updateCKRecord:record zoneID:zoneID];
99 self.storedCKRecord = record;
103 - (NSString*) CKRecordName {
104 @throw [NSException exceptionWithName:NSInternalInconsistencyException
105 reason:[NSString stringWithFormat:@"%@ must override %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]
108 - (CKRecord*) updateCKRecord: (CKRecord*) record zoneID: (CKRecordZoneID*) zoneID {
109 @throw [NSException exceptionWithName:NSInternalInconsistencyException
110 reason:[NSString stringWithFormat:@"%@ must override %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]
113 - (void) setFromCKRecord: (CKRecord*) record {
114 @throw [NSException exceptionWithName:NSInternalInconsistencyException
115 reason:[NSString stringWithFormat:@"%@ must override %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]
118 - (bool) matchesCKRecord: (CKRecord*) record {
119 @throw [NSException exceptionWithName:NSInternalInconsistencyException
120 reason:[NSString stringWithFormat:@"%@ must override %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]
124 - (instancetype)copyWithZone:(NSZone *)zone {
125 CKKSCKRecordHolder *rhCopy = [super copyWithZone:zone];
126 rhCopy->_zoneID = _zoneID;
127 rhCopy->_ckRecordType = _ckRecordType;
128 rhCopy->_encodedCKRecord = _encodedCKRecord;