summaryrefslogtreecommitdiffstats
path: root/src/lockdown-cu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lockdown-cu.c')
-rw-r--r--src/lockdown-cu.c1193
1 files changed, 1193 insertions, 0 deletions
diff --git a/src/lockdown-cu.c b/src/lockdown-cu.c
new file mode 100644
index 0000000..1afc2c5
--- /dev/null
+++ b/src/lockdown-cu.c
@@ -0,0 +1,1193 @@
1/*
2 * lockdown-cu.c
3 * com.apple.mobile.lockdownd service CU additions
4 *
5 * Copyright (c) 2021 Nikias Bassen, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
25
26#include <string.h>
27#include <stdlib.h>
28#define _GNU_SOURCE 1
29#define __USE_GNU 1
30#include <stdio.h>
31#include <ctype.h>
32#include <unistd.h>
33#include <plist/plist.h>
34
35#include "idevice.h"
36#include "lockdown.h"
37#include "common/debug.h"
38
39#ifdef HAVE_WIRELESS_PAIRING
40
41#include <libimobiledevice-glue/utils.h>
42#include <libimobiledevice-glue/socket.h>
43#include <libimobiledevice-glue/opack.h>
44#include <libimobiledevice-glue/tlv.h>
45
46#if defined(HAVE_OPENSSL)
47#include <openssl/hmac.h>
48#include <openssl/evp.h>
49#include <openssl/rand.h>
50#if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x2030200fL)
51#include <openssl/chacha.h>
52#include <openssl/poly1305.h>
53#endif
54#elif defined(HAVE_GCRYPT)
55#include <gcrypt.h>
56#elif defined(HAVE_MBEDTLS)
57#include <mbedtls/md.h>
58#include <mbedtls/chachapoly.h>
59#endif
60
61#ifdef __APPLE__
62#include <sys/sysctl.h>
63#include <SystemConfiguration/SystemConfiguration.h>
64#include <CoreFoundation/CoreFoundation.h>
65#include <TargetConditionals.h>
66#endif
67
68#include "property_list_service.h"
69#include "common/userpref.h"
70
71#include "endianness.h"
72
73#include "srp.h"
74#include "ed25519.h"
75
76/* {{{ SRP6a parameters */
77static const unsigned char kSRPModulus3072[384] = {
78 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34,
79 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74,
80 0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
81 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14, 0x37,
82 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45, 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6,
83 0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x37, 0xed, 0x6b, 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed,
84 0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5, 0xae, 0x9f, 0x24, 0x11, 0x7c, 0x4b, 0x1f, 0xe6,
85 0x49, 0x28, 0x66, 0x51, 0xec, 0xe4, 0x5b, 0x3d, 0xc2, 0x00, 0x7c, 0xb8, 0xa1, 0x63, 0xbf, 0x05,
86 0x98, 0xda, 0x48, 0x36, 0x1c, 0x55, 0xd3, 0x9a, 0x69, 0x16, 0x3f, 0xa8, 0xfd, 0x24, 0xcf, 0x5f,
87 0x83, 0x65, 0x5d, 0x23, 0xdc, 0xa3, 0xad, 0x96, 0x1c, 0x62, 0xf3, 0x56, 0x20, 0x85, 0x52, 0xbb,
88 0x9e, 0xd5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6d, 0x67, 0x0c, 0x35, 0x4e, 0x4a, 0xbc, 0x98, 0x04,
89 0xf1, 0x74, 0x6c, 0x08, 0xca, 0x18, 0x21, 0x7c, 0x32, 0x90, 0x5e, 0x46, 0x2e, 0x36, 0xce, 0x3b,
90 0xe3, 0x9e, 0x77, 0x2c, 0x18, 0x0e, 0x86, 0x03, 0x9b, 0x27, 0x83, 0xa2, 0xec, 0x07, 0xa2, 0x8f,
91 0xb5, 0xc5, 0x5d, 0xf0, 0x6f, 0x4c, 0x52, 0xc9, 0xde, 0x2b, 0xcb, 0xf6, 0x95, 0x58, 0x17, 0x18,
92 0x39, 0x95, 0x49, 0x7c, 0xea, 0x95, 0x6a, 0xe5, 0x15, 0xd2, 0x26, 0x18, 0x98, 0xfa, 0x05, 0x10,
93 0x15, 0x72, 0x8e, 0x5a, 0x8a, 0xaa, 0xc4, 0x2d, 0xad, 0x33, 0x17, 0x0d, 0x04, 0x50, 0x7a, 0x33,
94 0xa8, 0x55, 0x21, 0xab, 0xdf, 0x1c, 0xba, 0x64, 0xec, 0xfb, 0x85, 0x04, 0x58, 0xdb, 0xef, 0x0a,
95 0x8a, 0xea, 0x71, 0x57, 0x5d, 0x06, 0x0c, 0x7d, 0xb3, 0x97, 0x0f, 0x85, 0xa6, 0xe1, 0xe4, 0xc7,
96 0xab, 0xf5, 0xae, 0x8c, 0xdb, 0x09, 0x33, 0xd7, 0x1e, 0x8c, 0x94, 0xe0, 0x4a, 0x25, 0x61, 0x9d,
97 0xce, 0xe3, 0xd2, 0x26, 0x1a, 0xd2, 0xee, 0x6b, 0xf1, 0x2f, 0xfa, 0x06, 0xd9, 0x8a, 0x08, 0x64,
98 0xd8, 0x76, 0x02, 0x73, 0x3e, 0xc8, 0x6a, 0x64, 0x52, 0x1f, 0x2b, 0x18, 0x17, 0x7b, 0x20, 0x0c,
99 0xbb, 0xe1, 0x17, 0x57, 0x7a, 0x61, 0x5d, 0x6c, 0x77, 0x09, 0x88, 0xc0, 0xba, 0xd9, 0x46, 0xe2,
100 0x08, 0xe2, 0x4f, 0xa0, 0x74, 0xe5, 0xab, 0x31, 0x43, 0xdb, 0x5b, 0xfc, 0xe0, 0xfd, 0x10, 0x8e,
101 0x4b, 0x82, 0xd1, 0x20, 0xa9, 0x3a, 0xd2, 0xca, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
102};
103
104static const unsigned char kSRPGenerator5 = 5;
105/* }}} */
106
107/* {{{ HKDF */
108#if defined(HAVE_OPENSSL)
109#define MD_ALGO_SHA512 EVP_sha512()
110typedef const EVP_MD* MD_ALGO_TYPE_T;
111#define MD_ALGO_DIGEST_SIZE EVP_MD_size
112#define MD_MAX_DIGEST_SIZE EVP_MAX_MD_SIZE
113
114#elif defined(HAVE_GCRYPT)
115#define MD_ALGO_SHA512 GCRY_MD_SHA512
116typedef int MD_ALGO_TYPE_T;
117#define MD_ALGO_DIGEST_SIZE gcry_md_get_algo_dlen
118#define MD_MAX_DIGEST_SIZE 64
119
120static void HMAC(MD_ALGO_TYPE_T md, unsigned char* key, unsigned int key_len, unsigned char* data, unsigned int data_len, unsigned char* out, unsigned int* out_len)
121{
122 gcry_md_hd_t hd;
123 if (gcry_md_open(&hd, md, GCRY_MD_FLAG_HMAC)) {
124 debug_info("gcry_md_open() failed");
125 return;
126 }
127 if (gcry_md_setkey(hd, key, key_len)) {
128 gcry_md_close (hd);
129 debug_info("gcry_md_setkey() failed");
130 return;
131 }
132 gcry_md_write(hd, data, data_len);
133
134 unsigned char* digest = gcry_md_read(hd, md);
135 if (!digest) {
136 gcry_md_close(hd);
137 debug_info("gcry_md_read() failed");
138 return;
139 }
140
141 *out_len = gcry_md_get_algo_dlen(md);
142 memcpy(out, digest, *out_len);
143 gcry_md_close(hd);
144}
145#elif defined(HAVE_MBEDTLS)
146#define MD_ALGO_SHA512 MBEDTLS_MD_SHA512
147typedef mbedtls_md_type_t MD_ALGO_TYPE_T;
148#define MD_ALGO_DIGEST_SIZE(x) mbedtls_md_get_size(mbedtls_md_info_from_type(x))
149#define MD_MAX_DIGEST_SIZE MBEDTLS_MD_MAX_SIZE
150
151static void HMAC(MD_ALGO_TYPE_T md, unsigned char* key, unsigned int key_len, unsigned char* data, unsigned int data_len, unsigned char* out, unsigned int* out_len)
152{
153 mbedtls_md_context_t mdctx;
154 mbedtls_md_init(&mdctx);
155 int mr = mbedtls_md_setup(&mdctx, mbedtls_md_info_from_type(md), 1);
156 if (mr != 0) {
157 debug_info("mbedtls_md_setup() failed: %d", mr);
158 return;
159 }
160
161 mr = mbedtls_md_hmac_starts(&mdctx, key, key_len);
162 if (mr != 0) {
163 mbedtls_md_free(&mdctx);
164 debug_info("mbedtls_md_hmac_starts() failed: %d", mr);
165 return;
166 }
167
168 mbedtls_md_hmac_update(&mdctx, data, data_len);
169
170 mr = mbedtls_md_hmac_finish(&mdctx, out);
171 if (mr == 0) {
172 *out_len = mbedtls_md_get_size(mbedtls_md_info_from_type(md));
173 } else {
174 debug_info("mbedtls_md_hmac_finish() failed: %d", mr);
175 }
176 mbedtls_md_free(&mdctx);
177}
178#endif
179
180static void hkdf_md_extract(MD_ALGO_TYPE_T md, unsigned char* salt, unsigned int salt_len, unsigned char* input_key_material, unsigned int input_key_material_len, unsigned char* out, unsigned int* out_len)
181{
182 unsigned char empty_salt[MD_MAX_DIGEST_SIZE];
183 if (!md || !out || !out_len || !*out_len) return;
184 if (salt_len == 0) {
185 salt_len = MD_ALGO_DIGEST_SIZE(md);
186 salt = (unsigned char*)empty_salt;
187 }
188 HMAC(md, salt, salt_len, input_key_material, input_key_material_len, out, out_len);
189}
190
191static void hkdf_md_expand(MD_ALGO_TYPE_T md, unsigned char* prk, unsigned int prk_len, unsigned char* info, unsigned int info_len, unsigned char* out, unsigned int* out_len)
192{
193 if (!md || !out || !out_len || !*out_len) return;
194 unsigned int md_size = MD_ALGO_DIGEST_SIZE(md);
195 if (*out_len > 255 * md_size) {
196 *out_len = 0;
197 return;
198 }
199 int blocks_needed = (*out_len) / md_size;
200 if (((*out_len) % md_size) != 0) blocks_needed++;
201 unsigned int okm_len = 0;
202 unsigned char okm_block[MD_MAX_DIGEST_SIZE];
203 unsigned int okm_block_len = 0;
204 int i;
205 for (i = 0; i < blocks_needed; i++) {
206 unsigned int output_block_len = okm_block_len + info_len + 1;
207 unsigned char* output_block = malloc(output_block_len);
208 if (okm_block_len > 0) {
209 memcpy(output_block, okm_block, okm_block_len);
210 }
211 memcpy(output_block + okm_block_len, info, info_len);
212 output_block[okm_block_len + info_len] = (uint8_t)(i+1);
213
214 HMAC(md, prk, prk_len, output_block, output_block_len, okm_block, &okm_block_len);
215 if (okm_len < *out_len) {
216 memcpy(out + okm_len, okm_block, (okm_len + okm_block_len > *out_len) ? *out_len - okm_len : okm_block_len);
217 }
218 okm_len += okm_block_len;
219 free(output_block);
220 }
221}
222
223static void hkdf_md(MD_ALGO_TYPE_T md, unsigned char* salt, unsigned int salt_len, unsigned char* info, unsigned int info_len, unsigned char* initial_key_material, unsigned int initial_key_material_size, unsigned char* out, unsigned int *out_len)
224{
225 if (!md || !initial_key_material || !out || !out_len || !*out_len) return;
226
227 unsigned char prk[MD_MAX_DIGEST_SIZE];
228 unsigned int prk_len = MD_ALGO_DIGEST_SIZE(md);
229
230 hkdf_md_extract(md, salt, salt_len, initial_key_material, initial_key_material_size, prk, &prk_len);
231 if (prk_len > 0) {
232 hkdf_md_expand(md, prk, prk_len, info, info_len, out, out_len);
233 } else {
234 *out_len = 0;
235 }
236}
237/* }}} */
238
239/* {{{ chacha20 poly1305 encryption/decryption */
240#if defined(HAVE_OPENSSL) && defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x2030200fL)
241/* {{{ From: OpenBSD's e_chacha20poly1305.c */
242/*
243 * Copyright (c) 2015 Reyk Floter <reyk@openbsd.org>
244 * Copyright (c) 2014, Google Inc.
245 *
246 * Permission to use, copy, modify, and/or distribute this software for any
247 * purpose with or without fee is hereby granted, provided that the above
248 * copyright notice and this permission notice appear in all copies.
249 *
250 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
251 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
252 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
253 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
254 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
255 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
256 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
257 */
258static void
259poly1305_update_with_length(poly1305_state *poly1305,
260 const unsigned char *data, size_t data_len)
261{
262 size_t j = data_len;
263 unsigned char length_bytes[8];
264 unsigned i;
265
266 for (i = 0; i < sizeof(length_bytes); i++) {
267 length_bytes[i] = j;
268 j >>= 8;
269 }
270
271 if (data != NULL)
272 CRYPTO_poly1305_update(poly1305, data, data_len);
273 CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
274}
275
276static void
277poly1305_update_with_pad16(poly1305_state *poly1305,
278 const unsigned char *data, size_t data_len)
279{
280 static const unsigned char zero_pad16[16];
281 size_t pad_len;
282
283 CRYPTO_poly1305_update(poly1305, data, data_len);
284
285 /* pad16() is defined in RFC 7539 2.8.1. */
286 if ((pad_len = data_len % 16) == 0)
287 return;
288
289 CRYPTO_poly1305_update(poly1305, zero_pad16, 16 - pad_len);
290}
291/* }}} */
292#endif
293
294static void chacha20_poly1305_encrypt_96(unsigned char* key, unsigned char* nonce, unsigned char* ad, size_t ad_len, unsigned char* in, size_t in_len, unsigned char* out, size_t* out_len)
295{
296#if defined(HAVE_OPENSSL)
297#if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x3050000fL)
298#if (LIBRESSL_VERSION_NUMBER >= 0x2040000fL)
299 const EVP_AEAD *aead = EVP_aead_chacha20_poly1305();
300 EVP_AEAD_CTX ctx;
301 EVP_AEAD_CTX_init(&ctx, aead, key, EVP_AEAD_key_length(aead), EVP_AEAD_DEFAULT_TAG_LENGTH, NULL);
302 EVP_AEAD_CTX_seal(&ctx, out, out_len, *out_len, nonce, 12, in, in_len, ad, ad_len);
303#else
304 unsigned char poly1305_key[32];
305 poly1305_state poly1305;
306 uint64_t ctr = (uint64_t)(nonce[0] | nonce[1] << 8 | nonce[2] << 16 | nonce[3] << 24) << 32;
307 const unsigned char* iv = nonce + 4;
308
309 memset(poly1305_key, 0, sizeof(poly1305_key));
310 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), key, iv, ctr);
311
312 CRYPTO_poly1305_init(&poly1305, poly1305_key);
313 poly1305_update_with_pad16(&poly1305, ad, ad_len);
314 CRYPTO_chacha_20(out, in, in_len, key, iv, ctr + 1);
315 poly1305_update_with_pad16(&poly1305, out, in_len);
316 poly1305_update_with_length(&poly1305, NULL, ad_len);
317 poly1305_update_with_length(&poly1305, NULL, in_len);
318
319 CRYPTO_poly1305_finish(&poly1305, out + in_len);
320
321 *out_len = in_len + 16;
322#endif
323#elif defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L)
324 int outl = 0;
325 EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
326 EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), NULL, key, nonce);
327 EVP_EncryptUpdate(ctx, out, &outl, in, in_len);
328 *out_len = outl;
329 outl = 0;
330 EVP_EncryptFinal_ex(ctx, out + *out_len, &outl);
331 *out_len += outl;
332 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, out + *out_len);
333 EVP_CIPHER_CTX_free(ctx);
334 *out_len += 16;
335#else
336#error Please use a newer version of OpenSSL (>= 1.1.0)
337#endif
338#elif defined(HAVE_GCRYPT)
339#if defined(GCRYPT_VERSION_NUMBER) && (GCRYPT_VERSION_NUMBER >= 0x010700)
340 gcry_cipher_hd_t hd;
341 if (gcry_cipher_open(&hd, GCRY_CIPHER_CHACHA20, GCRY_CIPHER_MODE_POLY1305, 0)) {
342 debug_info("gcry_cipher_open() failed");
343 return;
344 }
345 gcry_cipher_setkey(hd, key, 32);
346 gcry_cipher_setiv(hd, nonce, 12);
347 gcry_cipher_authenticate(hd, ad, ad_len);
348 *out_len = in_len + 16;
349 if (gcry_cipher_encrypt(hd, out, *out_len, in, in_len)) {
350 *out_len = 0;
351 }
352 gcry_cipher_gettag(hd, out+in_len, 16);
353 gcry_cipher_close(hd);
354#else
355#error Please use a newer version of libgcrypt (>= 1.7.0)
356#endif
357#elif defined (HAVE_MBEDTLS)
358 mbedtls_chachapoly_context ctx;
359 mbedtls_chachapoly_init(&ctx);
360 mbedtls_chachapoly_setkey(&ctx, key);
361 if (mbedtls_chachapoly_encrypt_and_tag(&ctx, in_len, nonce, ad, ad_len, in, out, out+in_len) != 0) {
362 *out_len = 0;
363 }
364 mbedtls_chachapoly_free(&ctx);
365#else
366#error chacha20_poly1305_encrypt_96 is not implemented
367#endif
368}
369
370static void chacha20_poly1305_encrypt_64(unsigned char* key, unsigned char* nonce, unsigned char* ad, size_t ad_len, unsigned char* in, size_t in_len, unsigned char* out, size_t* out_len)
371{
372 unsigned char _nonce[12];
373 *(uint32_t*)(&_nonce[0]) = 0;
374 memcpy(&_nonce[4], nonce, 8);
375 chacha20_poly1305_encrypt_96(key, _nonce, ad, ad_len, in, in_len, out, out_len);
376}
377
378static void chacha20_poly1305_decrypt_96(unsigned char* key, unsigned char* nonce, unsigned char* ad, size_t ad_len, unsigned char* in, size_t in_len, unsigned char* out, size_t* out_len)
379{
380#if defined(HAVE_OPENSSL)
381#if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x3050000fL)
382#if (LIBRESSL_VERSION_NUMBER >= 0x2040000fL)
383 const EVP_AEAD *aead = EVP_aead_chacha20_poly1305();
384 EVP_AEAD_CTX ctx;
385 EVP_AEAD_CTX_init(&ctx, aead, key, EVP_AEAD_key_length(aead), EVP_AEAD_DEFAULT_TAG_LENGTH, NULL);
386 EVP_AEAD_CTX_open(&ctx, out, out_len, *out_len, nonce, 12, in, in_len, ad, ad_len);
387#else
388 unsigned char mac[16];
389 unsigned char poly1305_key[32];
390 poly1305_state poly1305;
391 size_t plaintext_len = in_len - 16;
392 uint64_t ctr = (uint64_t)(nonce[0] | nonce[1] << 8 | nonce[2] << 16 | nonce[3] << 24) << 32;
393 const unsigned char *iv = nonce + 4;
394
395 memset(poly1305_key, 0, sizeof(poly1305_key));
396 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), key, iv, ctr);
397
398 CRYPTO_poly1305_init(&poly1305, poly1305_key);
399 poly1305_update_with_pad16(&poly1305, ad, ad_len);
400 poly1305_update_with_pad16(&poly1305, in, plaintext_len);
401 poly1305_update_with_length(&poly1305, NULL, ad_len);
402 poly1305_update_with_length(&poly1305, NULL, plaintext_len);
403
404 CRYPTO_poly1305_finish(&poly1305, mac);
405
406 if (memcmp(mac, in + plaintext_len, 16) != 0) {
407 *out_len = 0;
408 return;
409 }
410
411 CRYPTO_chacha_20(out, in, plaintext_len, key, iv, ctr + 1);
412 *out_len = plaintext_len;
413#endif
414#elif defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L)
415 int outl = 0;
416 size_t plaintext_len = in_len - 16;
417 EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
418 EVP_DecryptInit_ex(ctx, EVP_chacha20_poly1305(), NULL, key, nonce);
419 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, in + plaintext_len);
420 EVP_DecryptUpdate(ctx, out, &outl, in, plaintext_len);
421 *out_len = outl;
422 outl = 0;
423 if (EVP_DecryptFinal_ex(ctx, out + *out_len, &outl) == 1) {
424 *out_len += outl;
425 } else {
426 *out_len = 0;
427 }
428 EVP_CIPHER_CTX_free(ctx);
429#else
430#error Please use a newer version of OpenSSL (>= 1.1.0)
431#endif
432#elif defined(HAVE_GCRYPT)
433#if defined(GCRYPT_VERSION_NUMBER) && (GCRYPT_VERSION_NUMBER >= 0x010700)
434 gcry_cipher_hd_t hd;
435 if (gcry_cipher_open(&hd, GCRY_CIPHER_CHACHA20, GCRY_CIPHER_MODE_POLY1305, 0)) {
436 debug_info("gcry_cipher_open() failed");
437 return;
438 }
439 gcry_cipher_setkey(hd, key, 32);
440 gcry_cipher_setiv(hd, nonce, 12);
441 gcry_cipher_authenticate(hd, ad, ad_len);
442 unsigned int plaintext_len = in_len - 16;
443 gcry_cipher_decrypt(hd, out, *out_len, in, plaintext_len);
444 if (gcry_cipher_checktag(hd, in + plaintext_len, 16) == 0) {
445 *out_len = plaintext_len;
446 } else {
447 *out_len = 0;
448 }
449 gcry_cipher_close(hd);
450#else
451#error Please use a newer version of libgcrypt (>= 1.7.0)
452#endif
453#elif defined(HAVE_MBEDTLS)
454 mbedtls_chachapoly_context ctx;
455 mbedtls_chachapoly_init(&ctx);
456 mbedtls_chachapoly_setkey(&ctx, key);
457 unsigned int plaintext_len = in_len - 16;
458 if (mbedtls_chachapoly_auth_decrypt(&ctx, plaintext_len, nonce, ad, ad_len, in + plaintext_len, in, out) == 0) {
459 *out_len = plaintext_len;
460 } else {
461 *out_len = 0;
462 }
463 mbedtls_chachapoly_free(&ctx);
464#else
465#error chacha20_poly1305_decrypt_96 is not implemented
466#endif
467}
468
469static void chacha20_poly1305_decrypt_64(unsigned char* key, unsigned char* nonce, unsigned char* ad, size_t ad_len, unsigned char* in, size_t in_len, unsigned char* out, size_t* out_len)
470{
471 unsigned char _nonce[12];
472 *(uint32_t*)(&_nonce[0]) = 0;
473 memcpy(&_nonce[4], nonce, 8);
474 chacha20_poly1305_decrypt_96(key, _nonce, ad, ad_len, in, in_len, out, out_len);
475}
476/* }}} */
477
478#define PAIRING_ERROR(x) \
479 debug_info(x); \
480 if (pairing_callback) { \
481 pairing_callback(LOCKDOWN_CU_PAIRING_ERROR, cb_user_data, (char*)x, NULL); \
482 }
483
484#define PAIRING_ERROR_FMT(...) \
485 sprintf(tmp, __VA_ARGS__); \
486 debug_info(tmp); \
487 if (pairing_callback) { \
488 pairing_callback(LOCKDOWN_CU_PAIRING_ERROR, cb_user_data, tmp, NULL); \
489 }
490
491#endif /* HAVE_WIRELESS_PAIRING */
492
493lockdownd_error_t lockdownd_cu_pairing_create(lockdownd_client_t client, lockdownd_cu_pairing_cb_t pairing_callback, void* cb_user_data, plist_t host_info, plist_t acl)
494{
495#ifdef HAVE_WIRELESS_PAIRING
496 if (!client || !pairing_callback || (host_info && plist_get_node_type(host_info) != PLIST_DICT) || (acl && plist_get_node_type(acl) != PLIST_DICT))
497 return LOCKDOWN_E_INVALID_ARG;
498
499 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
500
501 if (client->device && client->device->version == 0) {
502 plist_t p_version = NULL;
503 if (lockdownd_get_value(client, NULL, "ProductVersion", &p_version) == LOCKDOWN_E_SUCCESS) {
504 int vers[3] = {0, 0, 0};
505 char *s_version = NULL;
506 plist_get_string_val(p_version, &s_version);
507 if (s_version && sscanf(s_version, "%d.%d.%d", &vers[0], &vers[1], &vers[2]) >= 2) {
508 client->device->version = DEVICE_VERSION(vers[0], vers[1], vers[2]);
509 }
510 free(s_version);
511 }
512 plist_free(p_version);
513 }
514
515 char* pairing_uuid = NULL;
516 if (host_info) {
517 plist_t accountid = plist_dict_get_item(host_info, "accountID");
518 if (accountid && plist_get_node_type(accountid) == PLIST_STRING) {
519 plist_get_string_val(accountid, &pairing_uuid);
520 }
521 }
522 if (!pairing_uuid) {
523 userpref_read_system_buid(&pairing_uuid);
524 }
525 if (!pairing_uuid) {
526 pairing_uuid = generate_uuid();
527 }
528 unsigned int pairing_uuid_len = strlen(pairing_uuid);
529
530 SRP_initialize_library();
531
532 SRP* srp = SRP_new(SRP6a_sha512_client_method());
533 if (!srp) {
534 PAIRING_ERROR("Failed to initialize SRP")
535 return LOCKDOWN_E_UNKNOWN_ERROR;
536 }
537
538 char tmp[256];
539 plist_t dict = NULL;
540 uint8_t current_state = 0;
541 uint8_t final_state = 6;
542
543 unsigned char* salt = NULL;
544 unsigned int salt_size = 0;
545 unsigned char* pubkey = NULL;
546 unsigned int pubkey_size = 0;
547
548 unsigned char setup_encryption_key[32];
549
550 cstr *thekey = NULL;
551
552 do {
553 current_state++;
554
555 dict = plist_new_dict();
556 plist_dict_set_item(dict, "Request", plist_new_string("CUPairingCreate"));
557 if (current_state == 1) {
558 plist_dict_set_item(dict, "Flags", plist_new_uint(1));
559 } else {
560 plist_dict_set_item(dict, "Flags", plist_new_uint(0));
561 }
562
563 tlv_buf_t tlv = tlv_buf_new();
564
565 if (current_state == 1) {
566 /* send method */
567 tlv_buf_append(tlv, 0x00, 1, (void*)"\x00"); // 0x00 (Method), 1 bytes, 00
568 } else if (current_state == 3) {
569 /* generate public key */
570 cstr* own_pub = NULL;
571 SRP_gen_pub(srp, &own_pub);
572
573 if (!own_pub) {
574 PAIRING_ERROR("[SRP] Failed to generate public key")
575 ret = LOCKDOWN_E_PAIRING_FAILED;
576 break;
577 }
578
579 /* compute key from remote's public key */
580 if (SRP_compute_key(srp, &thekey, pubkey, pubkey_size) != 0) {
581 cstr_free(own_pub);
582 PAIRING_ERROR("[SRP] Failed to compute key")
583 ret = LOCKDOWN_E_PAIRING_FAILED;
584 break;
585 }
586
587 /* compute response */
588 cstr *response = NULL;
589 SRP_respond(srp, &response);
590
591 /* send our public key + response */
592 tlv_buf_append(tlv, 0x03, own_pub->length, own_pub->data);
593 tlv_buf_append(tlv, 0x04, response->length, response->data);
594 cstr_free(response);
595 cstr_free(own_pub);
596 } else if (current_state == 5) {
597 /* send encrypted info */
598
599 static const char PAIR_SETUP_ENCRYPT_SALT[] = "Pair-Setup-Encrypt-Salt";
600 static const char PAIR_SETUP_ENCRYPT_INFO[] = "Pair-Setup-Encrypt-Info";
601 static const char PAIR_SETUP_CONTROLLER_SIGN_SALT[] = "Pair-Setup-Controller-Sign-Salt";
602 static const char PAIR_SETUP_CONTROLLER_SIGN_INFO[] = "Pair-Setup-Controller-Sign-Info";
603
604 // HKDF with above computed key (SRP_compute_key) + Pair-Setup-Encrypt-Salt + Pair-Setup-Encrypt-Info
605 // result used as key for chacha20-poly1305
606 unsigned int setup_encryption_key_len = sizeof(setup_encryption_key);
607 hkdf_md(MD_ALGO_SHA512, (unsigned char*)PAIR_SETUP_ENCRYPT_SALT, sizeof(PAIR_SETUP_ENCRYPT_SALT)-1, (unsigned char*)PAIR_SETUP_ENCRYPT_INFO, sizeof(PAIR_SETUP_ENCRYPT_INFO)-1, (unsigned char*)thekey->data, thekey->length, setup_encryption_key, &setup_encryption_key_len);
608
609 unsigned char ed25519_pubkey[32];
610 unsigned char ed25519_privkey[64];
611 unsigned char ed25519seed[32];
612 ed25519_create_seed(ed25519seed);
613
614 ed25519_create_keypair(ed25519_pubkey, ed25519_privkey, ed25519seed);
615
616 unsigned int signbuf_len = pairing_uuid_len + 64;
617 unsigned char* signbuf = malloc(signbuf_len);
618 unsigned int hkdf_len = 32;
619 // HKDF with above computed key (SRP_compute_key) + Pair-Setup-Controller-Sign-Salt + Pair-Setup-Controller-Sign-Info
620 hkdf_md(MD_ALGO_SHA512, (unsigned char*)PAIR_SETUP_CONTROLLER_SIGN_SALT, sizeof(PAIR_SETUP_CONTROLLER_SIGN_SALT)-1, (unsigned char*)PAIR_SETUP_CONTROLLER_SIGN_INFO, sizeof(PAIR_SETUP_CONTROLLER_SIGN_INFO)-1, (unsigned char*)thekey->data, thekey->length, signbuf, &hkdf_len);
621
622 memcpy(signbuf + 32, pairing_uuid, pairing_uuid_len);
623 memcpy(signbuf + 32 + pairing_uuid_len, ed25519_pubkey, 32);
624
625 unsigned char ed_sig[64];
626 ed25519_sign(ed_sig, signbuf, 0x64, ed25519_pubkey, ed25519_privkey);
627
628 tlv_buf_t tlvbuf = tlv_buf_new();
629 tlv_buf_append(tlvbuf, 0x01, pairing_uuid_len, (void*)pairing_uuid);
630 tlv_buf_append(tlvbuf, 0x03, sizeof(ed25519_pubkey), ed25519_pubkey);
631 tlv_buf_append(tlvbuf, 0x0a, sizeof(ed_sig), ed_sig);
632
633 /* ACL */
634 unsigned char* odata = NULL;
635 unsigned int olen = 0;
636 if (acl) {
637 opack_encode_from_plist(acl, &odata, &olen);
638 } else {
639 /* defaut ACL */
640 plist_t acl_plist = plist_new_dict();
641 plist_dict_set_item(acl_plist, "com.apple.ScreenCapture", plist_new_bool(1));
642 plist_dict_set_item(acl_plist, "com.apple.developer", plist_new_bool(1));
643 opack_encode_from_plist(acl_plist, &odata, &olen);
644 plist_free(acl_plist);
645 }
646 tlv_buf_append(tlvbuf, 0x12, olen, odata);
647 free(odata);
648
649 /* HOST INFORMATION */
650 char hostname[256];
651#if defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
652 CFStringRef cname = SCDynamicStoreCopyComputerName(NULL, NULL);
653 CFStringGetCString(cname, hostname, sizeof(hostname), kCFStringEncodingUTF8);
654 CFRelease(cname);
655#else
656#ifdef WIN32
657 DWORD hostname_len = sizeof(hostname);
658 GetComputerName(hostname, &hostname_len);
659#else
660 gethostname(hostname, sizeof(hostname));
661#endif
662#endif
663
664 char modelname[256];
665 modelname[0] = '\0';
666#ifdef __APPLE__
667 size_t len = sizeof(modelname);
668 sysctlbyname("hw.model", &modelname, &len, NULL, 0);
669#endif
670 if (strlen(modelname) == 0) {
671 strcpy(modelname, "HackbookPro13,37");
672 }
673
674 unsigned char primary_mac_addr[6] = { 0, 0, 0, 0, 0, 0 };
675 if (get_primary_mac_address(primary_mac_addr) != 0) {
676 debug_info("Failed to get primary mac address");
677 }
678 debug_info("Primary mac address: %02x:%02x:%02x:%02x:%02x:%02x\n", primary_mac_addr[0], primary_mac_addr[1], primary_mac_addr[2], primary_mac_addr[3], primary_mac_addr[4], primary_mac_addr[5]);
679
680 // "OPACK" encoded device info
681 plist_t info_plist = plist_new_dict();
682 //plist_dict_set_item(info_plist, "altIRK", plist_new_data((char*)altIRK, 16));
683 plist_dict_set_item(info_plist, "accountID", plist_new_string(pairing_uuid));
684 plist_dict_set_item(info_plist, "model", plist_new_string(modelname));
685 plist_dict_set_item(info_plist, "name", plist_new_string(hostname));
686 plist_dict_set_item(info_plist, "mac", plist_new_data((char*)primary_mac_addr, 6));
687 if (host_info) {
688 plist_dict_merge(&info_plist, host_info);
689 }
690 opack_encode_from_plist(info_plist, &odata, &olen);
691 plist_free(info_plist);
692 tlv_buf_append(tlvbuf, 0x11, olen, odata);
693 free(odata);
694
695 size_t encrypted_len = tlvbuf->length + 16;
696 unsigned char* encrypted_buf = (unsigned char*)malloc(encrypted_len);
697
698 chacha20_poly1305_encrypt_64(setup_encryption_key, (unsigned char*)"PS-Msg05", NULL, 0, tlvbuf->data, tlvbuf->length, encrypted_buf, &encrypted_len);
699
700 tlv_buf_free(tlvbuf);
701
702 tlv_buf_append(tlv, 0x05, encrypted_len, encrypted_buf);
703 free(encrypted_buf);
704 } else {
705 tlv_buf_free(tlv);
706 PAIRING_ERROR("[SRP] Invalid state");
707 ret = LOCKDOWN_E_PAIRING_FAILED;
708 break;
709 }
710 tlv_buf_append(tlv, 0x06, 1, &current_state);
711 plist_dict_set_item(dict, "Payload", plist_new_data((char*)tlv->data, tlv->length));
712 tlv_buf_free(tlv);
713
714 plist_dict_set_item(dict, "Label", plist_new_string(client->label));
715 plist_dict_set_item(dict, "ProtocolVersion", plist_new_uint(2));
716
717 ret = lockdownd_send(client, dict);
718 plist_free(dict);
719 dict = NULL;
720
721 if (ret != LOCKDOWN_E_SUCCESS) {
722 break;
723 }
724
725 current_state++;
726
727 ret = lockdownd_receive(client, &dict);
728 if (ret != LOCKDOWN_E_SUCCESS) {
729 break;
730 }
731 ret = lockdown_check_result(dict, "CUPairingCreate");
732 if (ret != LOCKDOWN_E_SUCCESS) {
733 break;
734 }
735
736 plist_t extresp = plist_dict_get_item(dict, "ExtendedResponse");
737 if (!extresp) {
738 ret = LOCKDOWN_E_PLIST_ERROR;
739 break;
740 }
741 plist_t blob = plist_dict_get_item(extresp, "Payload");
742 if (!blob) {
743 ret = LOCKDOWN_E_PLIST_ERROR;
744 break;
745 }
746 uint64_t data_len = 0;
747 const char* data = plist_get_data_ptr(blob, &data_len);
748
749 uint8_t state = 0;
750 if (!tlv_data_get_uint8(data, data_len, 0x06, &state)) {
751 PAIRING_ERROR("[SRP] ERROR: Could not find state in response");
752 ret = LOCKDOWN_E_PAIRING_FAILED;
753 break;
754 }
755 if (state != current_state) {
756 PAIRING_ERROR_FMT("[SRP] ERROR: Unexpected state %d, expected %d", state, current_state);
757 ret = LOCKDOWN_E_PAIRING_FAILED;
758 break;
759 }
760
761 unsigned int errval = 0;
762 uint64_t u64val = 0;
763 tlv_data_get_uint(data, data_len, 0x07, &u64val);
764debug_buffer(data, data_len);
765 errval = (unsigned int)u64val;
766 if (errval > 0) {
767 if (errval == 3) {
768 u64val = 0;
769 tlv_data_get_uint(data, data_len, 0x08, &u64val);
770 if (u64val > 0) {
771 uint32_t retry_delay = (uint32_t)u64val;
772 PAIRING_ERROR_FMT("[SRP] Pairing is blocked for another %u seconds", retry_delay)
773 ret = LOCKDOWN_E_PAIRING_FAILED;
774 break;
775 }
776 } else if (errval == 2 && state == 4) {
777 PAIRING_ERROR_FMT("[SRP] Invalid PIN")
778 ret = LOCKDOWN_E_PAIRING_FAILED;
779 break;
780 } else {
781 PAIRING_ERROR_FMT("[SRP] Received error %u in state %d.", errval, state);
782 ret = LOCKDOWN_E_PAIRING_FAILED;
783 break;
784 }
785 }
786
787 if (state == 2) {
788 /* receive salt and public key */
789 if (!tlv_data_copy_data(data, data_len, 0x02, (void**)&salt, &salt_size)) {
790 PAIRING_ERROR("[SRP] ERROR: Could not find salt in response");
791 ret = LOCKDOWN_E_PAIRING_FAILED;
792 break;
793 }
794 if (!tlv_data_copy_data(data, data_len, 0x03, (void**)&pubkey, &pubkey_size)) {
795 PAIRING_ERROR("[SRP] ERROR: Could not find public key in response");
796
797 ret = LOCKDOWN_E_PAIRING_FAILED;
798 break;
799 }
800
801 const char PAIR_SETUP[] = "Pair-Setup";
802 if (SRP_set_user_raw(srp, (const unsigned char*)PAIR_SETUP, sizeof(PAIR_SETUP)-1) != 0) {
803 PAIRING_ERROR("[SRP] Failed to set SRP user");
804 ret = LOCKDOWN_E_PAIRING_FAILED;
805 break;
806 }
807
808 /* kSRPParameters_3072_SHA512 */
809 if (SRP_set_params(srp, kSRPModulus3072, sizeof(kSRPModulus3072), &kSRPGenerator5, 1, salt, salt_size) != 0) {
810 PAIRING_ERROR("[SRP] Failed to set SRP parameters");
811 ret = LOCKDOWN_E_PAIRING_FAILED;
812 break;
813
814 }
815
816 if (pairing_callback) {
817 char pin[64];
818 unsigned int pin_len = sizeof(pin);
819 pairing_callback(LOCKDOWN_CU_PAIRING_PIN_REQUESTED, cb_user_data, pin, &pin_len);
820
821 SRP_set_auth_password_raw(srp, (const unsigned char*)pin, pin_len);
822 }
823 } else if (state == 4) {
824 /* receive proof */
825 unsigned char* proof = NULL;
826 unsigned int proof_len = 0;
827
828 if (!tlv_data_copy_data(data, data_len, 0x04, (void**)&proof, &proof_len)) {
829 PAIRING_ERROR("[SRP] ERROR: Could not find proof data in response");
830 ret = LOCKDOWN_E_PAIRING_FAILED;
831 break;
832 }
833
834 /* verify */
835 int vrfy_result = SRP_verify(srp, proof, proof_len);
836 free(proof);
837
838 if (vrfy_result == 0) {
839 debug_info("[SRP] PIN verified successfully");
840 } else {
841 PAIRING_ERROR("[SRP] PIN verification failure");
842 ret = LOCKDOWN_E_PAIRING_FAILED;
843 break;
844 }
845
846 } else if (state == 6) {
847 int srp_pair_success = 0;
848 plist_t node = plist_dict_get_item(extresp, "doSRPPair");
849 if (node) {
850 const char* strv = plist_get_string_ptr(node, NULL);
851 if (strcmp(strv, "succeed") == 0) {
852 srp_pair_success = 1;
853 }
854 }
855 if (!srp_pair_success) {
856 PAIRING_ERROR("SRP Pairing failed");
857 ret = LOCKDOWN_E_PAIRING_FAILED;
858 break;
859 }
860
861 /* receive encrypted info */
862 unsigned char* encrypted_buf = NULL;
863 unsigned int enc_len = 0;
864 if (!tlv_data_copy_data(data, data_len, 0x05, (void**)&encrypted_buf, &enc_len)) {
865 PAIRING_ERROR("[SRP] ERROR: Could not find encrypted data in response");
866 ret = LOCKDOWN_E_PAIRING_FAILED;
867 break;
868 }
869 size_t plain_len = enc_len-16;
870 unsigned char* plain_buf = malloc(plain_len);
871 chacha20_poly1305_decrypt_64(setup_encryption_key, (unsigned char*)"PS-Msg06", NULL, 0, encrypted_buf, enc_len, plain_buf, &plain_len);
872 free(encrypted_buf);
873
874 unsigned char* dev_info = NULL;
875 unsigned int dev_info_len = 0;
876 int res = tlv_data_copy_data(plain_buf, plain_len, 0x11, (void**)&dev_info, &dev_info_len);
877 free(plain_buf);
878 if (!res) {
879 PAIRING_ERROR("[SRP] ERROR: Failed to locate device info in response");
880 ret = LOCKDOWN_E_PAIRING_FAILED;
881 break;
882 }
883 plist_t device_info = NULL;
884 opack_decode_to_plist(dev_info, dev_info_len, &device_info);
885 free(dev_info);
886
887 if (!device_info) {
888 PAIRING_ERROR("[SRP] ERROR: Failed to parse device info");
889 ret = LOCKDOWN_E_PAIRING_FAILED;
890 break;
891 }
892
893 if (pairing_callback) {
894 pairing_callback(LOCKDOWN_CU_PAIRING_DEVICE_INFO, cb_user_data, device_info, NULL);
895 }
896 plist_free(device_info);
897 } else {
898 PAIRING_ERROR("[SRP] ERROR: Invalid state");
899 ret = LOCKDOWN_E_PAIRING_FAILED;
900 break;
901 }
902 plist_free(dict);
903 dict = NULL;
904
905 } while (current_state != final_state);
906
907 plist_free(dict);
908
909 free(salt);
910 free(pubkey);
911
912 SRP_free(srp);
913 srp = NULL;
914
915 if (ret != LOCKDOWN_E_SUCCESS) {
916 if (thekey) {
917 cstr_free(thekey);
918 }
919 return ret;
920 }
921
922 free(client->cu_key);
923 client->cu_key = malloc(thekey->length);
924 memcpy(client->cu_key, thekey->data, thekey->length);
925 client->cu_key_len = thekey->length;
926 cstr_free(thekey);
927
928 return LOCKDOWN_E_SUCCESS;
929#else
930 debug_info("not supported");
931 return LOCKDOWN_E_UNKNOWN_ERROR;
932#endif
933}
934
935lockdownd_error_t lockdownd_cu_send_request_and_get_reply(lockdownd_client_t client, const char* request, plist_t request_payload, plist_t* reply)
936{
937#ifdef HAVE_WIRELESS_PAIRING
938 if (!client || !request)
939 return LOCKDOWN_E_INVALID_ARG;
940
941 if (!client->cu_key)
942 return LOCKDOWN_E_NO_RUNNING_SESSION;
943
944 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
945
946 /* derive keys */
947 unsigned char cu_write_key[32];
948 unsigned int cu_write_key_len = sizeof(cu_write_key);
949 static const char WRITE_KEY_SALT_MDLD[] = "WriteKeySaltMDLD";
950 static const char WRITE_KEY_INFO_MDLD[] = "WriteKeyInfoMDLD";
951 hkdf_md(MD_ALGO_SHA512, (unsigned char*)WRITE_KEY_SALT_MDLD, sizeof(WRITE_KEY_SALT_MDLD)-1, (unsigned char*)WRITE_KEY_INFO_MDLD, sizeof(WRITE_KEY_INFO_MDLD)-1, client->cu_key, client->cu_key_len, cu_write_key, &cu_write_key_len);
952
953 unsigned char cu_read_key[32];
954 unsigned int cu_read_key_len = sizeof(cu_write_key);
955 static const char READ_KEY_SALT_MDLD[] = "ReadKeySaltMDLD";
956 static const char READ_KEY_INFO_MDLD[] = "ReadKeyInfoMDLD";
957 hkdf_md(MD_ALGO_SHA512, (unsigned char*)READ_KEY_SALT_MDLD, sizeof(READ_KEY_SALT_MDLD)-1, (unsigned char*)READ_KEY_INFO_MDLD, sizeof(READ_KEY_INFO_MDLD)-1, client->cu_key, client->cu_key_len, cu_read_key, &cu_read_key_len);
958
959 // Starting with iOS/tvOS 11.2 and WatchOS 4.2, this nonce is random and sent along with the request. Before, the request doesn't have a nonce and it uses hardcoded nonce "sendone01234".
960 unsigned char cu_nonce[12] = "sendone01234"; // guaranteed to be random by fair dice troll
961 if (client->device->version >= DEVICE_VERSION(11,2,0)) {
962#if defined(HAVE_OPENSSL)
963 RAND_bytes(cu_nonce, sizeof(cu_nonce));
964#elif defined(HAVE_GCRYPT)
965 gcry_create_nonce(cu_nonce, sizeof(cu_nonce));
966#endif
967 }
968
969 debug_plist(request_payload);
970
971 /* convert request payload to binary */
972 uint32_t bin_len = 0;
973 char* bin = NULL;
974 plist_to_bin(request_payload, &bin, &bin_len);
975
976 /* encrypt request */
977 size_t encrypted_len = bin_len + 16;
978 unsigned char* encrypted_buf = malloc(encrypted_len);
979 chacha20_poly1305_encrypt_96(cu_write_key, cu_nonce, NULL, 0, (unsigned char*)bin, bin_len, encrypted_buf, &encrypted_len);
980 free(bin);
981 bin = NULL;
982
983 plist_t dict = plist_new_dict();
984 plist_dict_set_item(dict,"Request", plist_new_string(request));
985 plist_dict_set_item(dict, "Payload", plist_new_data((char*)encrypted_buf, encrypted_len));
986 free(encrypted_buf);
987 plist_dict_set_item(dict, "Nonce", plist_new_data((char*)cu_nonce, sizeof(cu_nonce)));
988 plist_dict_set_item(dict, "Label", plist_new_string(client->label));
989 plist_dict_set_item(dict, "ProtocolVersion", plist_new_uint(2));
990
991 /* send to device */
992 ret = lockdownd_send(client, dict);
993 plist_free(dict);
994 dict = NULL;
995
996 if (ret != LOCKDOWN_E_SUCCESS)
997 return ret;
998
999 /* Now get device's answer */
1000 ret = lockdownd_receive(client, &dict);
1001 if (ret != LOCKDOWN_E_SUCCESS)
1002 return ret;
1003
1004 ret = lockdown_check_result(dict, request);
1005 if (ret != LOCKDOWN_E_SUCCESS) {
1006 plist_free(dict);
1007 return ret;
1008 }
1009
1010 /* get payload */
1011 plist_t blob = plist_dict_get_item(dict, "Payload");
1012 if (!blob) {
1013 plist_free(dict);
1014 return LOCKDOWN_E_DICT_ERROR;
1015 }
1016
1017 uint64_t dl = 0;
1018 const char* dt = plist_get_data_ptr(blob, &dl);
1019
1020 /* see if we have a nonce */
1021 blob = plist_dict_get_item(dict, "Nonce");
1022 const unsigned char* rnonce = (unsigned char*)"receiveone01";
1023 if (blob) {
1024 uint64_t rl = 0;
1025 rnonce = (const unsigned char*)plist_get_data_ptr(blob, &rl);
1026 }
1027
1028 /* decrypt payload */
1029 size_t decrypted_len = dl-16;
1030 unsigned char* decrypted = malloc(decrypted_len);
1031 chacha20_poly1305_decrypt_96(cu_read_key, (unsigned char*)rnonce, NULL, 0, (unsigned char*)dt, dl, decrypted, &decrypted_len);
1032 plist_free(dict);
1033 dict = NULL;
1034
1035 plist_from_memory((const char*)decrypted, decrypted_len, &dict, NULL);
1036 if (!dict) {
1037 ret = LOCKDOWN_E_PLIST_ERROR;
1038 debug_info("Failed to parse PLIST from decrypted payload:");
1039 debug_buffer((const char*)decrypted, decrypted_len);
1040 free(decrypted);
1041 return ret;
1042 }
1043 free(decrypted);
1044
1045 debug_plist(dict);
1046
1047 if (reply) {
1048 *reply = dict;
1049 } else {
1050 plist_free(dict);
1051 }
1052
1053 return LOCKDOWN_E_SUCCESS;
1054#else
1055 debug_info("not supported");
1056 return LOCKDOWN_E_UNKNOWN_ERROR;
1057#endif
1058}
1059
1060lockdownd_error_t lockdownd_get_value_cu(lockdownd_client_t client, const char* domain, const char* key, plist_t* value)
1061{
1062#ifdef HAVE_WIRELESS_PAIRING
1063 if (!client)
1064 return LOCKDOWN_E_INVALID_ARG;
1065
1066 if (!client->cu_key)
1067 return LOCKDOWN_E_NO_RUNNING_SESSION;
1068
1069 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
1070
1071 plist_t request = plist_new_dict();
1072 if (domain) {
1073 plist_dict_set_item(request, "Domain", plist_new_string(domain));
1074 }
1075 if (key) {
1076 plist_dict_set_item(request, "Key", plist_new_string(key));
1077 }
1078
1079 plist_t reply = NULL;
1080 ret = lockdownd_cu_send_request_and_get_reply(client, "GetValueCU", request, &reply);
1081 plist_free(request);
1082 if (ret != LOCKDOWN_E_SUCCESS) {
1083 return ret;
1084 }
1085
1086 plist_t value_node = plist_dict_get_item(reply, "Value");
1087 if (value_node) {
1088 debug_info("has a value");
1089 *value = plist_copy(value_node);
1090 }
1091 plist_free(reply);
1092
1093 return ret;
1094#else
1095 debug_info("not supported");
1096 return LOCKDOWN_E_UNKNOWN_ERROR;
1097#endif
1098}
1099
1100lockdownd_error_t lockdownd_pair_cu(lockdownd_client_t client)
1101{
1102#ifdef HAVE_WIRELESS_PAIRING
1103 if (!client)
1104 return LOCKDOWN_E_INVALID_ARG;
1105
1106 if (!client->cu_key)
1107 return LOCKDOWN_E_NO_RUNNING_SESSION;
1108
1109 lockdownd_error_t ret;
1110
1111 plist_t wifi_mac = NULL;
1112 ret = lockdownd_get_value_cu(client, NULL, "WiFiAddress", &wifi_mac);
1113 if (ret != LOCKDOWN_E_SUCCESS) {
1114 return ret;
1115 }
1116
1117 plist_t pubkey = NULL;
1118 ret = lockdownd_get_value_cu(client, NULL, "DevicePublicKey", &pubkey);
1119 if (ret != LOCKDOWN_E_SUCCESS) {
1120 plist_free(wifi_mac);
1121 return ret;
1122 }
1123
1124 key_data_t public_key = { NULL, 0 };
1125 uint64_t data_len = 0;
1126 plist_get_data_val(pubkey, (char**)&public_key.data, &data_len);
1127 public_key.size = (unsigned int)data_len;
1128 plist_free(pubkey);
1129
1130 plist_t pair_record_plist = plist_new_dict();
1131 pair_record_generate_keys_and_certs(pair_record_plist, public_key);
1132
1133 char* host_id = NULL;
1134 char* system_buid = NULL;
1135
1136 /* set SystemBUID */
1137 userpref_read_system_buid(&system_buid);
1138 if (system_buid) {
1139 plist_dict_set_item(pair_record_plist, USERPREF_SYSTEM_BUID_KEY, plist_new_string(system_buid));
1140 free(system_buid);
1141 }
1142
1143 /* set HostID */
1144 host_id = generate_uuid();
1145 pair_record_set_host_id(pair_record_plist, host_id);
1146 free(host_id);
1147
1148 plist_t request_pair_record = plist_copy(pair_record_plist);
1149 /* remove stuff that is private */
1150 plist_dict_remove_item(request_pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY);
1151 plist_dict_remove_item(request_pair_record, USERPREF_HOST_PRIVATE_KEY_KEY);
1152
1153 plist_t request = plist_new_dict();
1154 plist_dict_set_item(request, "PairRecord", request_pair_record);
1155 plist_t pairing_opts = plist_new_dict();
1156 plist_dict_set_item(pairing_opts, "ExtendedPairingErrors", plist_new_bool(1));
1157 plist_dict_set_item(request, "PairingOptions", pairing_opts);
1158
1159 plist_t reply = NULL;
1160 ret = lockdownd_cu_send_request_and_get_reply(client, "PairCU", request, &reply);
1161 plist_free(request);
1162 if (ret != LOCKDOWN_E_SUCCESS) {
1163 plist_free(wifi_mac);
1164 return ret;
1165 }
1166
1167 char *s_udid = NULL;
1168 plist_t p_udid = plist_dict_get_item(reply, "UDID");
1169 if (p_udid) {
1170 plist_get_string_val(p_udid, &s_udid);
1171 }
1172 plist_t ebag = plist_dict_get_item(reply, "EscrowBag");
1173 if (ebag) {
1174 plist_dict_set_item(pair_record_plist, USERPREF_ESCROW_BAG_KEY, plist_copy(ebag));
1175 }
1176 plist_dict_set_item(pair_record_plist, USERPREF_WIFI_MAC_ADDRESS_KEY, wifi_mac);
1177 plist_free(reply);
1178
1179 if (userpref_save_pair_record(s_udid, 0, pair_record_plist) != 0) {
1180 printf("Failed to save pair record for UDID %s\n", s_udid);
1181 }
1182 free(s_udid);
1183 s_udid = NULL;
1184 plist_free(pair_record_plist);
1185
1186 ret = LOCKDOWN_E_SUCCESS;
1187
1188 return ret;
1189#else
1190 debug_info("not supported");
1191 return LOCKDOWN_E_UNKNOWN_ERROR;
1192#endif
1193}