1 #include "SOSForerunnerSession.h"
2 #include "SOSAccountDer.c"
3 #include "SOSPlatform.h"
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>
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
28 #define FR_Z_SZ_HKDF_V1 32
30 #define FR_Z_FROM_REQUESTOR "requestor2acceptor"
31 #define FR_Z_FROM_ACCEPTOR "acceptor2requestor"
33 #define FR_TAG_SIZE_V1 CCAES_KEY_SIZE_128
34 #define FR_SIDECAR_SIZE_V1 (sizeof(uint64_t) + FR_TAG_SIZE_V1)
36 // The initialization vector has three parts.
37 // |<-------- DSID -------->|<- X ->|<------ counter ------>|
38 // 64 bits 8 bits 56 bits
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)
54 #define FR_MAX_ACCEPTOR_TRIES 2
56 #define print_paddedline(stream, pad, fmt, ...) do { \
58 for (i = 0; i < pad; i++) { \
59 fprintf((stream), "\t"); \
62 fprintf((stream), fmt "\n", ## __VA_ARGS__); \
65 #pragma mark Utilities
67 _print_blob(FILE *stream
, size_t pad
, const char *name
,
68 uint8_t *buff
, size_t sz
, size_t len2print
)
71 if (len2print
&& len2print
< sz
) {
78 print_paddedline(stream
, pad
, "%s = (null)\n", name
);
81 for (i
= 0; i
< pad
; i
++) {
82 fprintf(stream
, "\t");
85 fprintf(stream
, "%s = 0x", name
);
87 uint8_t *buffp
= buff
;
88 for (i
= 0; i
< nb2w
; i
++) {
89 fprintf(stream
, "%2.2x", buffp
[i
]);
92 if (len2print
&& sz
> len2print
) {
93 fprintf(stream
, "...");
96 fprintf(stream
, "\n");
100 #pragma mark CoreCrypto Helpers
102 _ccder_shim_encode_octet_string(size_t len
, const uint8_t *start
,
103 const uint8_t *der
, uint8_t *der_end
)
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
, {
116 _ccder_shim_decode_octect_string(size_t *len
, const uint8_t **start
,
117 const uint8_t *der
, const uint8_t *der_end
)
119 der
= ccder_decode_tl(CCDER_OCTET_STRING
, len
, der
, der_end
);
125 return (uint8_t *)der
;
129 _ccsrp_shim_alloc(const struct ccdigest_info
*di
, ccdh_const_gp_t gp
)
131 ccsrp_ctx
*srp
= NULL
;
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
, {
142 if (!((uintptr_t)srp
& 7) == 0) {
146 ccsrp_ctx_init(srp
, di
, gp
);
159 _derive_sending_key(ccsrp_ctx
*srp
, const char *info
, uint8_t *Z
, size_t Z_len
)
161 const struct ccdigest_info
*di
= ccsha256_di();
162 const uint8_t *K
= NULL
;
164 uint8_t Z2
[FR_Z_SZ_HKDF_V1
];
167 if (Z_len
< FR_Z_SZ_V1
) {
171 K
= ccsrp_get_session_key(srp
, &K_len
);
173 error
= cchkdf(di
, K_len
, K
, 0, NULL
, strlen(info
), info
, sizeof(Z2
), Z2
);
174 os_assert_zero(error
);
176 // Only use first 16 bytes for AEAD.
177 memcpy(Z
, Z2
, FR_Z_SZ_V1
);
181 _construct_iv_v1(const uint8_t iv
[FR_IV_SIZE_V1
], uint64_t dsid
,
182 uint8_t x
, uint64_t cnt
)
184 uint8_t *cur_iv
= (uint8_t *)iv
;
186 if (!(x
== FR_IV_X_ACCEPT_V1
|| x
== FR_IV_X_REQUEST_V1
)) {
190 dsid
= OSSwapHostToBigInt64(dsid
);
191 memcpy(cur_iv
, &dsid
, sizeof(dsid
));
192 cur_iv
+= sizeof(dsid
);
194 // No need to swap; it's just one byte.
195 memcpy(cur_iv
, &x
, sizeof(x
));
198 if (cnt
> FR_IV_CNT_MAX_V1
) {
202 cnt
= OSSwapHostToBigInt64(cnt
);
203 memcpy(cur_iv
, &cnt
, FR_IV_CNT_SIZE_V1
);
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
)
214 uint8_t *enc_cur
= NULL
;
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
];
220 enc_len2
+= FR_SIDECAR_SIZE_V1
;
221 enc_len2
+= unenc_len
;
223 enc
= malloc(enc_len2
);
224 require_action_quiet(enc
, xit
, {
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
);
235 if (cnt
> FR_IV_CNT_MAX_V1
) {
239 cnt
= OSSwapHostToBigInt64(cnt
);
240 memcpy(enc_cur
, &cnt
, sizeof(cnt
));
241 enc_cur
+= sizeof(cnt
);
243 ccgcm_update(mode
, gcm
, unenc_len
, unenc
, enc_cur
);
244 enc_cur
+= unenc_len
;
246 ccgcm_finalize(mode
, gcm
, FR_TAG_SIZE_V1
, enc_cur
);
250 ccgcm_ctx_clear(ccgcm_context_size(mode
), gcm
);
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
)
271 const struct ccmode_gcm
*mode
= ccaes_gcm_decrypt_mode();
272 ccgcm_ctx_decl(mode
->size
, gcm
);
273 const uint8_t *enc_cur
= NULL
;
275 uint8_t iv
[FR_IV_SIZE_V1
];
276 uint8_t tag
[FR_TAG_SIZE_V1
];
280 // At minimum, the encrypted data must contain the tag and counter.
281 require_action_quiet(enc_len
>= FR_SIDECAR_SIZE_V1
, xit
, {
284 dec_len2
= enc_len
- FR_SIDECAR_SIZE_V1
;
286 dec
= malloc(dec_len2
);
287 require_action_quiet(dec
, xit
, {
291 memcpy(&cnt
, enc_cur
, sizeof(cnt
));
292 cnt
= OSSwapBigToHostConstInt64(cnt
);
293 require_action_quiet(cnt
<= FR_IV_CNT_MAX_V1
, xit
, {
296 enc_cur
+= sizeof(cnt
);
298 ccgcm_init(mode
, gcm
, key_len
, key
);
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
);
304 ccgcm_update(mode
, gcm
, dec_len2
, enc_cur
, dec
);
307 ccgcm_finalize(mode
, gcm
, FR_TAG_SIZE_V1
, tag
);
309 ret
= cc_cmp_safe(FR_TAG_SIZE_V1
, enc_cur
, tag
);
310 require_action_quiet(ret
== 0, xit
, {
317 ccgcm_ctx_clear(ccgcm_context_size(mode
), gcm
);
329 #pragma mark Protocol Messages
331 _version_and_magic_size(void)
333 return ccder_sizeof_uint64(FR_VERSION
) +
334 ccder_sizeof_uint64(FR_MAGIC_REQUEST
);
338 _stamp_version_and_magic(uint8_t *der
, uint8_t *der_end
, uint64_t which
)
340 uint8_t *der_end2
= der_end
;
342 der_end2
= ccder_encode_uint64(which
, der
, der_end2
);
343 der_end2
= ccder_encode_uint64(FR_VERSION
, der
, der_end2
);
349 _validate_blob(const uint8_t *der
, uint8_t *der_end
, uint64_t which
, int *error
)
352 uint64_t version
= 0;
354 der
= ccder_decode_uint64(&version
, der
, der_end
);
355 if (version
!= FR_VERSION
) {
360 der
= ccder_decode_uint64(&magic
, der
, der_end
);
361 if (magic
!= which
) {
366 return (uint8_t *)der
;
370 _create_request_v1(const uint8_t *A_bytes
, size_t A_len
,
371 size_t *der_len
, int *error
)
374 uint8_t *der_end
= NULL
;
378 needed
+= _version_and_magic_size();
379 needed
+= ccder_sizeof(CCDER_OCTET_STRING
, A_len
);
381 der
= malloc(needed
);
382 require_action_quiet(der
, xit
, {
386 der_end
= der
+ needed
;
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
, {
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
)
417 uint8_t *A_bytes2
= NULL
;
419 uint8_t *der_end
= der
+ der_len
;
421 der
= _validate_blob(der
, der_end
, FR_MAGIC_REQUEST
, &error2
);
422 require_quiet(der
, xit
);
424 der
= _ccder_shim_decode_octect_string(&A_len2
,
425 (const uint8_t **)&A_bytes2
, der
, der_end
);
426 require_action_quiet(der
, xit
, {
430 require_action_quiet(A_len2
== ccsrp_ctx_sizeof_n(ctx
), xit
, {
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
)
454 uint8_t *der_end
= NULL
;
458 needed
+= _version_and_magic_size();
459 needed
+= ccder_sizeof(CCDER_OCTET_STRING
, B_len
);
460 needed
+= ccder_sizeof(CCDER_OCTET_STRING
, salt_len
);
462 der
= malloc(needed
);
463 require_action_quiet(der
, xit
, {
467 der_end
= der
+ needed
;
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
, {
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
,
498 uint8_t *B_bytes2
= NULL
;
500 uint8_t *salt2
= NULL
;
501 size_t salt_len2
= 0;
502 uint8_t *der_end
= der
+ der_len
;
504 der
= _validate_blob(der
, der_end
, FR_MAGIC_CHALLENGE
, &error2
);
505 require_quiet(der
, xit
);
507 der
= _ccder_shim_decode_octect_string(&B_len2
, (const uint8_t **)&B_bytes2
,
509 require_action_quiet(B_bytes
, xit
, {
513 require_action_quiet(B_len2
== ccsrp_ctx_sizeof_n(srp
), xit
, {
517 der
= _ccder_shim_decode_octect_string(&salt_len2
, (const uint8_t **)&salt2
,
519 require_action_quiet(der
, xit
, {
523 require_action_quiet(salt_len2
== FR_SALT_LEN
, xit
, {
534 *salt_len
= salt_len2
;
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
,
550 uint8_t *der_end
= NULL
;
553 needed
+= _version_and_magic_size();
554 needed
+= ccder_sizeof(CCDER_OCTET_STRING
, M1_len
);
555 needed
+= ccder_sizeof(CCDER_OCTET_STRING
, I_len
);
557 der
= malloc(needed
);
558 require_action_quiet(der
, xit
, {
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
, {
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
)
592 uint8_t *M_bytes2
= NULL
;
594 uint8_t *I_bytes2
= NULL
;
596 uint8_t *der_end
= der
+ der_len
;
598 der
= _validate_blob(der
, der_end
, FR_MAGIC_RESPONSE
, &error2
);
599 require_quiet(der
, xit
);
601 der
= _ccder_shim_decode_octect_string(&M_len2
, (const uint8_t **)&M_bytes2
,
603 require_action_quiet(der
, xit
, {
607 require_action_quiet(M_len2
== ccsrp_session_size(srp
), xit
, {
611 der
= _ccder_shim_decode_octect_string(&I_len2
,
612 (const uint8_t **)&I_bytes2
, der
, der_end
);
613 require_action_quiet(der
, xit
, {
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
)
640 uint8_t *der_end
= NULL
;
643 needed
+= _version_and_magic_size();
644 needed
+= ccder_sizeof(CCDER_OCTET_STRING
, hsa2code_len
);
645 needed
+= ccder_sizeof(CCDER_OCTET_STRING
, HAMK_len
);
647 der
= malloc(needed
);
648 require_action_quiet(der
, xit
, {
652 der_end
= der
+ needed
;
653 der_end
= _ccder_shim_encode_octet_string(HAMK_len
, HAMK_bytes
,
655 der_end
= _ccder_shim_encode_octet_string(hsa2code_len
, hsa2code
,
657 der_end
= _stamp_version_and_magic(der
, der_end
, FR_MAGIC_HSA2
);
658 require_action_quiet(der_end
, xit
, {
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
,
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
;
690 der
= _validate_blob(der
, der_end
, FR_MAGIC_HSA2
, &error2
);
691 require_quiet(der
, xit
);
693 der
= _ccder_shim_decode_octect_string(&hsa2_len2
,
694 (const uint8_t **)&hsa2_bytes2
, der
, der_end
);
695 require_action_quiet(der
, xit
, {
699 der
= _ccder_shim_decode_octect_string(&HAMK_len2
,
700 (const uint8_t **)&HAMK_bytes2
, der
, der_end
);
701 require_action_quiet(der
, xit
, {
705 require_action_quiet(HAMK_len2
== ccsrp_session_size(srp
), xit
, {
713 *hsa2_bytes
= hsa2_bytes2
;
714 *hsa2_len
= hsa2_len2
;
716 *HAMK_bytes
= HAMK_bytes2
;
717 *HAMK_len
= HAMK_len2
;
725 #pragma mark Requesting Session
726 struct __OpaqueSOSForerunnerRequestorSession
{
731 uint64_t rs_packet_cnt
;
733 uint8_t rs_Z_r2a
[FR_Z_SZ_V1
];
734 uint8_t rs_Z_a2r
[FR_Z_SZ_V1
];
736 CFStringRef rsUsername
;
740 _SOSForerunnerRequestorSessionClassInit(CFTypeRef session
)
742 SOSForerunnerRequestorSessionRef self
= (void *)session
;
743 size_t howmuch2zero
= sizeof(*self
) - sizeof(self
->__cf
);
744 uint8_t *start
= (uint8_t *)self
+ sizeof(self
->__cf
);
746 bzero(start
, howmuch2zero
);
750 _SOSForerunnerRequestorSessionClassFinalize(CFTypeRef session
)
752 SOSForerunnerRequestorSessionRef self
= (void *)session
;
755 CFReleaseNull(self
->rsUsername
);
758 static CFRuntimeClass _SOSForerunnerRequestorSessionClass
= {
760 .className
= "forerunner requestor session",
761 .init
= _SOSForerunnerRequestorSessionClassInit
,
763 .finalize
= _SOSForerunnerRequestorSessionClassFinalize
,
766 .copyFormattingDesc
= NULL
,
767 .copyDebugDesc
= NULL
,
770 #pragma mark Requestor Class Methods
772 SOSForerunnerRequestorSessionGetTypeID(void)
774 static dispatch_once_t once
= 0;
775 static CFTypeID tid
= 0;
777 dispatch_once(&once
, ^{
778 tid
= _CFRuntimeRegisterClass(
779 (const CFRuntimeClass
* const)
780 &_SOSForerunnerRequestorSessionClass
);
781 if (tid
== _kCFRuntimeNotATypeID
) {
789 #pragma mark Requestor Public Methods
790 SOSForerunnerRequestorSessionRef
791 SOSForerunnerRequestorSessionCreate(CFAllocatorRef allocator
,
792 CFStringRef username
, uint64_t dsid
)
794 SOSForerunnerRequestorSessionRef self
= NULL
;
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();
800 self
= (void *)_CFRuntimeCreateInstance(allocator
,
801 SOSForerunnerRequestorSessionGetTypeID(), xtra
, NULL
);
802 require_action_quiet(self
, xit
, {
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
, {
825 SOSFRSCopyRequestPacket(SOSForerunnerRequestorSessionRef self
,
828 CFDataRef request
= NULL
;
831 uint8_t A_bytes
[ccsrp_exchange_size(self
->rs_srp
)];
832 size_t A_len
= ccsrp_exchange_size(self
->rs_srp
);
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"));
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"));
850 request
= CFDataCreateWithBytesNoCopy(NULL
, der
, der_len
,
852 require_action_quiet(request
, xit
, {
854 (void)SecPOSIXError(error
, cferror
,
855 CFSTR("failed to allocate request data"));
872 SOSFRSCopyResponsePacket(SOSForerunnerRequestorSessionRef self
,
873 CFDataRef challenge
, CFStringRef secret
, CFDictionaryRef peerInfo
,
876 CFDataRef response
= NULL
;
879 char *username_str
= NULL
;
880 char *secret_str
= NULL
;
885 uint8_t *salt
= NULL
;
887 uint8_t *B_bytes
= NULL
;
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
);
896 #if CONFIG_ARM_AUTOACCEPT
897 SOSPeerInfoRef peer
= NULL
;
898 CFDataRef cfI
= NULL
;
899 #else // CONFIG_ARM_AUTOACCEPT
900 const uint8_t fakeI
[] = {
908 #endif // CONFIG_ARM_AUTOACCEPT
910 const uint8_t *I_bytes
= NULL
;
912 uint8_t *I_enc_bytes
= NULL
;
913 size_t I_enc_len
= 0;
915 der
= (UInt8
*)CFDataGetBytePtr(challenge
);
917 username_str
= CFStringToCString(self
->rsUsername
);
918 require_quiet(username_str
, xit
);
920 secret_str
= CFStringToCString(secret
);
921 require_quiet(secret_str
, xit
);
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"));
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
,
935 require_action_quiet(error
== 0, xit
, {
936 (void)SecCoreCryptoError(error
, cferror
,
937 CFSTR("failed to process challenge"));
940 _derive_sending_key(self
->rs_srp
, FR_Z_FROM_REQUESTOR
,
941 self
->rs_Z_r2a
, sizeof(self
->rs_Z_r2a
));
943 #if CONFIG_ARM_AUTOACCEPT
944 peer
= SOSCCCopyMyPeerInfo(cferror
);
945 require_quiet(peer
, xit
);
947 cfI
= SOSPeerInfoGetAutoAcceptInfo(peer
);
948 require_action_quiet(cfI
, xit
, {
950 (void)SecPOSIXError(error
, cferror
,
951 CFSTR("failed to obtain auto-accept info"));
954 I_bytes
= CFDataGetBytePtr(cfI
);
955 I_len
= CFDataGetLength(cfI
);
956 #else // CONFIG_ARM_AUTOACCEPT
958 I_len
= sizeof(fakeI
);
959 #endif // CONFIG_ARM_AUTOACCEPT
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
, {
968 self
->rs_packet_cnt
++;
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"));
977 response
= CFDataCreateWithBytesNoCopy(NULL
, resp_der
, resp_der_len
,
979 require_action_quiet(response
, xit
, {
981 (void)SecCoreCryptoError(error
, cferror
,
982 CFSTR("failed to create response"));
1004 SOSFRSCopyHSA2CodeFromPacket(SOSForerunnerRequestorSessionRef self
,
1005 CFDataRef hsa2packet
, CFErrorRef
*cferror
)
1007 CFDataRef cfhsa2
= NULL
;
1010 bool result
= false;
1011 uint8_t *der
= NULL
;
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;
1020 der
= (UInt8
*)CFDataGetBytePtr(hsa2packet
);
1021 der_len
= CFDataGetLength(hsa2packet
);
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
);
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"));
1033 _derive_sending_key(self
->rs_srp
, FR_Z_FROM_ACCEPTOR
,
1034 self
->rs_Z_a2r
, sizeof(self
->rs_Z_a2r
));
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
, {
1043 cfhsa2
= CFDataCreateWithBytesNoCopy(NULL
, hsa2_bytes
, hsa2_len
,
1044 kCFAllocatorMalloc
);
1045 require_action_quiet(cfhsa2
, xit
, {
1065 SOSFRSCopyDecryptedData(SOSForerunnerRequestorSessionRef self
,
1066 CFDataRef encrypted
)
1068 CFDataRef decrypted
= NULL
;
1071 const uint8_t *enc
= CFDataGetBytePtr(encrypted
);
1072 size_t enc_len
= CFDataGetLength(encrypted
);
1073 uint8_t *dec
= NULL
;
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
, {
1083 decrypted
= CFDataCreateWithBytesNoCopy(NULL
, dec
, dec_len
,
1084 kCFAllocatorMalloc
);
1085 require_action_quiet(decrypted
, xit
, {
1094 CFRelease(decrypted
);
1104 #pragma mark Acceptor Session
1105 struct __OpaqueSOSForerunnerAcceptorSession
{
1110 uint64_t as_accept_cnt
;
1111 uint64_t as_packet_cnt
;
1113 uint8_t as_Z_a2r
[FR_Z_SZ_V1
];
1114 uint8_t as_Z_r2a
[FR_Z_SZ_V1
];
1116 CFStringRef asUsername
;
1117 CFDataRef asCircleSecret
;
1121 _SOSForerunnerAcceptorSessionClassInit(CFTypeRef session
)
1123 SOSForerunnerAcceptorSessionRef self
= (void *)session
;
1124 size_t howmuch2zero
= sizeof(*self
) - sizeof(self
->__cf
);
1125 uint8_t *start
= (uint8_t *)self
+ sizeof(self
->__cf
);
1127 bzero(start
, howmuch2zero
);
1131 _SOSForerunnerAcceptorSessionClassFinalize(CFTypeRef session
)
1133 SOSForerunnerAcceptorSessionRef self
= (void *)session
;
1136 CFRelease(self
->asUsername
);
1137 CFRelease(self
->asCircleSecret
);
1140 static CFRuntimeClass _SOSForerunnerAcceptorSessionClass
= {
1142 .className
= "forerunner acceptor session",
1143 .init
= _SOSForerunnerAcceptorSessionClassInit
,
1145 .finalize
= _SOSForerunnerAcceptorSessionClassFinalize
,
1148 .copyFormattingDesc
= NULL
,
1149 .copyDebugDesc
= NULL
,
1152 #pragma mark Acceptor Class Methods
1154 SOSForerunnerAcceptorSessionGetTypeID(void)
1156 static dispatch_once_t once
= 0;
1157 static CFTypeID tid
= 0;
1159 dispatch_once(&once
, ^{
1160 tid
= _CFRuntimeRegisterClass(
1161 (const CFRuntimeClass
* const)
1162 &_SOSForerunnerAcceptorSessionClass
);
1163 if (tid
== _kCFRuntimeNotATypeID
) {
1171 #pragma mark Acceptor Public Methods
1172 SOSForerunnerAcceptorSessionRef
1173 SOSForerunnerAcceptorSessionCreate(CFAllocatorRef allocator
,
1174 CFStringRef username
, uint64_t dsid
, CFStringRef circleSecret
)
1176 SOSForerunnerAcceptorSessionRef self
= NULL
;
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();
1184 self
= (void *)_CFRuntimeCreateInstance(allocator
,
1185 SOSForerunnerAcceptorSessionGetTypeID(), xtra
, NULL
);
1186 require_action_quiet(self
, xit
, {
1190 self
->as_srp
= _ccsrp_shim_alloc(di
, gp
);
1191 require_action_quiet(self
, xit
, {
1195 self
->as_dsid
= dsid
;
1197 secret
= CFStringToCString(circleSecret
);
1198 require_action_quiet(secret
, xit
, {
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
, {
1209 self
->asUsername
= CFRetain(username
);
1214 if (!self
->asCircleSecret
) {
1218 CFReleaseNull(self
);
1226 SOSFASCopyChallengePacket(SOSForerunnerAcceptorSessionRef self
,
1227 CFDataRef requestorPacket
, CFErrorRef
*cferror
)
1229 CFDataRef challenge
= NULL
;
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
];
1238 uint8_t *der
= NULL
;
1239 uint8_t *challenge_der
= NULL
;
1240 size_t challenge_len
= 0;
1242 uint8_t *A_bytes
= NULL
;
1244 uint8_t B_bytes
[ccsrp_exchange_size(self
->as_srp
)];
1245 size_t B_len
= ccsrp_exchange_size(self
->as_srp
);
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"));
1254 username_str
= CFStringToCString(self
->asUsername
);
1255 ret
= SecRandomCopyBytes(NULL
, sizeof(salt
), salt
);
1256 require_action_quiet(ret
== 0, xit
, {
1258 (void)SecPOSIXError(error
, cferror
, CFSTR("failed to generate salt"));
1261 error
= ccsrp_generate_verifier(self
->as_srp
, username_str
,
1262 CFDataGetLength(self
->asCircleSecret
),
1263 CFDataGetBytePtr(self
->asCircleSecret
), sizeof(salt
), salt
,
1265 require_action_quiet(error
== 0, xit
, {
1266 (void)SecCoreCryptoError(error
, cferror
,
1267 CFSTR("failed to generate SRP verifier"));
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"));
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"));
1284 challenge
= CFDataCreateWithBytesNoCopy(NULL
, challenge_der
, challenge_len
,
1285 kCFAllocatorMalloc
);
1291 CFRelease(challenge
);
1294 free(challenge_der
);
1302 SOSFASCopyHSA2Packet(SOSForerunnerAcceptorSessionRef self
,
1303 CFDataRef responsePacket
, CFDataRef hsa2code
, CFErrorRef
*cferror
)
1305 CFDataRef hsa2
= NULL
;
1309 const uint8_t *der
= CFDataGetBytePtr(responsePacket
);
1310 size_t der_len
= CFDataGetLength(responsePacket
);
1311 uint8_t *M_bytes
= NULL
;
1313 uint8_t *I_enc_bytes
= NULL
;
1314 size_t I_enc_len
= 0;
1315 uint8_t *I_bytes
= NULL
;
1317 uint8_t HAMK_bytes
[ccsrp_session_size(self
->as_srp
)];
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;
1327 bool result
= false;
1328 #if CONFIG_ARM_AUTOACCEPT
1329 CFDataRef cfI
= NULL
;
1330 #endif // CONFIG_ARM_AUTOACCEPT
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"));
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
) {
1344 self
->as_accept_cnt
++;
1347 (void)SecPOSIXError(error
, cferror
,
1348 CFSTR("session verification failed"));
1351 _derive_sending_key(self
->as_srp
, FR_Z_FROM_ACCEPTOR
,
1352 self
->as_Z_a2r
, sizeof(self
->as_Z_a2r
));
1354 hsa2_bytes
= (uint8_t *)CFDataGetBytePtr(hsa2code
);
1355 hsa2_len
= CFDataGetLength(hsa2code
);
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
, {
1364 self
->as_packet_cnt
++;
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
);
1370 hsa2
= CFDataCreateWithBytesNoCopy(NULL
, hsa2_packet_bytes
, hsa2_packet_len
,
1371 kCFAllocatorMalloc
);
1372 require_action_quiet(hsa2
, xit
, {
1374 (void)SecPOSIXError(error
, cferror
,
1375 CFSTR("could not create hsa2 packet"));
1378 _derive_sending_key(self
->as_srp
, FR_Z_FROM_REQUESTOR
,
1379 self
->as_Z_r2a
, sizeof(self
->as_Z_r2a
));
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
, {
1388 #if CONFIG_ARM_AUTOACCEPT
1389 cfI
= CFDataCreateWithBytesNoCopy(NULL
, I_bytes
, I_len
, kCFAllocatorMalloc
);
1390 require_action_quiet(cfI
, xit
, {
1392 (void)SecPOSIXError(error
, cferror
,
1393 CFSTR("could not create identity data"));
1396 result
= SOSCCSetAutoAcceptInfo(cfI
, cferror
);
1397 require_quiet(result
, xit
);
1398 #endif // CONFIG_ARM_AUTOACCEPT
1408 free(hsa2_packet_bytes
);
1412 free(hsa2_enc_bytes
);
1414 #if CONFIG_ARM_AUTOACCEPT
1420 #else // CONFIG_ARM_AUTOACCEPT
1422 #endif // CONFIG_ARM_AUTOACCEPT
1428 SOSFASCopyEncryptedData(SOSForerunnerAcceptorSessionRef self
, CFDataRef data
)
1430 CFDataRef encrypted
= NULL
;
1433 uint8_t *enc
= NULL
;
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
, {
1443 encrypted
= CFDataCreateWithBytesNoCopy(NULL
, enc
, enc_len
,
1444 kCFAllocatorMalloc
);
1445 require_action_quiet(encrypted
, xit
, {
1454 CFRelease(encrypted
);