]>
Commit | Line | Data |
---|---|---|
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 | } |