]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSForerunnerSession.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSForerunnerSession.c
1 #include "SOSForerunnerSession.h"
2 #include "SOSAccountDer.c"
3 #include "SOSPlatform.h"
4
5 #include <CoreFoundation/CFRuntime.h>
6 #include <utilities/SecCFWrappers.h>
7 #include <utilities/SecCFError.h>
8 #include <Security/SecureObjectSync/SOSInternal.h>
9 #include <corecrypto/ccsrp.h>
10 #include <corecrypto/ccsha2.h>
11 #include <corecrypto/ccdh_gp.h>
12 #include <corecrypto/ccder.h>
13 #include <corecrypto/ccaes.h>
14 #include <corecrypto/ccmode.h>
15 #include <corecrypto/cchkdf.h>
16 #include <CommonCrypto/CommonRandomSPI.h>
17 #include <os/assumes.h>
18 #include <AssertMacros.h>
19
20 #pragma mark Definitions
21 #define FR_VERSION 1llu
22 #define FR_MAGIC_REQUEST 0x67756d70llu
23 #define FR_MAGIC_CHALLENGE 0x67756d71llu
24 #define FR_MAGIC_RESPONSE 0x67756d72llu
25 #define FR_MAGIC_HSA2 0x67756d73llu
26 #define FR_SALT_LEN 32llu
27
28 #define FR_Z_SZ_HKDF_V1 32
29 #define FR_Z_SZ_V1 16
30 #define FR_Z_FROM_REQUESTOR "requestor2acceptor"
31 #define FR_Z_FROM_ACCEPTOR "acceptor2requestor"
32
33 #define FR_TAG_SIZE_V1 CCAES_KEY_SIZE_128
34 #define FR_SIDECAR_SIZE_V1 (sizeof(uint64_t) + FR_TAG_SIZE_V1)
35
36 // The initialization vector has three parts.
37 // |<-------- DSID -------->|<- X ->|<------ counter ------>|
38 // 64 bits 8 bits 56 bits
39 //
40 // The DSID is known to each end and supplied to each session object at create-
41 // time. X is either 0x0a or 0x0b, depending on whether the message came from an
42 // acceptor or requestor session, respectively. These values are static and
43 // known to each end. The counter starts at zero on each end and is incremented
44 // for each packet generated. It is sent as a sidecar along with the encrypted
45 // data blob, and it is then used to construct the IV for decryption along with
46 // the other two (known) components. Its value can not exceed 2^56 - 1.
47 #define FR_IV_SIZE_V1 (sizeof(uint64_t) + sizeof(uint64_t))
48 #define FR_IV_X_ACCEPT_V1 (0x0a)
49 #define FR_IV_X_REQUEST_V1 (0x0b)
50 #define FR_IV_X_SIZE_V1 (1)
51 #define FR_IV_CNT_MAX_V1 ((0x100000000000000llu) - 1)
52 #define FR_IV_CNT_SIZE_V1 (7)
53
54 #define FR_MAX_ACCEPTOR_TRIES 2
55
56 #define print_paddedline(stream, pad, fmt, ...) do { \
57 size_t i = 0; \
58 for (i = 0; i < pad; i++) { \
59 fprintf((stream), "\t"); \
60 } \
61 \
62 fprintf((stream), fmt "\n", ## __VA_ARGS__); \
63 } while (0);
64
65 #pragma mark Utilities
66 __unused static void
67 _print_blob(FILE *stream, size_t pad, const char *name,
68 uint8_t *buff, size_t sz, size_t len2print)
69 {
70 size_t nb2w = 0;
71 if (len2print && len2print < sz) {
72 nb2w = len2print;
73 } else {
74 nb2w = sz;
75 }
76
77 if (nb2w == 0) {
78 print_paddedline(stream, pad, "%s = (null)\n", name);
79 } else {
80 size_t i = 0; \
81 for (i = 0; i < pad; i++) {
82 fprintf(stream, "\t");
83 }
84
85 fprintf(stream, "%s = 0x", name);
86
87 uint8_t *buffp = buff;
88 for (i = 0; i < nb2w; i++) {
89 fprintf(stream, "%2.2x", buffp[i]);
90 }
91
92 if (len2print && sz > len2print) {
93 fprintf(stream, "...");
94 }
95
96 fprintf(stream, "\n");
97 }
98 }
99
100 #pragma mark CoreCrypto Helpers
101 static uint8_t *
102 _ccder_shim_encode_octet_string(size_t len, const uint8_t *start,
103 const uint8_t *der, uint8_t *der_end)
104 {
105 der_end = ccder_encode_body(len, start, der, der_end);
106 der_end = ccder_encode_tl(CCDER_OCTET_STRING, len, der, der_end);
107 require_action_quiet(der_end, xit, {
108 os_hardware_trap();
109 });
110
111 xit:
112 return der_end;
113 }
114
115 static uint8_t *
116 _ccder_shim_decode_octect_string(size_t *len, const uint8_t **start,
117 const uint8_t *der, const uint8_t *der_end)
118 {
119 der = ccder_decode_tl(CCDER_OCTET_STRING, len, der, der_end);
120 if (der && start) {
121 *start = der;
122 der += *len;
123 }
124
125 return (uint8_t *)der;
126 }
127
128 static ccsrp_ctx *
129 _ccsrp_shim_alloc(const struct ccdigest_info *di, ccdh_const_gp_t gp)
130 {
131 ccsrp_ctx *srp = NULL;
132 int error = -1;
133
134 // CoreCrypto wants these to be 8-byte aligned. malloc(3) and friends return
135 // memory that is suitable for use as AltiVec/SSE data types, so they are
136 // good for this interface.
137 srp = malloc(ccsrp_sizeof_srp(di, gp));
138 require_action_quiet(srp, xit, {
139 error = errno;
140 });
141
142 if (!((uintptr_t)srp & 7) == 0) {
143 os_hardware_trap();
144 }
145
146 ccsrp_ctx_init(srp, di, gp);
147 error = 0;
148
149 xit:
150 if (error) {
151 free(srp);
152 srp = NULL;
153 }
154
155 return srp;
156 }
157
158 static void
159 _derive_sending_key(ccsrp_ctx *srp, const char *info, uint8_t *Z, size_t Z_len)
160 {
161 const struct ccdigest_info *di = ccsha256_di();
162 const uint8_t *K = NULL;
163 size_t K_len = 0;
164 uint8_t Z2[FR_Z_SZ_HKDF_V1];
165 int error = -1;
166
167 if (Z_len < FR_Z_SZ_V1) {
168 os_hardware_trap();
169 }
170
171 K = ccsrp_get_session_key(srp, &K_len);
172
173 error = cchkdf(di, K_len, K, 0, NULL, strlen(info), info, sizeof(Z2), Z2);
174 os_assert_zero(error);
175
176 // Only use first 16 bytes for AEAD.
177 memcpy(Z, Z2, FR_Z_SZ_V1);
178 }
179
180 static void
181 _construct_iv_v1(const uint8_t iv[FR_IV_SIZE_V1], uint64_t dsid,
182 uint8_t x, uint64_t cnt)
183 {
184 uint8_t *cur_iv = (uint8_t *)iv;
185
186 if (!(x == FR_IV_X_ACCEPT_V1 || x == FR_IV_X_REQUEST_V1)) {
187 os_hardware_trap();
188 }
189
190 dsid = OSSwapHostToBigInt64(dsid);
191 memcpy(cur_iv, &dsid, sizeof(dsid));
192 cur_iv += sizeof(dsid);
193
194 // No need to swap; it's just one byte.
195 memcpy(cur_iv, &x, sizeof(x));
196 cur_iv += sizeof(x);
197
198 if (cnt > FR_IV_CNT_MAX_V1) {
199 os_hardware_trap();
200 }
201
202 cnt = OSSwapHostToBigInt64(cnt);
203 memcpy(cur_iv, &cnt, FR_IV_CNT_SIZE_V1);
204 }
205
206 static uint8_t *
207 _encrypt_data_v1(const uint8_t *unenc, size_t unenc_len,
208 uint64_t dsid, uint8_t x, uint64_t cnt,
209 uint8_t *key, size_t key_len, size_t *enc_len)
210 {
211 uint8_t *enc = NULL;
212 int error = -1;
213
214 uint8_t *enc_cur = NULL;
215 size_t enc_len2 = 0;
216 const struct ccmode_gcm *mode = ccaes_gcm_encrypt_mode();
217 ccgcm_ctx_decl(mode->size, gcm);
218 uint8_t iv[FR_IV_SIZE_V1];
219
220 enc_len2 += FR_SIDECAR_SIZE_V1;
221 enc_len2 += unenc_len;
222
223 enc = malloc(enc_len2);
224 require_action_quiet(enc, xit, {
225 error = errno;
226 });
227
228 enc_cur = enc;
229
230 ccgcm_init(mode, gcm, key_len, key);
231 _construct_iv_v1(iv, dsid, x, cnt);
232 ccgcm_set_iv(mode, gcm, FR_IV_SIZE_V1, iv);
233 ccgcm_gmac(mode, gcm, 0, NULL);
234
235 if (cnt > FR_IV_CNT_MAX_V1) {
236 os_hardware_trap();
237 }
238
239 cnt = OSSwapHostToBigInt64(cnt);
240 memcpy(enc_cur, &cnt, sizeof(cnt));
241 enc_cur += sizeof(cnt);
242
243 ccgcm_update(mode, gcm, unenc_len, unenc, enc_cur);
244 enc_cur += unenc_len;
245
246 ccgcm_finalize(mode, gcm, FR_TAG_SIZE_V1, enc_cur);
247 error = 0;
248
249 xit:
250 ccgcm_ctx_clear(ccgcm_context_size(mode), gcm);
251
252 if (error) {
253 free(enc);
254 enc = NULL;
255 } else {
256 *enc_len = enc_len2;
257 }
258
259 return enc;
260 }
261
262 static uint8_t *
263 _decrypt_data_v1(const uint8_t *enc, size_t enc_len,
264 uint64_t dsid, uint8_t x, uint8_t *key, size_t key_len, size_t *dec_len)
265 {
266 uint8_t *dec = NULL;
267 int error = -1;
268 int ret = -1;
269
270 size_t dec_len2 = 0;
271 const struct ccmode_gcm *mode = ccaes_gcm_decrypt_mode();
272 ccgcm_ctx_decl(mode->size, gcm);
273 const uint8_t *enc_cur = NULL;
274 uint64_t cnt = 0;
275 uint8_t iv[FR_IV_SIZE_V1];
276 uint8_t tag[FR_TAG_SIZE_V1];
277
278 enc_cur = enc;
279
280 // At minimum, the encrypted data must contain the tag and counter.
281 require_action_quiet(enc_len >= FR_SIDECAR_SIZE_V1, xit, {
282 error = EINVAL;
283 });
284 dec_len2 = enc_len - FR_SIDECAR_SIZE_V1;
285
286 dec = malloc(dec_len2);
287 require_action_quiet(dec, xit, {
288 error = errno;
289 });
290
291 memcpy(&cnt, enc_cur, sizeof(cnt));
292 cnt = OSSwapBigToHostConstInt64(cnt);
293 require_action_quiet(cnt <= FR_IV_CNT_MAX_V1, xit, {
294 error = ERANGE;
295 });
296 enc_cur += sizeof(cnt);
297
298 ccgcm_init(mode, gcm, key_len, key);
299
300 _construct_iv_v1(iv, dsid, x, cnt);
301 ccgcm_set_iv(mode, gcm, FR_IV_SIZE_V1, iv);
302 ccgcm_gmac(mode, gcm, 0, NULL);
303
304 ccgcm_update(mode, gcm, dec_len2, enc_cur, dec);
305 enc_cur += dec_len2;
306
307 ccgcm_finalize(mode, gcm, FR_TAG_SIZE_V1, tag);
308
309 ret = cc_cmp_safe(FR_TAG_SIZE_V1, enc_cur, tag);
310 require_action_quiet(ret == 0, xit, {
311 error = EINVAL;
312 });
313
314 error = 0;
315
316 xit:
317 ccgcm_ctx_clear(ccgcm_context_size(mode), gcm);
318
319 if (error) {
320 free(dec);
321 dec = NULL;
322 } else {
323 *dec_len = dec_len2;
324 }
325
326 return dec;
327 }
328
329 #pragma mark Protocol Messages
330 static size_t
331 _version_and_magic_size(void)
332 {
333 return ccder_sizeof_uint64(FR_VERSION) +
334 ccder_sizeof_uint64(FR_MAGIC_REQUEST);
335 }
336
337 static uint8_t *
338 _stamp_version_and_magic(uint8_t *der, uint8_t *der_end, uint64_t which)
339 {
340 uint8_t *der_end2 = der_end;
341
342 der_end2 = ccder_encode_uint64(which, der, der_end2);
343 der_end2 = ccder_encode_uint64(FR_VERSION, der, der_end2);
344
345 return der_end2;
346 }
347
348 static uint8_t *
349 _validate_blob(const uint8_t *der, uint8_t *der_end, uint64_t which, int *error)
350 {
351 uint64_t magic = 0;
352 uint64_t version = 0;
353
354 der = ccder_decode_uint64(&version, der, der_end);
355 if (version != FR_VERSION) {
356 *error = EPROTO;
357 return NULL;
358 }
359
360 der = ccder_decode_uint64(&magic, der, der_end);
361 if (magic != which) {
362 *error = EBADRPC;
363 return NULL;
364 }
365
366 return (uint8_t *)der;
367 }
368
369 static uint8_t *
370 _create_request_v1(const uint8_t *A_bytes, size_t A_len,
371 size_t *der_len, int *error)
372 {
373 uint8_t *der = NULL;
374 uint8_t *der_end = NULL;
375 int error2 = -1;
376 size_t needed = 0;
377
378 needed += _version_and_magic_size();
379 needed += ccder_sizeof(CCDER_OCTET_STRING, A_len);
380
381 der = malloc(needed);
382 require_action_quiet(der, xit, {
383 error2 = errno;
384 });
385
386 der_end = der + needed;
387
388 // DER encoding happens back-to-front, so stash the end value and pass to
389 // subsequent invocations of the API. In practical terms, if the buffer
390 // length is large enough, these encoding calls should not fail, so don't
391 // bother to check the return value since we've gone through the trouble of
392 // sizing the buffer above.
393 der_end = _ccder_shim_encode_octet_string(A_len, A_bytes, der, der_end);
394 der_end = _stamp_version_and_magic(der, der_end, FR_MAGIC_REQUEST);
395 require_action_quiet(der_end, xit, {
396 os_hardware_trap();
397 });
398
399 *der_len = needed;
400 error2 = 0;
401
402 xit:
403 if (error2) {
404 free(der);
405 der = NULL;
406 }
407
408 return der;
409 }
410
411 static bool
412 _decode_request_v1(ccsrp_ctx *ctx, uint8_t **A_bytes, size_t *A_len,
413 uint8_t *der, size_t der_len, int *error)
414 {
415 bool result = false;
416 int error2 = -1;
417 uint8_t *A_bytes2 = NULL;
418 size_t A_len2 = 0;
419 uint8_t *der_end = der + der_len;
420
421 der = _validate_blob(der, der_end, FR_MAGIC_REQUEST, &error2);
422 require_quiet(der, xit);
423
424 der = _ccder_shim_decode_octect_string(&A_len2,
425 (const uint8_t **)&A_bytes2, der, der_end);
426 require_action_quiet(der, xit, {
427 error2 = EINVAL;
428 });
429
430 require_action_quiet(A_len2 == ccsrp_ctx_sizeof_n(ctx), xit, {
431 error2 = ERANGE;
432 });
433
434 result = true;
435
436 xit:
437 if (result) {
438 *A_bytes = A_bytes2;
439 *A_len = A_len2;
440 } else {
441 *error = error2;
442 }
443
444 return result;
445 }
446
447 static uint8_t *
448 _create_challenge_v1(const uint8_t *B_bytes, size_t B_len,
449 const uint8_t *salt, size_t salt_len, size_t *der_len, int *error)
450 {
451 uint8_t *der = NULL;
452 int error2 = -1;
453
454 uint8_t *der_end = NULL;
455
456 size_t needed = 0;
457
458 needed += _version_and_magic_size();
459 needed += ccder_sizeof(CCDER_OCTET_STRING, B_len);
460 needed += ccder_sizeof(CCDER_OCTET_STRING, salt_len);
461
462 der = malloc(needed);
463 require_action_quiet(der, xit, {
464 error2 = errno;
465 });
466
467 der_end = der + needed;
468
469 der_end = _ccder_shim_encode_octet_string(salt_len, salt, der, der_end);
470 der_end = _ccder_shim_encode_octet_string(B_len, B_bytes, der, der_end);
471 der_end = _stamp_version_and_magic(der, der_end, FR_MAGIC_CHALLENGE);
472 require_action_quiet(der_end, xit, {
473 os_hardware_trap();
474 });
475
476 *der_len = needed;
477 error2 = 0;
478
479 xit:
480 if (error2) {
481 *error = error2;
482
483 free(der);
484 der = NULL;
485 }
486
487 return der;
488 }
489
490 static bool
491 _decode_challenge_v1(ccsrp_ctx *srp, uint8_t **B_bytes, size_t *B_len,
492 uint8_t **salt, size_t *salt_len, uint8_t *der, size_t der_len,
493 int *error)
494 {
495 bool result = false;
496 int error2 = -1;
497
498 uint8_t *B_bytes2 = NULL;
499 size_t B_len2 = 0;
500 uint8_t *salt2 = NULL;
501 size_t salt_len2 = 0;
502 uint8_t *der_end = der + der_len;
503
504 der = _validate_blob(der, der_end, FR_MAGIC_CHALLENGE, &error2);
505 require_quiet(der, xit);
506
507 der = _ccder_shim_decode_octect_string(&B_len2, (const uint8_t **)&B_bytes2,
508 der, der_end);
509 require_action_quiet(B_bytes, xit, {
510 error2 = EINVAL;
511 });
512
513 require_action_quiet(B_len2 == ccsrp_ctx_sizeof_n(srp), xit, {
514 error2 = ERANGE;
515 });
516
517 der = _ccder_shim_decode_octect_string(&salt_len2, (const uint8_t **)&salt2,
518 der, der_end);
519 require_action_quiet(der, xit, {
520 error2 = EINVAL;
521 });
522
523 require_action_quiet(salt_len2 == FR_SALT_LEN, xit, {
524 error2 = ERANGE;
525 });
526
527 result = true;
528
529 xit:
530 if (result) {
531 *B_bytes = B_bytes2;
532 *B_len = B_len2;
533 *salt = salt2;
534 *salt_len = salt_len2;
535 } else {
536 *error = error2;
537 }
538
539 return result;
540 }
541
542 static uint8_t *
543 _create_response_v1(const uint8_t *M1_bytes, size_t M1_len,
544 const uint8_t *I_bytes, size_t I_len, size_t *der_len,
545 int *error)
546 {
547 uint8_t *der = NULL;
548 int error2 = -1;
549
550 uint8_t *der_end = NULL;
551 size_t needed = 0;
552
553 needed += _version_and_magic_size();
554 needed += ccder_sizeof(CCDER_OCTET_STRING, M1_len);
555 needed += ccder_sizeof(CCDER_OCTET_STRING, I_len);
556
557 der = malloc(needed);
558 require_action_quiet(der, xit, {
559 error2 = errno;
560 });
561
562 der_end = der + needed;
563 der_end = _ccder_shim_encode_octet_string(I_len, I_bytes, der, der_end);
564 der_end = _ccder_shim_encode_octet_string(M1_len, M1_bytes, der, der_end);
565 der_end = _stamp_version_and_magic(der, der_end, FR_MAGIC_RESPONSE);
566 require_action_quiet(der_end, xit, {
567 os_hardware_trap();
568 });
569
570 *der_len = needed;
571 error2 = 0;
572
573 xit:
574 if (error2) {
575 *error = error2;
576
577 free(der);
578 der = NULL;
579 }
580
581 return der;
582 }
583
584 static bool
585 _decode_response_v1(ccsrp_ctx *srp, uint8_t **M_bytes, size_t *M_len,
586 uint8_t **I_bytes, size_t *I_len,
587 uint8_t *der, size_t der_len, int *error)
588 {
589 bool result = false;
590 int error2 = -1;
591
592 uint8_t *M_bytes2 = NULL;
593 size_t M_len2 = 0;
594 uint8_t *I_bytes2 = NULL;
595 size_t I_len2 = 0;
596 uint8_t *der_end = der + der_len;
597
598 der = _validate_blob(der, der_end, FR_MAGIC_RESPONSE, &error2);
599 require_quiet(der, xit);
600
601 der = _ccder_shim_decode_octect_string(&M_len2, (const uint8_t **)&M_bytes2,
602 der, der_end);
603 require_action_quiet(der, xit, {
604 error2 = EINVAL;
605 });
606
607 require_action_quiet(M_len2 == ccsrp_session_size(srp), xit, {
608 error2 = ERANGE;
609 });
610
611 der = _ccder_shim_decode_octect_string(&I_len2,
612 (const uint8_t **)&I_bytes2, der, der_end);
613 require_action_quiet(der, xit, {
614 error2 = EINVAL;
615 });
616
617 result = true;
618
619 xit:
620 if (result) {
621 *M_bytes = M_bytes2;
622 *M_len = M_len2;
623
624 *I_bytes = I_bytes2;
625 *I_len = I_len2;
626 } else {
627 *error = error2;
628 }
629
630 return result;
631 }
632
633 static uint8_t *
634 _create_hsa2_v1(uint8_t *hsa2code, size_t hsa2code_len,
635 uint8_t *HAMK_bytes, size_t HAMK_len, size_t *der_len, int *error)
636 {
637 uint8_t *der = NULL;
638 int error2 = -1;
639
640 uint8_t *der_end = NULL;
641 size_t needed = 0;
642
643 needed += _version_and_magic_size();
644 needed += ccder_sizeof(CCDER_OCTET_STRING, hsa2code_len);
645 needed += ccder_sizeof(CCDER_OCTET_STRING, HAMK_len);
646
647 der = malloc(needed);
648 require_action_quiet(der, xit, {
649 error2 = errno;
650 });
651
652 der_end = der + needed;
653 der_end = _ccder_shim_encode_octet_string(HAMK_len, HAMK_bytes,
654 der, der_end);
655 der_end = _ccder_shim_encode_octet_string(hsa2code_len, hsa2code,
656 der, der_end);
657 der_end = _stamp_version_and_magic(der, der_end, FR_MAGIC_HSA2);
658 require_action_quiet(der_end, xit, {
659 os_hardware_trap();
660 });
661
662 *der_len = needed;
663 error2 = 0;
664
665 xit:
666 if (error2) {
667 *error = error2;
668
669 free(der);
670 der = NULL;
671 }
672
673 return der;
674 }
675
676 static bool
677 _decode_hsa2_v1(ccsrp_ctx *srp, uint8_t **hsa2_bytes, size_t *hsa2_len,
678 uint8_t **HAMK_bytes, size_t *HAMK_len, uint8_t *der, size_t der_len,
679 int *error)
680 {
681 bool result = false;
682 int error2 = -1;
683
684 uint8_t *hsa2_bytes2 = NULL;
685 size_t hsa2_len2 = 0;
686 uint8_t *HAMK_bytes2 = NULL;
687 size_t HAMK_len2 = 0;
688 uint8_t *der_end = der + der_len;
689
690 der = _validate_blob(der, der_end, FR_MAGIC_HSA2, &error2);
691 require_quiet(der, xit);
692
693 der = _ccder_shim_decode_octect_string(&hsa2_len2,
694 (const uint8_t **)&hsa2_bytes2, der, der_end);
695 require_action_quiet(der, xit, {
696 error2 = EINVAL;
697 });
698
699 der = _ccder_shim_decode_octect_string(&HAMK_len2,
700 (const uint8_t **)&HAMK_bytes2, der, der_end);
701 require_action_quiet(der, xit, {
702 error2 = EINVAL;
703 });
704
705 require_action_quiet(HAMK_len2 == ccsrp_session_size(srp), xit, {
706 error2 = ERANGE;
707 });
708
709 result = true;
710
711 xit:
712 if (result) {
713 *hsa2_bytes = hsa2_bytes2;
714 *hsa2_len = hsa2_len2;
715
716 *HAMK_bytes = HAMK_bytes2;
717 *HAMK_len = HAMK_len2;
718 } else {
719 *error = error2;
720 }
721
722 return result;
723 }
724
725 #pragma mark Requesting Session
726 struct __OpaqueSOSForerunnerRequestorSession {
727 CFRuntimeBase __cf;
728
729 ccsrp_ctx *rs_srp;
730 uint64_t rs_dsid;
731 uint64_t rs_packet_cnt;
732
733 uint8_t rs_Z_r2a[FR_Z_SZ_V1];
734 uint8_t rs_Z_a2r[FR_Z_SZ_V1];
735
736 CFStringRef rsUsername;
737 };
738
739 static void
740 _SOSForerunnerRequestorSessionClassInit(CFTypeRef session)
741 {
742 SOSForerunnerRequestorSessionRef self = (void *)session;
743 size_t howmuch2zero = sizeof(*self) - sizeof(self->__cf);
744 uint8_t *start = (uint8_t *)self + sizeof(self->__cf);
745
746 bzero(start, howmuch2zero);
747 }
748
749 static void
750 _SOSForerunnerRequestorSessionClassFinalize(CFTypeRef session)
751 {
752 SOSForerunnerRequestorSessionRef self = (void *)session;
753
754 free(self->rs_srp);
755 CFReleaseNull(self->rsUsername);
756 }
757
758 static CFRuntimeClass _SOSForerunnerRequestorSessionClass = {
759 .version = 0,
760 .className = "forerunner requestor session",
761 .init = _SOSForerunnerRequestorSessionClassInit,
762 .copy = NULL,
763 .finalize = _SOSForerunnerRequestorSessionClassFinalize,
764 .equal = NULL,
765 .hash = NULL,
766 .copyFormattingDesc = NULL,
767 .copyDebugDesc = NULL,
768 };
769
770 #pragma mark Requestor Class Methods
771 CFTypeID
772 SOSForerunnerRequestorSessionGetTypeID(void)
773 {
774 static dispatch_once_t once = 0;
775 static CFTypeID tid = 0;
776
777 dispatch_once(&once, ^{
778 tid = _CFRuntimeRegisterClass(
779 (const CFRuntimeClass * const)
780 &_SOSForerunnerRequestorSessionClass);
781 if (tid == _kCFRuntimeNotATypeID) {
782 os_hardware_trap();
783 }
784 });
785
786 return tid;
787 }
788
789 #pragma mark Requestor Public Methods
790 SOSForerunnerRequestorSessionRef
791 SOSForerunnerRequestorSessionCreate(CFAllocatorRef allocator,
792 CFStringRef username, uint64_t dsid)
793 {
794 SOSForerunnerRequestorSessionRef self = NULL;
795 int error = -1;
796 const size_t xtra = sizeof(*self) - sizeof(self->__cf);
797 const struct ccdigest_info *di = ccsha256_di();
798 ccdh_const_gp_t gp = ccsrp_gp_rfc5054_3072();
799
800 self = (void *)_CFRuntimeCreateInstance(allocator,
801 SOSForerunnerRequestorSessionGetTypeID(), xtra, NULL);
802 require_action_quiet(self, xit, {
803 error = ENOMEM;
804 });
805
806 self->rsUsername = CFRetain(username);
807 self->rs_srp = _ccsrp_shim_alloc(di, gp);
808 self->rs_dsid = dsid;
809 require_action_quiet(self->rs_srp, xit, {
810 error = ENOMEM;
811 });
812
813 error = 0;
814
815 xit:
816 if (error) {
817 CFReleaseNull(self);
818 self = NULL;
819 }
820
821 return self;
822 }
823
824 CFDataRef
825 SOSFRSCopyRequestPacket(SOSForerunnerRequestorSessionRef self,
826 CFErrorRef *cferror)
827 {
828 CFDataRef request = NULL;
829 int error = -1;
830
831 uint8_t A_bytes[ccsrp_exchange_size(self->rs_srp)];
832 size_t A_len = ccsrp_exchange_size(self->rs_srp);
833 uint8_t *der = NULL;
834 size_t der_len = 0;
835
836 error = ccsrp_client_start_authentication(self->rs_srp,
837 ccDRBGGetRngState(), A_bytes);
838 require_action_quiet(error == 0, xit, {
839 (void)SecCoreCryptoError(error, cferror, CFSTR("failed to start SRP"));
840 });
841
842 der = _create_request_v1(A_bytes, A_len, &der_len, &error);
843 require_action_quiet(der, xit, {
844 // Yes, I know, let's report an allocation error by trying to allocate a
845 // bloated pseudo-exception.
846 (void)SecPOSIXError(error, cferror,
847 CFSTR("failed to allocate response data"));
848 });
849
850 request = CFDataCreateWithBytesNoCopy(NULL, der, der_len,
851 kCFAllocatorMalloc);
852 require_action_quiet(request, xit, {
853 error = ENOMEM;
854 (void)SecPOSIXError(error, cferror,
855 CFSTR("failed to allocate request data"));
856 });
857
858 xit:
859 if (error) {
860 if (request) {
861 CFRelease(request);
862 request = NULL;
863 } else {
864 free(der);
865 }
866 }
867
868 return request;
869 }
870
871 CFDataRef
872 SOSFRSCopyResponsePacket(SOSForerunnerRequestorSessionRef self,
873 CFDataRef challenge, CFStringRef secret, CFDictionaryRef peerInfo,
874 CFErrorRef *cferror)
875 {
876 CFDataRef response = NULL;
877 int error = -1;
878
879 char *username_str = NULL;
880 char *secret_str = NULL;
881
882 // Challenge.
883 bool result = false;
884 uint8_t *der = NULL;
885 uint8_t *salt = NULL;
886 size_t salt_len = 0;
887 uint8_t *B_bytes = NULL;
888 size_t B_len = 0;
889
890 // Response.
891 uint8_t *resp_der = NULL;
892 size_t resp_der_len = 0;
893 uint8_t M1_bytes[ccsrp_session_size(self->rs_srp)];
894 size_t M1_len = ccsrp_session_size(self->rs_srp);
895
896 #if CONFIG_ARM_AUTOACCEPT
897 SOSPeerInfoRef peer = NULL;
898 CFDataRef cfI = NULL;
899 #else // CONFIG_ARM_AUTOACCEPT
900 const uint8_t fakeI[] = {
901 'A',
902 'B',
903 'C',
904 'D',
905 'E',
906 'F',
907 };
908 #endif // CONFIG_ARM_AUTOACCEPT
909
910 const uint8_t *I_bytes = NULL;
911 size_t I_len = 0;
912 uint8_t *I_enc_bytes = NULL;
913 size_t I_enc_len = 0;
914
915 der = (UInt8 *)CFDataGetBytePtr(challenge);
916
917 username_str = CFStringToCString(self->rsUsername);
918 require_quiet(username_str, xit);
919
920 secret_str = CFStringToCString(secret);
921 require_quiet(secret_str, xit);
922
923 result = _decode_challenge_v1(self->rs_srp, &B_bytes, &B_len,
924 &salt, &salt_len, der, CFDataGetLength(challenge), &error);
925 require_action_quiet(result, xit, {
926 (void)SecCoreCryptoError(error, cferror,
927 CFSTR("failed to decode challenge"));
928 });
929
930 // Do not include the null terminator in the length of the secret -- for the
931 // purposes of this challenge, it's just a blob of data.
932 error = ccsrp_client_process_challenge(self->rs_srp, username_str,
933 strlen(secret_str), secret_str, salt_len, salt,
934 B_bytes, M1_bytes);
935 require_action_quiet(error == 0, xit, {
936 (void)SecCoreCryptoError(error, cferror,
937 CFSTR("failed to process challenge"));
938 });
939
940 _derive_sending_key(self->rs_srp, FR_Z_FROM_REQUESTOR,
941 self->rs_Z_r2a, sizeof(self->rs_Z_r2a));
942
943 #if CONFIG_ARM_AUTOACCEPT
944 peer = SOSCCCopyMyPeerInfo(cferror);
945 require_quiet(peer, xit);
946
947 cfI = SOSPeerInfoGetAutoAcceptInfo(peer);
948 require_action_quiet(cfI, xit, {
949 error = ENOENT;
950 (void)SecPOSIXError(error, cferror,
951 CFSTR("failed to obtain auto-accept info"));
952 });
953
954 I_bytes = CFDataGetBytePtr(cfI);
955 I_len = CFDataGetLength(cfI);
956 #else // CONFIG_ARM_AUTOACCEPT
957 I_bytes = fakeI;
958 I_len = sizeof(fakeI);
959 #endif // CONFIG_ARM_AUTOACCEPT
960
961 I_enc_bytes = _encrypt_data_v1(I_bytes, I_len,
962 self->rs_dsid, FR_IV_X_REQUEST_V1, self->rs_packet_cnt,
963 self->rs_Z_r2a, sizeof(self->rs_Z_r2a), &I_enc_len);
964 require_action_quiet(I_enc_bytes, xit, {
965 error = ENOMEM;
966 });
967
968 self->rs_packet_cnt++;
969
970 resp_der = _create_response_v1(M1_bytes, M1_len, I_enc_bytes, I_enc_len,
971 &resp_der_len, &error);
972 require_action_quiet(resp_der, xit, {
973 (void)SecCoreCryptoError(error, cferror,
974 CFSTR("failed to create response"));
975 });
976
977 response = CFDataCreateWithBytesNoCopy(NULL, resp_der, resp_der_len,
978 kCFAllocatorMalloc);
979 require_action_quiet(response, xit, {
980 error = ENOMEM;
981 (void)SecCoreCryptoError(error, cferror,
982 CFSTR("failed to create response"));
983 });
984
985 error = 0;
986
987 xit:
988 free(username_str);
989 free(secret_str);
990
991 if (error) {
992 if (response) {
993 CFRelease(response);
994 response = NULL;
995 } else {
996 free(resp_der);
997 }
998 }
999
1000 return response;
1001 }
1002
1003 CFDataRef
1004 SOSFRSCopyHSA2CodeFromPacket(SOSForerunnerRequestorSessionRef self,
1005 CFDataRef hsa2packet, CFErrorRef *cferror)
1006 {
1007 CFDataRef cfhsa2 = NULL;
1008 int error = -1;
1009
1010 bool result = false;
1011 uint8_t *der = NULL;
1012 size_t der_len = 0;
1013 uint8_t *hsa2_enc_bytes = NULL;
1014 size_t hsa2_enc_len = 0;
1015 uint8_t *hsa2_bytes = NULL;
1016 size_t hsa2_len = 0;
1017 uint8_t *HAMK_bytes = NULL;
1018 size_t HAMK_len = 0;
1019
1020 der = (UInt8 *)CFDataGetBytePtr(hsa2packet);
1021 der_len = CFDataGetLength(hsa2packet);
1022
1023 result = _decode_hsa2_v1(self->rs_srp, &hsa2_enc_bytes, &hsa2_enc_len,
1024 &HAMK_bytes, &HAMK_len, der, der_len, &error);
1025 require_quiet(result, xit);
1026
1027 result = ccsrp_client_verify_session(self->rs_srp, HAMK_bytes);
1028 require_action_quiet(result, xit, {
1029 (void)SecPOSIXError(EBADMSG, cferror,
1030 CFSTR("failed to verify session"));
1031 });
1032
1033 _derive_sending_key(self->rs_srp, FR_Z_FROM_ACCEPTOR,
1034 self->rs_Z_a2r, sizeof(self->rs_Z_a2r));
1035
1036 hsa2_bytes = _decrypt_data_v1(hsa2_enc_bytes, hsa2_enc_len,
1037 self->rs_dsid, FR_IV_X_ACCEPT_V1,
1038 self->rs_Z_a2r, sizeof(self->rs_Z_a2r), &hsa2_len);
1039 require_action_quiet(hsa2_bytes, xit, {
1040 error = EINVAL;
1041 });
1042
1043 cfhsa2 = CFDataCreateWithBytesNoCopy(NULL, hsa2_bytes, hsa2_len,
1044 kCFAllocatorMalloc);
1045 require_action_quiet(cfhsa2, xit, {
1046 error = ENOMEM;
1047 });
1048
1049 error = 0;
1050
1051 xit:
1052 if (error) {
1053 if (cfhsa2) {
1054 CFRelease(cfhsa2);
1055 cfhsa2 = NULL;
1056 } else {
1057 free(hsa2_bytes);
1058 }
1059 }
1060
1061 return cfhsa2;
1062 }
1063
1064 CFDataRef
1065 SOSFRSCopyDecryptedData(SOSForerunnerRequestorSessionRef self,
1066 CFDataRef encrypted)
1067 {
1068 CFDataRef decrypted = NULL;
1069 int error = -1;
1070
1071 const uint8_t *enc = CFDataGetBytePtr(encrypted);
1072 size_t enc_len = CFDataGetLength(encrypted);
1073 uint8_t *dec = NULL;
1074 size_t dec_len = 0;
1075
1076 dec = _decrypt_data_v1(enc, enc_len,
1077 self->rs_dsid, FR_IV_X_ACCEPT_V1,
1078 self->rs_Z_a2r, sizeof(self->rs_Z_a2r), &dec_len);
1079 require_action_quiet(dec, xit, {
1080 error = EINVAL;
1081 });
1082
1083 decrypted = CFDataCreateWithBytesNoCopy(NULL, dec, dec_len,
1084 kCFAllocatorMalloc);
1085 require_action_quiet(decrypted, xit, {
1086 error = ENOMEM;
1087 });
1088
1089 error = 0;
1090
1091 xit:
1092 if (error) {
1093 if (decrypted) {
1094 CFRelease(decrypted);
1095 decrypted = NULL;
1096 } else {
1097 free(dec);
1098 }
1099 }
1100
1101 return decrypted;
1102 }
1103
1104 #pragma mark Acceptor Session
1105 struct __OpaqueSOSForerunnerAcceptorSession {
1106 CFRuntimeBase __cf;
1107
1108 ccsrp_ctx *as_srp;
1109 uint64_t as_dsid;
1110 uint64_t as_accept_cnt;
1111 uint64_t as_packet_cnt;
1112
1113 uint8_t as_Z_a2r[FR_Z_SZ_V1];
1114 uint8_t as_Z_r2a[FR_Z_SZ_V1];
1115
1116 CFStringRef asUsername;
1117 CFDataRef asCircleSecret;
1118 };
1119
1120 static void
1121 _SOSForerunnerAcceptorSessionClassInit(CFTypeRef session)
1122 {
1123 SOSForerunnerAcceptorSessionRef self = (void *)session;
1124 size_t howmuch2zero = sizeof(*self) - sizeof(self->__cf);
1125 uint8_t *start = (uint8_t *)self + sizeof(self->__cf);
1126
1127 bzero(start, howmuch2zero);
1128 }
1129
1130 static void
1131 _SOSForerunnerAcceptorSessionClassFinalize(CFTypeRef session)
1132 {
1133 SOSForerunnerAcceptorSessionRef self = (void *)session;
1134
1135 free(self->as_srp);
1136 CFRelease(self->asUsername);
1137 CFRelease(self->asCircleSecret);
1138 }
1139
1140 static CFRuntimeClass _SOSForerunnerAcceptorSessionClass = {
1141 .version = 0,
1142 .className = "forerunner acceptor session",
1143 .init = _SOSForerunnerAcceptorSessionClassInit,
1144 .copy = NULL,
1145 .finalize = _SOSForerunnerAcceptorSessionClassFinalize,
1146 .equal = NULL,
1147 .hash = NULL,
1148 .copyFormattingDesc = NULL,
1149 .copyDebugDesc = NULL,
1150 };
1151
1152 #pragma mark Acceptor Class Methods
1153 CFTypeID
1154 SOSForerunnerAcceptorSessionGetTypeID(void)
1155 {
1156 static dispatch_once_t once = 0;
1157 static CFTypeID tid = 0;
1158
1159 dispatch_once(&once, ^{
1160 tid = _CFRuntimeRegisterClass(
1161 (const CFRuntimeClass * const)
1162 &_SOSForerunnerAcceptorSessionClass);
1163 if (tid == _kCFRuntimeNotATypeID) {
1164 os_hardware_trap();
1165 }
1166 });
1167
1168 return tid;
1169 }
1170
1171 #pragma mark Acceptor Public Methods
1172 SOSForerunnerAcceptorSessionRef
1173 SOSForerunnerAcceptorSessionCreate(CFAllocatorRef allocator,
1174 CFStringRef username, uint64_t dsid, CFStringRef circleSecret)
1175 {
1176 SOSForerunnerAcceptorSessionRef self = NULL;
1177 int error = -1;
1178
1179 size_t xtra = sizeof(*self) - sizeof(self->__cf);
1180 char *secret = NULL;
1181 const struct ccdigest_info *di = ccsha256_di();
1182 ccdh_const_gp_t gp = ccsrp_gp_rfc5054_3072();
1183
1184 self = (void *)_CFRuntimeCreateInstance(allocator,
1185 SOSForerunnerAcceptorSessionGetTypeID(), xtra, NULL);
1186 require_action_quiet(self, xit, {
1187 error = ENOMEM;
1188 });
1189
1190 self->as_srp = _ccsrp_shim_alloc(di, gp);
1191 require_action_quiet(self, xit, {
1192 error = ENOMEM;
1193 });
1194
1195 self->as_dsid = dsid;
1196
1197 secret = CFStringToCString(circleSecret);
1198 require_action_quiet(secret, xit, {
1199 error = ENOMEM;
1200 });
1201
1202 // We don't care about the null terminating byte.
1203 self->asCircleSecret = CFDataCreateWithBytesNoCopy(NULL,
1204 (const UInt8 *)secret, strlen(secret), kCFAllocatorMalloc);
1205 require_action_quiet(self->asCircleSecret, xit, {
1206 error = ENOMEM;
1207 });
1208
1209 self->asUsername = CFRetain(username);
1210 error = 0;
1211
1212 xit:
1213 if (error) {
1214 if (!self->asCircleSecret) {
1215 free(secret);
1216 }
1217
1218 CFReleaseNull(self);
1219 self = NULL;
1220 }
1221
1222 return self;
1223 }
1224
1225 CFDataRef
1226 SOSFASCopyChallengePacket(SOSForerunnerAcceptorSessionRef self,
1227 CFDataRef requestorPacket, CFErrorRef *cferror)
1228 {
1229 CFDataRef challenge = NULL;
1230 int error = -1;
1231 int ret = -1;
1232
1233 bool decoded = false;
1234 char *username_str = NULL;
1235 uint8_t verifier[ccsrp_ctx_sizeof_n(self->as_srp)];
1236 uint8_t salt[FR_SALT_LEN];
1237
1238 uint8_t *der = NULL;
1239 uint8_t *challenge_der = NULL;
1240 size_t challenge_len = 0;
1241
1242 uint8_t *A_bytes = NULL;
1243 size_t A_len = 0;
1244 uint8_t B_bytes[ccsrp_exchange_size(self->as_srp)];
1245 size_t B_len = ccsrp_exchange_size(self->as_srp);
1246
1247 der = (uint8_t *)CFDataGetBytePtr(requestorPacket);
1248 decoded = _decode_request_v1(self->as_srp, &A_bytes, &A_len,
1249 der, CFDataGetLength(requestorPacket), &error);
1250 require_action_quiet(decoded, xit, {
1251 (void)SecCoreCryptoError(error, cferror, CFSTR("bad request packet"));
1252 });
1253
1254 username_str = CFStringToCString(self->asUsername);
1255 ret = SecRandomCopyBytes(NULL, sizeof(salt), salt);
1256 require_action_quiet(ret == 0, xit, {
1257 error = errno;
1258 (void)SecPOSIXError(error, cferror, CFSTR("failed to generate salt"));
1259 });
1260
1261 error = ccsrp_generate_verifier(self->as_srp, username_str,
1262 CFDataGetLength(self->asCircleSecret),
1263 CFDataGetBytePtr(self->asCircleSecret), sizeof(salt), salt,
1264 verifier);
1265 require_action_quiet(error == 0, xit, {
1266 (void)SecCoreCryptoError(error, cferror,
1267 CFSTR("failed to generate SRP verifier"));
1268 });
1269
1270 error = ccsrp_server_start_authentication(self->as_srp, ccDRBGGetRngState(),
1271 username_str, sizeof(salt), salt, verifier, A_bytes, B_bytes);
1272 require_action_quiet(error == 0, xit, {
1273 (void)SecCoreCryptoError(error, cferror,
1274 CFSTR("could not start server SRP"));
1275 });
1276
1277 challenge_der = _create_challenge_v1(B_bytes, B_len,
1278 salt, sizeof(salt), &challenge_len, &error);
1279 require_action_quiet(challenge_der, xit, {
1280 (void)SecPOSIXError(error, cferror,
1281 CFSTR("could not construct challenge"));
1282 });
1283
1284 challenge = CFDataCreateWithBytesNoCopy(NULL, challenge_der, challenge_len,
1285 kCFAllocatorMalloc);
1286 error = 0;
1287
1288 xit:
1289 if (error) {
1290 if (challenge) {
1291 CFRelease(challenge);
1292 challenge = NULL;
1293 } else {
1294 free(challenge_der);
1295 }
1296 }
1297
1298 return challenge;
1299 }
1300
1301 CFDataRef
1302 SOSFASCopyHSA2Packet(SOSForerunnerAcceptorSessionRef self,
1303 CFDataRef responsePacket, CFDataRef hsa2code, CFErrorRef *cferror)
1304 {
1305 CFDataRef hsa2 = NULL;
1306 int error = -1;
1307
1308 // Response.
1309 const uint8_t *der = CFDataGetBytePtr(responsePacket);
1310 size_t der_len = CFDataGetLength(responsePacket);
1311 uint8_t *M_bytes = NULL;
1312 size_t M_len = 0;
1313 uint8_t *I_enc_bytes = NULL;
1314 size_t I_enc_len = 0;
1315 uint8_t *I_bytes = NULL;
1316 size_t I_len = 0;
1317 uint8_t HAMK_bytes[ccsrp_session_size(self->as_srp)];
1318
1319 // HSA2 packet.
1320 uint8_t *hsa2_bytes = NULL;
1321 size_t hsa2_len = 0;
1322 uint8_t *hsa2_enc_bytes = NULL;
1323 size_t hsa2_enc_len = 0;
1324 uint8_t *hsa2_packet_bytes = NULL;
1325 size_t hsa2_packet_len = 0;
1326
1327 bool result = false;
1328 #if CONFIG_ARM_AUTOACCEPT
1329 CFDataRef cfI = NULL;
1330 #endif // CONFIG_ARM_AUTOACCEPT
1331
1332 result = _decode_response_v1(self->as_srp, &M_bytes, &M_len,
1333 &I_enc_bytes, &I_enc_len, (uint8_t *)der, der_len, &error);
1334 require_action_quiet(result, xit, {
1335 (void)SecPOSIXError(error, cferror, CFSTR("bad response"));
1336 });
1337
1338 result = ccsrp_server_verify_session(self->as_srp, M_bytes, HAMK_bytes);
1339 require_action_quiet(result, xit, {
1340 if (self->as_accept_cnt > FR_MAX_ACCEPTOR_TRIES) {
1341 error = EBADMSG;
1342 } else {
1343 error = EAGAIN;
1344 self->as_accept_cnt++;
1345 }
1346
1347 (void)SecPOSIXError(error, cferror,
1348 CFSTR("session verification failed"));
1349 });
1350
1351 _derive_sending_key(self->as_srp, FR_Z_FROM_ACCEPTOR,
1352 self->as_Z_a2r, sizeof(self->as_Z_a2r));
1353
1354 hsa2_bytes = (uint8_t *)CFDataGetBytePtr(hsa2code);
1355 hsa2_len = CFDataGetLength(hsa2code);
1356
1357 hsa2_enc_bytes = _encrypt_data_v1(hsa2_bytes, hsa2_len,
1358 self->as_dsid, FR_IV_X_ACCEPT_V1, self->as_packet_cnt,
1359 self->as_Z_a2r, sizeof(self->as_Z_a2r), &hsa2_enc_len);
1360 require_action_quiet(hsa2_enc_bytes, xit, {
1361 error = ENOMEM;
1362 });
1363
1364 self->as_packet_cnt++;
1365
1366 hsa2_packet_bytes = _create_hsa2_v1(hsa2_enc_bytes, hsa2_enc_len,
1367 HAMK_bytes, sizeof(HAMK_bytes), &hsa2_packet_len, &error);
1368 require_quiet(hsa2_packet_bytes, xit);
1369
1370 hsa2 = CFDataCreateWithBytesNoCopy(NULL, hsa2_packet_bytes, hsa2_packet_len,
1371 kCFAllocatorMalloc);
1372 require_action_quiet(hsa2, xit, {
1373 error = ENOMEM;
1374 (void)SecPOSIXError(error, cferror,
1375 CFSTR("could not create hsa2 packet"));
1376 });
1377
1378 _derive_sending_key(self->as_srp, FR_Z_FROM_REQUESTOR,
1379 self->as_Z_r2a, sizeof(self->as_Z_r2a));
1380
1381 I_bytes = _decrypt_data_v1(I_enc_bytes, I_enc_len,
1382 self->as_dsid, FR_IV_X_REQUEST_V1,
1383 self->as_Z_r2a, sizeof(self->as_Z_r2a), &I_len);
1384 require_action_quiet(I_bytes, xit, {
1385 error = EINVAL;
1386 });
1387
1388 #if CONFIG_ARM_AUTOACCEPT
1389 cfI = CFDataCreateWithBytesNoCopy(NULL, I_bytes, I_len, kCFAllocatorMalloc);
1390 require_action_quiet(cfI, xit, {
1391 error = ENOMEM;
1392 (void)SecPOSIXError(error, cferror,
1393 CFSTR("could not create identity data"));
1394 });
1395
1396 result = SOSCCSetAutoAcceptInfo(cfI, cferror);
1397 require_quiet(result, xit);
1398 #endif // CONFIG_ARM_AUTOACCEPT
1399
1400 error = 0;
1401
1402 xit:
1403 if (error) {
1404 if (hsa2) {
1405 CFRelease(hsa2);
1406 hsa2 = NULL;
1407 } else {
1408 free(hsa2_packet_bytes);
1409 }
1410 }
1411
1412 free(hsa2_enc_bytes);
1413
1414 #if CONFIG_ARM_AUTOACCEPT
1415 if (cfI) {
1416 CFRelease(cfI);
1417 } else {
1418 free(I_bytes);
1419 }
1420 #else // CONFIG_ARM_AUTOACCEPT
1421 free(I_bytes);
1422 #endif // CONFIG_ARM_AUTOACCEPT
1423
1424 return hsa2;
1425 }
1426
1427 CFDataRef
1428 SOSFASCopyEncryptedData(SOSForerunnerAcceptorSessionRef self, CFDataRef data)
1429 {
1430 CFDataRef encrypted = NULL;
1431 int error = -1;
1432
1433 uint8_t *enc = NULL;
1434 size_t enc_len = 0;
1435
1436 enc = _encrypt_data_v1(CFDataGetBytePtr(data), CFDataGetLength(data),
1437 self->as_dsid, FR_IV_X_ACCEPT_V1, self->as_packet_cnt,
1438 self->as_Z_a2r, sizeof(self->as_Z_a2r), &enc_len);
1439 require_action_quiet(enc, xit, {
1440 error = EINVAL;
1441 });
1442
1443 encrypted = CFDataCreateWithBytesNoCopy(NULL, enc, enc_len,
1444 kCFAllocatorMalloc);
1445 require_action_quiet(encrypted, xit, {
1446 error = ENOMEM;
1447 });
1448
1449 error = 0;
1450
1451 xit:
1452 if (error) {
1453 if (encrypted) {
1454 CFRelease(encrypted);
1455 encrypted = NULL;
1456 } else {
1457 free(enc);
1458 }
1459 }
1460
1461 return encrypted;
1462 }