]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecServerEncryptionSupport.c
Security-57740.31.2.tar.gz
[apple/security.git] / OSX / sec / Security / SecServerEncryptionSupport.c
1 //
2 // SecServerEncryptionSupport.c
3 // sec
4 //
5 //
6
7 #include <TargetConditionals.h>
8
9 #include <AssertMacros.h>
10 #include <Security/SecServerEncryptionSupport.h>
11 #include <Security/SecECKeyPriv.h>
12
13 #include <utilities/SecCFError.h>
14 #include <utilities/SecCFWrappers.h>
15
16 #include <Security/SecKeyInternal.h>
17
18 #include <Security/SecBasePriv.h>
19
20 #include <corecrypto/ccsha2.h>
21 #include <corecrypto/ccecies.h>
22 #include <corecrypto/ccaes.h>
23 #include <corecrypto/ccder.h>
24
25 //
26 // We assume that SecKey is set up for this to work.
27 // Specifically ccrng_seckey needs to be initialized
28 //
29 // As it happens we work in terms of SecKeys at the
30 // higher level, so we're good.
31 //
32
33 const uint32_t kBlobCipherKeySize = CCAES_KEY_SIZE_128;
34 const uint32_t kBlobMacSize = 16;
35
36 static void InitServerECIES(ccecies_gcm_t ecies, const struct ccmode_gcm *gcm_mode)
37 {
38 ccecies_encrypt_gcm_setup(ecies,
39 ccsha256_di(),
40 ccrng_seckey,
41 gcm_mode,
42 kBlobCipherKeySize,
43 kBlobMacSize,
44 ECIES_EXPORT_PUB_STANDARD+ECIES_EPH_PUBKEY_IN_SHAREDINFO1);
45 }
46
47 //
48 // Der Encode
49 //
50
51 //
52 // EncryptedPayloadToServerVersion ::= INTEGER {v1(1)}
53 //
54 // EncryptedPayloadToServer ::= SEQUENCE {
55 // version EncryptedPayloadToServerVersion DEFAULT v1,
56 // ephemeralPublicKey OCTET STRING,
57 // GCMEncryptedData OCTET STRING,
58 // GCMTag OCTET STRING
59 // }
60
61
62 enum {
63 SERVER_BLOB_ENCRYPTED_DATA = 0
64 };
65
66 static size_t sizeof_implicit_nocopy(ccder_tag implicit_tag, size_t space)
67 {
68 return ccder_sizeof(implicit_tag, space);
69 }
70
71 static uint8_t *encode_implicit_nocopy(ccder_tag implicit_tag, size_t size, uint8_t**start, const uint8_t *der, uint8_t *der_end)
72 {
73 if (start == NULL)
74 return NULL;
75
76 return ccder_encode_tl(implicit_tag, size, der,
77 (*start = ccder_encode_body_nocopy(size, der, der_end)));
78 }
79
80 static uint8_t *encode_octect_string_nocopy(size_t size, uint8_t**start, const uint8_t *der, uint8_t *der_end)
81 {
82 return encode_implicit_nocopy(CCDER_OCTET_STRING, size, start, der, der_end);
83 }
84
85 static size_t sizeof_server_blob(size_t public_key_size,
86 size_t ciphertext_size,
87 size_t verifier_size)
88 {
89 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE,
90 sizeof_implicit_nocopy(CCDER_OCTET_STRING, public_key_size) +
91 sizeof_implicit_nocopy(CCDER_OCTET_STRING, ciphertext_size) +
92 sizeof_implicit_nocopy(CCDER_OCTET_STRING, verifier_size));
93 }
94
95
96 static uint8_t* encode_empty_server_blob_for(size_t public_key_size, uint8_t **public_key_start,
97 size_t ciphertext_size, uint8_t **ciphertext,
98 size_t verifier_size, uint8_t **verifier,
99 const uint8_t *der, uint8_t *der_end)
100 {
101 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
102 encode_octect_string_nocopy(public_key_size, public_key_start, der,
103 encode_octect_string_nocopy(ciphertext_size, ciphertext, der,
104 encode_octect_string_nocopy(verifier_size, verifier, der, der_end))));
105 }
106
107 static const uint8_t* decode_octect_string(size_t* size, const uint8_t ** start, const uint8_t *der, const uint8_t* der_end)
108 {
109 if (size == NULL)
110 return NULL;
111
112 der = ccder_decode_tl(CCDER_OCTET_STRING, size, der, der_end);
113
114 if (der && start) {
115 *start = der;
116 der += *size;
117 }
118
119 return der;
120 }
121
122 static const uint8_t* decode_server_blob(size_t *public_key_size, const uint8_t **public_key_start,
123 size_t *ciphertext_size, const uint8_t **ciphertext,
124 size_t *verifier_size, const uint8_t **verifier,
125 CFErrorRef *error, const uint8_t *der, const uint8_t *der_end)
126 {
127 const uint8_t *sequence_end;
128 der = ccder_decode_sequence_tl(&sequence_end, der, der_end);
129
130 if (der_end != sequence_end)
131 der = NULL;
132
133 der = decode_octect_string(public_key_size, public_key_start, der, der_end);
134 der = decode_octect_string(ciphertext_size, ciphertext, der, der_end);
135 der = decode_octect_string(verifier_size, verifier, der, der_end);
136
137 return der;
138 }
139
140 static CFMutableDataRef CreateDataForEncodeEncryptedBlobOf(ccec_pub_ctx_t public_key,
141 size_t public_key_size, uint8_t **public_key_start,
142 size_t ciphertext_size, uint8_t **ciphertext,
143 size_t verifier_size, uint8_t **verifier,
144 CFErrorRef *error)
145 {
146 CFMutableDataRef result = NULL;
147 CFMutableDataRef allocated = CFDataCreateMutableWithScratch(kCFAllocatorDefault, sizeof_server_blob(public_key_size, ciphertext_size, verifier_size));
148
149 require_action_quiet(allocated, fail, SecError(errSecAllocate, error, CFSTR("failed to create data")));
150
151 uint8_t *der = CFDataGetMutableBytePtr(allocated);
152 uint8_t *der_end = der + CFDataGetLength(allocated);
153
154 der = encode_empty_server_blob_for(public_key_size, public_key_start,
155 ciphertext_size, ciphertext,
156 verifier_size, verifier,
157 der, der_end);
158
159 require_action_quiet(der, fail, SecError(errSecParam, error, CFSTR("Encoding failed")));
160
161 CFRetainAssign(result, allocated);
162
163 fail:
164 CFReleaseNull(allocated);
165 return result;
166 }
167
168 static bool ParseAndFindEncryptedData(CFDataRef blob,
169 size_t *public_key_size, const uint8_t **public_key_start,
170 size_t *ciphertext_size, const uint8_t **ciphertext,
171 size_t *verifier_size, const uint8_t **verifier,
172 CFErrorRef *error)
173 {
174 bool success = false;
175 const uint8_t *der = CFDataGetBytePtr(blob);
176 const uint8_t *der_end = der + CFDataGetLength(blob);
177 der = decode_server_blob(public_key_size, public_key_start,
178 ciphertext_size, ciphertext,
179 verifier_size, verifier,
180 error, der, der_end);
181
182 require_action_quiet(der == der_end, fail, SecError(errSecParam, error, CFSTR("Blob failed to decode")));
183
184 success = true;
185 fail:
186 return success;
187
188 }
189
190 static size_t ccec_x963_pub_export_size(ccec_pub_ctx_t key)
191 {
192 return ccec_x963_export_size(0,(ccec_full_ctx_t)key.body); // We lie since the API is broken.
193 }
194
195 CFDataRef SecCopyEncryptedToServerKey(SecKeyRef publicKey, CFDataRef dataToEncrypt, CFErrorRef *error)
196 {
197 __block CFDataRef result = NULL;
198
199
200 SecECDoWithPubKey(publicKey, error, ^(ccec_pub_ctx_t public_key) {
201 CFMutableDataRef encrypted = NULL;
202
203 struct ccecies_gcm ecies_encrypt;
204 InitServerECIES(&ecies_encrypt, ccaes_gcm_encrypt_mode());
205
206 size_t plain_size = CFDataGetLength(dataToEncrypt);
207 size_t encrypted_size = ccecies_encrypt_gcm_ciphertext_size(public_key, &ecies_encrypt, plain_size);
208
209 CFMutableDataRef encryption_temp = CFDataCreateMutableWithScratch(kCFAllocatorDefault, encrypted_size);
210 require_action_quiet(encryption_temp, errout, SecError(errSecAllocate, error, CFSTR("failed to create data")));
211
212 uint8_t *encryption_buffer = (uint8_t *) CFDataGetMutableBytePtr(encryption_temp);
213
214 int encrypt_result = ccecies_encrypt_gcm(public_key,
215 &ecies_encrypt,
216 plain_size, CFDataGetBytePtr(dataToEncrypt),
217 0, NULL,
218 0, NULL,
219 &encrypted_size, encryption_buffer);
220
221
222 size_t public_key_size = ccec_x963_pub_export_size(public_key);
223 uint8_t *public_key_data = NULL;
224 size_t ciphertext_size = plain_size;
225 uint8_t *ciphertext = NULL;
226 size_t tag_size = kBlobMacSize;
227 uint8_t *tag = NULL;
228
229 require_action_quiet(public_key_size + ciphertext_size + tag_size == encrypted_size, errout, SecError(errSecInternal, error, CFSTR("Allocation mismatch"), encrypt_result));
230
231 encrypted = CreateDataForEncodeEncryptedBlobOf(public_key,
232 public_key_size, &public_key_data,
233 ciphertext_size, &ciphertext,
234 tag_size, &tag,
235 error);
236 require_quiet(encrypted, errout);
237
238 //
239 // Core crypto SPI a work in progress, until then we copy.
240 //
241
242 memcpy(public_key_data, encryption_buffer, public_key_size);
243 memcpy(ciphertext, encryption_buffer + public_key_size, ciphertext_size);
244 memcpy(tag, encryption_buffer + public_key_size + ciphertext_size, tag_size);
245
246 require_action_quiet(encrypt_result == 0, errout, SecError(errSecBadReq, error, CFSTR("ccecies_encrypt_gcm failed %d"), encrypt_result));
247
248 CFRetainAssign(result, encrypted);
249 errout:
250 CFReleaseSafe(encryption_temp);
251 CFReleaseSafe(encrypted);
252 });
253
254
255 return result;
256 }
257
258
259 CFDataRef SecCopyDecryptedForServer(SecKeyRef serverFullKey, CFDataRef blob, CFErrorRef* error)
260 {
261 __block CFDataRef result = NULL;
262
263 SecECDoWithFullKey(serverFullKey, error, ^(ccec_full_ctx_t private_key) {
264 CFMutableDataRef plain = NULL;
265 CFMutableDataRef crypto_buffer = NULL;
266 size_t encrypted_size;
267
268 size_t plain_size;
269
270 struct ccecies_gcm ecies_decrypt;
271 InitServerECIES(&ecies_decrypt, ccaes_gcm_decrypt_mode());
272 size_t public_key_size;
273 const uint8_t *public_key_start = NULL;
274 size_t ciphertext_size;
275 const uint8_t *ciphertext = NULL;
276 size_t verifier_size;
277 const uint8_t *verifier = NULL;
278
279 require_quiet(ParseAndFindEncryptedData(blob,
280 &public_key_size, &public_key_start,
281 &ciphertext_size, &ciphertext,
282 &verifier_size, &verifier,
283 error), errout);
284
285 require_quiet(public_key_start, errout); // Silence analyzer, shouldn't ever happen.
286 require_quiet(ciphertext, errout); // Silence analyzer, shouldn't ever happen.
287 require_quiet(verifier, errout); // Silence analyzer, shouldn't ever happen.
288
289 encrypted_size = public_key_size + ciphertext_size + verifier_size;
290 crypto_buffer = CFDataCreateMutableWithScratch(kCFAllocatorDefault, encrypted_size);
291 require_action_quiet(crypto_buffer, errout, SecError(errSecAllocate, error, CFSTR("failed to create data")));
292
293 uint8_t *crypto_buffer_ptr = CFDataGetMutableBytePtr(crypto_buffer);
294 memcpy(crypto_buffer_ptr, public_key_start, public_key_size);
295 memcpy(crypto_buffer_ptr + public_key_size, ciphertext, ciphertext_size);
296 memcpy(crypto_buffer_ptr + public_key_size + ciphertext_size, verifier, verifier_size);
297
298
299 plain_size = ccecies_decrypt_gcm_plaintext_size(private_key, &ecies_decrypt, encrypted_size);
300 plain = CFDataCreateMutableWithScratch(kCFAllocatorDefault, plain_size);
301
302 int decrypt_result = ccecies_decrypt_gcm(private_key,
303 &ecies_decrypt,
304 encrypted_size, crypto_buffer_ptr,
305 0, NULL,
306 0, NULL,
307 &plain_size, CFDataGetMutableBytePtr(plain));
308
309 require_action_quiet(decrypt_result == 0, errout, SecError(errSecBadReq, error, CFSTR("ccecies_decrypt_gcm failed %d"), decrypt_result));
310
311 CFRetainAssign(result, plain);
312
313 errout:
314 CFReleaseSafe(plain);
315 CFReleaseSafe(crypto_buffer);
316 });
317
318 return result;
319 }
320
321 #if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_EMBEDDED)
322 #include <Security/SecTrustInternal.h>
323 #endif
324
325 CFDataRef SecCopyEncryptedToServer(SecTrustRef trustedEvaluation, CFDataRef dataToEncrypt, CFErrorRef *error)
326 {
327 CFDataRef result = NULL;
328 #if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_EMBEDDED)
329 SecKeyRef trustKey = SecTrustCopyPublicKey_ios(trustedEvaluation);
330 #else
331 SecKeyRef trustKey = SecTrustCopyPublicKey(trustedEvaluation);
332 #endif
333
334 require_action_quiet(trustKey, fail,
335 SecError(errSecInteractionNotAllowed, error, CFSTR("Failed to get key out of trust ref, was it evaluated?")));
336
337
338 result = SecCopyEncryptedToServerKey(trustKey, dataToEncrypt, error);
339
340 fail:
341 CFReleaseNull(trustKey);
342 return result;
343 }