2 * Copyright (c) 2015 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@
25 * SOSBackupEvent.c - Implementation of a secure object syncing peer
28 #include <Security/SecureObjectSync/SOSBackupEvent.h>
29 #include <corecrypto/ccsha1.h>
30 #include <utilities/SecCFError.h>
31 #include <utilities/SecCFRelease.h>
32 #include <utilities/array_size.h>
33 #include <utilities/der_plist.h>
34 #include <utilities/der_plist_internal.h>
35 #include <AssertMacros.h>
42 Event ASN.1 definitions
44 ResetEvent := SEQUENCE {
45 keybag OCTET STRING OPTIONAL
63 DeleteEvent := OCTET STRING
65 CompleteEvent := INTEGER
71 complete CompleteEvent
76 static size_t der_sizeof_backup_reset(CFDataRef keybag
) {
77 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
,
78 keybag
? ccder_sizeof_raw_octet_string(CFDataGetLength(keybag
)) : 0);
81 static uint8_t* der_encode_backup_reset(CFDataRef keybag
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
) {
82 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
,
83 keybag
? ccder_encode_raw_octet_string(CFDataGetLength(keybag
), CFDataGetBytePtr(keybag
), der
, der_end
) : der_end
);
86 static size_t der_sizeof_backup_add(CFDictionaryRef add
) {
87 return der_sizeof_dictionary(add
, NULL
);
90 static uint8_t* der_encode_backup_add(CFDictionaryRef add
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
) {
91 // der_dictionary tag is CCDER_CONSTRUCTED_SET
92 return der_encode_dictionary(add
, error
, der
, der_end
);
95 static size_t der_sizeof_backup_delete(CFDataRef deletedDigest
) {
96 return ccder_sizeof_raw_octet_string(CFDataGetLength(deletedDigest
));
99 static uint8_t* der_encode_backup_delete(CFDataRef deletedDigest
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
) {
100 return ccder_encode_raw_octet_string(CFDataGetLength(deletedDigest
), CFDataGetBytePtr(deletedDigest
), der
, der_end
);
103 static size_t der_sizeof_backup_complete(uint64_t event_num
) {
104 return ccder_sizeof_uint64(event_num
);
107 static uint8_t* der_encode_backup_complete(uint64_t event_num
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
) {
108 return ccder_encode_uint64(event_num
, der
, der_end
);
116 static bool SOSBackupEventWrite(FILE *journalFile
, CFErrorRef
*error
,
118 uint8_t *(^encode
)(const uint8_t *der
, uint8_t *der_end
))
121 CFMutableDataRef derObject
= CFDataCreateMutable(kCFAllocatorDefault
, len
);
122 CFDataSetLength(derObject
, len
);
123 uint8_t *der_end
= CFDataGetMutableBytePtr(derObject
);
124 const uint8_t *der
= der_end
;
127 require(der_end
= encode(der
, der_end
), xit
);
128 require_action(der
== der_end
, xit
, SecError(-1, error
, CFSTR("size mismatch der_end - der: %td"), der_end
- der
));
130 ok
= SecCheckErrno(1 != fwrite(der
, len
, 1, journalFile
), error
, CFSTR("fwrite SOSBackupEventWrite"));
132 CFReleaseSafe(derObject
);
136 bool SOSBackupEventWriteReset(FILE *journalFile
, CFDataRef keybag
, CFErrorRef
*error
) {
137 return SOSBackupEventWrite(journalFile
, error
, der_sizeof_backup_reset(keybag
), ^uint8_t *(const uint8_t *der
, uint8_t *der_end
) {
138 return der_encode_backup_reset(keybag
, error
, der
, der_end
);
142 bool SOSBackupEventWriteDelete(FILE *journalFile
, CFDataRef deletedDigest
, CFErrorRef
*error
) {
143 return SOSBackupEventWrite(journalFile
, error
, der_sizeof_backup_delete(deletedDigest
), ^uint8_t *(const uint8_t *der
, uint8_t *der_end
) {
144 return der_encode_backup_delete(deletedDigest
, error
, der
, der_end
);
148 bool SOSBackupEventWriteAdd(FILE *journalFile
, CFDictionaryRef backup_item
, CFErrorRef
*error
) {
149 return SOSBackupEventWrite(journalFile
, error
, der_sizeof_backup_add(backup_item
), ^uint8_t *(const uint8_t *der
, uint8_t *der_end
) {
150 return der_encode_backup_add(backup_item
, error
, der
, der_end
);
154 bool SOSBackupEventWriteCompleteMarker(FILE *journalFile
, uint64_t eventID
, CFErrorRef
*error
) {
155 bool ok
= SOSBackupEventWrite(journalFile
, error
, der_sizeof_backup_complete(eventID
), ^uint8_t *(const uint8_t *der
, uint8_t *der_end
) {
156 return der_encode_backup_complete(eventID
, error
, der
, der_end
);
158 // TODO: Move this to right before we send a notification or something.