]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSBackupEvent.c
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSBackupEvent.c
1 /*
2 * Copyright (c) 2015 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 * SOSBackupEvent.c - Implementation of a secure object syncing peer
26 */
27
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>
36
37 //
38 // MARK: statics
39 //
40
41 /*
42 Event ASN.1 definitions
43
44 ResetEvent := SEQUENCE {
45 keybag OCTET STRING OPTIONAL
46 }
47
48 AddEvent := SET {
49 SEQUENCE {
50 UTF8STRING :class
51 class UTF8STRING
52 }
53 SEQUENCE {
54 UTF8STRING :hash
55 hash OCTET STRING
56 }
57 SEQUENCE {
58 UTF8STRING :data
59 data OCTET STRING
60 }
61 }
62
63 DeleteEvent := OCTET STRING
64
65 CompleteEvent := INTEGER
66
67 Event := CHOICE {
68 reset ResetEvent
69 add AddEvent
70 delete DeleteEvent
71 complete CompleteEvent
72 }
73
74 */
75
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);
79 }
80
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);
84 }
85
86 static size_t der_sizeof_backup_add(CFDictionaryRef add) {
87 return der_sizeof_dictionary(add, NULL);
88 }
89
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);
93 }
94
95 static size_t der_sizeof_backup_delete(CFDataRef deletedDigest) {
96 return ccder_sizeof_raw_octet_string(CFDataGetLength(deletedDigest));
97 }
98
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);
101 }
102
103 static size_t der_sizeof_backup_complete(uint64_t event_num) {
104 return ccder_sizeof_uint64(event_num);
105 }
106
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);
109 }
110
111
112 //
113 // MARK: SPI
114 //
115
116 static bool SOSBackupEventWrite(FILE *journalFile, CFErrorRef *error,
117 size_t len,
118 uint8_t *(^encode)(const uint8_t *der, uint8_t *der_end))
119 {
120 bool ok = false;
121 CFMutableDataRef derObject = CFDataCreateMutable(kCFAllocatorDefault, len);
122 CFDataSetLength(derObject, len);
123 uint8_t *der_end = CFDataGetMutableBytePtr(derObject);
124 const uint8_t *der = der_end;
125 der_end += len;
126
127 require(der_end = encode(der, der_end), xit);
128 require_action(der == der_end, xit, SecError(-1, error, CFSTR("size mismatch der: %zu der_end: %zu")));
129
130 ok = SecCheckErrno(1 != fwrite(der, len, 1, journalFile), error, CFSTR("fwrite %s"), journalFile);
131 xit:
132 CFReleaseSafe(derObject);
133 return ok;
134 }
135
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);
139 });
140 }
141
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);
145 });
146 }
147
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);
151 });
152 }
153
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);
157 });
158 // TODO: Move this to right before we send a notification or something.
159 fflush(journalFile);
160 return ok;
161 }