userpref.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171
  1. /*
  2. * userpref.c
  3. * contains methods to access user specific certificates IDs and more.
  4. *
  5. * Copyright (c) 2013-2021 Nikias Bassen, All Rights Reserved.
  6. * Copyright (c) 2013-2014 Martin Szulecki All Rights Reserved.
  7. * Copyright (c) 2008 Jonathan Beck All Rights Reserved.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2.1 of the License, or (at your option) any later version.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. #ifdef HAVE_CONFIG_H
  24. #include <config.h>
  25. #endif
  26. #include <stdio.h>
  27. #include <stdint.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <errno.h>
  31. #ifdef HAVE_SYS_TYPES_H
  32. #include <sys/types.h>
  33. #endif
  34. #include <dirent.h>
  35. #ifndef _WIN32
  36. #include <pwd.h>
  37. #include <unistd.h>
  38. #include <libgen.h>
  39. #include <sys/stat.h>
  40. #endif
  41. #include <usbmuxd.h>
  42. #if defined(HAVE_OPENSSL)
  43. #include <openssl/bn.h>
  44. #include <openssl/pem.h>
  45. #include <openssl/rsa.h>
  46. #include <openssl/x509.h>
  47. #include <openssl/x509v3.h>
  48. #if OPENSSL_VERSION_NUMBER < 0x1010000fL || \
  49. (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x20700000L))
  50. #define X509_set1_notBefore X509_set_notBefore
  51. #define X509_set1_notAfter X509_set_notAfter
  52. #endif
  53. #elif defined(HAVE_GNUTLS)
  54. #include <gnutls/gnutls.h>
  55. #include <gnutls/crypto.h>
  56. #include <gnutls/x509.h>
  57. #include <gcrypt.h>
  58. #include <libtasn1.h>
  59. #elif defined(HAVE_MBEDTLS)
  60. #include <mbedtls/ssl.h>
  61. #include <mbedtls/entropy.h>
  62. #include <mbedtls/ctr_drbg.h>
  63. #include <mbedtls/asn1write.h>
  64. #include <mbedtls/oid.h>
  65. #else
  66. #error No supported TLS/SSL library enabled
  67. #endif
  68. #ifdef _WIN32
  69. #include <shlobj.h>
  70. #endif
  71. #ifndef ETIMEDOUT
  72. #define ETIMEDOUT 138
  73. #endif
  74. #include <libimobiledevice-glue/utils.h>
  75. #include "userpref.h"
  76. #include "debug.h"
  77. #if defined(HAVE_GNUTLS)
  78. const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = {
  79. {"PKCS1", 536872976, 0},
  80. {0, 1073741836, 0},
  81. {"RSAPublicKey", 536870917, 0},
  82. {"modulus", 1073741827, 0},
  83. {"publicExponent", 3, 0},
  84. {0, 0, 0}
  85. };
  86. #endif
  87. #ifdef _WIN32
  88. #define DIR_SEP '\\'
  89. #define DIR_SEP_S "\\"
  90. #else
  91. #define DIR_SEP '/'
  92. #define DIR_SEP_S "/"
  93. #endif
  94. #define USERPREF_CONFIG_EXTENSION ".plist"
  95. #ifdef _WIN32
  96. #define USERPREF_CONFIG_DIR "Apple"DIR_SEP_S"Lockdown"
  97. #else
  98. #define USERPREF_CONFIG_DIR "lockdown"
  99. #endif
  100. #define USERPREF_CONFIG_FILE "SystemConfiguration"USERPREF_CONFIG_EXTENSION
  101. static char *__config_dir = NULL;
  102. #ifdef _WIN32
  103. static char *userpref_utf16_to_utf8(wchar_t *unistr, long len, long *items_read, long *items_written)
  104. {
  105. if (!unistr || (len <= 0)) return NULL;
  106. char *outbuf = (char*)malloc(3*(len+1));
  107. int p = 0;
  108. int i = 0;
  109. wchar_t wc;
  110. while (i < len) {
  111. wc = unistr[i++];
  112. if (wc >= 0x800) {
  113. outbuf[p++] = (char)(0xE0 + ((wc >> 12) & 0xF));
  114. outbuf[p++] = (char)(0x80 + ((wc >> 6) & 0x3F));
  115. outbuf[p++] = (char)(0x80 + (wc & 0x3F));
  116. } else if (wc >= 0x80) {
  117. outbuf[p++] = (char)(0xC0 + ((wc >> 6) & 0x1F));
  118. outbuf[p++] = (char)(0x80 + (wc & 0x3F));
  119. } else {
  120. outbuf[p++] = (char)(wc & 0x7F);
  121. }
  122. }
  123. if (items_read) {
  124. *items_read = i;
  125. }
  126. if (items_written) {
  127. *items_written = p;
  128. }
  129. outbuf[p] = 0;
  130. return outbuf;
  131. }
  132. #endif
  133. const char *userpref_get_config_dir()
  134. {
  135. char *base_config_dir = NULL;
  136. if (__config_dir)
  137. return __config_dir;
  138. #ifdef _WIN32
  139. wchar_t path[MAX_PATH+1];
  140. HRESULT hr;
  141. LPITEMIDLIST pidl = NULL;
  142. BOOL b = FALSE;
  143. hr = SHGetSpecialFolderLocation (NULL, CSIDL_COMMON_APPDATA, &pidl);
  144. if (hr == S_OK) {
  145. b = SHGetPathFromIDListW (pidl, path);
  146. if (b) {
  147. base_config_dir = userpref_utf16_to_utf8 (path, wcslen(path), NULL, NULL);
  148. CoTaskMemFree (pidl);
  149. }
  150. }
  151. #else
  152. #ifdef __APPLE__
  153. base_config_dir = strdup("/var/db");
  154. #else
  155. base_config_dir = strdup("/var/lib");
  156. #endif
  157. #endif
  158. __config_dir = string_concat(base_config_dir, DIR_SEP_S, USERPREF_CONFIG_DIR, NULL);
  159. if (__config_dir) {
  160. int i = strlen(__config_dir)-1;
  161. while ((i > 0) && (__config_dir[i] == DIR_SEP)) {
  162. __config_dir[i--] = '\0';
  163. }
  164. }
  165. free(base_config_dir);
  166. debug_info("initialized config_dir to %s", __config_dir);
  167. return __config_dir;
  168. }
  169. /**
  170. * Reads the SystemBUID from a previously generated configuration file.
  171. *
  172. * @note It is the responsibility of the calling function to free the returned system_buid.
  173. * @param system_buid A pointer that will be set to a newly allocated string containing the
  174. * SystemBUID upon successful return.
  175. * @return 0 if the SystemBUID has been successfully retrieved or < 0 otherwise.
  176. */
  177. int userpref_read_system_buid(char **system_buid)
  178. {
  179. int res = usbmuxd_read_buid(system_buid);
  180. if (res == 0) {
  181. debug_info("using %s as %s", *system_buid, USERPREF_SYSTEM_BUID_KEY);
  182. } else {
  183. debug_info("could not read system buid, error %d", res);
  184. }
  185. return res;
  186. }
  187. /**
  188. * Fills a list with UDIDs of devices that have been connected to this
  189. * system before, i.e. for which a public key file exists.
  190. *
  191. * @param list A pointer to a char** initially pointing to NULL that will
  192. * hold a newly allocated list of UDIDs upon successful return.
  193. * The caller is responsible for freeing the memory. Note that if
  194. * no public key file was found the list has to be freed too as it
  195. * points to a terminating NULL element.
  196. * @param count The number of UDIDs found. This parameter can be NULL if it
  197. * is not required.
  198. *
  199. * @return USERPREF_E_SUCCESS on success, or USERPREF_E_INVALID_ARG if the
  200. * list parameter is not pointing to NULL.
  201. */
  202. userpref_error_t userpref_get_paired_udids(char ***list, unsigned int *count)
  203. {
  204. DIR *config_dir;
  205. const char *config_path = NULL;
  206. unsigned int found = 0;
  207. if (!list || (list && *list)) {
  208. debug_info("ERROR: The list parameter needs to point to NULL!");
  209. return USERPREF_E_INVALID_ARG;
  210. }
  211. if (count) {
  212. *count = 0;
  213. }
  214. *list = (char**)malloc(sizeof(char*));
  215. config_path = userpref_get_config_dir();
  216. config_dir = opendir(config_path);
  217. if (config_dir) {
  218. struct dirent *entry;
  219. while ((entry = readdir(config_dir))) {
  220. if (strcmp(entry->d_name, USERPREF_CONFIG_FILE) == 0) {
  221. /* ignore SystemConfiguration.plist */
  222. continue;
  223. }
  224. char *ext = strrchr(entry->d_name, '.');
  225. if (ext && (strcmp(ext, USERPREF_CONFIG_EXTENSION) == 0)) {
  226. size_t len = strlen(entry->d_name) - strlen(USERPREF_CONFIG_EXTENSION);
  227. char **newlist = (char**)realloc(*list, sizeof(char*) * (found+2));
  228. if (!newlist) {
  229. fprintf(stderr, "ERROR: Out of memory\n");
  230. break;
  231. }
  232. *list = newlist;
  233. char *tmp = (char*)malloc(len+1);
  234. if (tmp) {
  235. strncpy(tmp, entry->d_name, len);
  236. tmp[len] = '\0';
  237. }
  238. (*list)[found] = tmp;
  239. if (!tmp) {
  240. fprintf(stderr, "ERROR: Out of memory\n");
  241. break;
  242. }
  243. found++;
  244. }
  245. }
  246. closedir(config_dir);
  247. }
  248. (*list)[found] = NULL;
  249. if (count) {
  250. *count = found;
  251. }
  252. return USERPREF_E_SUCCESS;
  253. }
  254. /**
  255. * Save a pair record for a device.
  256. *
  257. * @param udid The device UDID as given by the device
  258. * @param device_id The usbmux device id (handle) of the connected device, or 0
  259. * @param pair_record The pair record to save
  260. *
  261. * @return 1 on success and 0 if no device record is given or if it has already
  262. * been saved previously.
  263. */
  264. userpref_error_t userpref_save_pair_record(const char *udid, uint32_t device_id, plist_t pair_record)
  265. {
  266. char* record_data = NULL;
  267. uint32_t record_size = 0;
  268. plist_to_bin(pair_record, &record_data, &record_size);
  269. int res = usbmuxd_save_pair_record_with_device_id(udid, device_id, record_data, record_size);
  270. free(record_data);
  271. return res == 0 ? USERPREF_E_SUCCESS: USERPREF_E_UNKNOWN_ERROR;
  272. }
  273. /**
  274. * Read a pair record for a device.
  275. *
  276. * @param udid The device UDID as given by the device
  277. * @param pair_record The pair record to read
  278. *
  279. * @return USERPREF_E_SUCCESS on success,
  280. * USERPREF_E_NOENT if no pairing record was found,
  281. * USERPREF_E_READ_ERROR if retrieving the pairing record from usbmuxd failed,
  282. * or USERPREF_E_INVALID_CONF otherwise.
  283. */
  284. userpref_error_t userpref_read_pair_record(const char *udid, plist_t *pair_record)
  285. {
  286. char* record_data = NULL;
  287. uint32_t record_size = 0;
  288. int res = usbmuxd_read_pair_record(udid, &record_data, &record_size);
  289. if (res < 0) {
  290. free(record_data);
  291. switch (-res) {
  292. case ENOENT:
  293. return USERPREF_E_NOENT;
  294. case ETIMEDOUT:
  295. return USERPREF_E_READ_ERROR;
  296. default:
  297. return USERPREF_E_INVALID_CONF;
  298. }
  299. }
  300. *pair_record = NULL;
  301. plist_from_memory(record_data, record_size, pair_record, NULL);
  302. free(record_data);
  303. if (!*pair_record) {
  304. debug_info("Failed to parse pairing record");
  305. return USERPREF_E_INVALID_CONF;
  306. }
  307. return USERPREF_E_SUCCESS;
  308. }
  309. /**
  310. * Remove the pairing record stored for a device from this host.
  311. *
  312. * @param udid The udid of the device
  313. *
  314. * @return USERPREF_E_SUCCESS on success.
  315. */
  316. userpref_error_t userpref_delete_pair_record(const char *udid)
  317. {
  318. int res = usbmuxd_delete_pair_record(udid);
  319. return res == 0 ? USERPREF_E_SUCCESS: USERPREF_E_UNKNOWN_ERROR;
  320. }
  321. #if defined(HAVE_OPENSSL)
  322. static int X509_add_ext_helper(X509 *cert, int nid, char *value)
  323. {
  324. X509_EXTENSION *ex;
  325. X509V3_CTX ctx;
  326. /* No configuration database */
  327. X509V3_set_ctx_nodb(&ctx);
  328. X509V3_set_ctx(&ctx, NULL, cert, NULL, NULL, 0);
  329. ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
  330. if (!ex) {
  331. debug_info("ERROR: X509V3_EXT_conf_nid(%d, %s) failed", nid, value);
  332. return 0;
  333. }
  334. X509_add_ext(cert, ex, -1);
  335. X509_EXTENSION_free(ex);
  336. return 1;
  337. }
  338. #elif defined(HAVE_MBEDTLS)
  339. static int _mbedtls_x509write_crt_set_basic_constraints_critical(mbedtls_x509write_cert *ctx, int is_ca, int max_pathlen)
  340. {
  341. int ret;
  342. unsigned char buf[9];
  343. unsigned char *c = buf + sizeof(buf);
  344. size_t len = 0;
  345. memset( buf, 0, sizeof(buf) );
  346. if (is_ca && max_pathlen > 127)
  347. return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
  348. if (is_ca) {
  349. if (max_pathlen >= 0) {
  350. MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) );
  351. }
  352. MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) );
  353. }
  354. MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
  355. MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
  356. return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ), 1, buf + sizeof(buf) - len, len );
  357. }
  358. #endif
  359. /**
  360. * Private function to generate required private keys and certificates.
  361. *
  362. * @param pair_record a #PLIST_DICT that will be filled with the keys
  363. * and certificates
  364. * @param public_key the public key to use (device public key)
  365. *
  366. * @return 1 if keys were successfully generated, 0 otherwise
  367. */
  368. userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_data_t public_key)
  369. {
  370. userpref_error_t ret = USERPREF_E_SSL_ERROR;
  371. key_data_t dev_cert_pem = { NULL, 0 };
  372. key_data_t root_key_pem = { NULL, 0 };
  373. key_data_t root_cert_pem = { NULL, 0 };
  374. key_data_t host_key_pem = { NULL, 0 };
  375. key_data_t host_cert_pem = { NULL, 0 };
  376. if (!pair_record || !public_key.data)
  377. return USERPREF_E_INVALID_ARG;
  378. debug_info("Generating keys and certificates...");
  379. #if defined(HAVE_OPENSSL)
  380. #if OPENSSL_VERSION_NUMBER >= 0x30000000L
  381. EVP_PKEY* root_pkey = EVP_RSA_gen(2048);
  382. EVP_PKEY* host_pkey = EVP_RSA_gen(2048);
  383. #else
  384. BIGNUM *e = BN_new();
  385. RSA* root_keypair = RSA_new();
  386. RSA* host_keypair = RSA_new();
  387. BN_set_word(e, 65537);
  388. RSA_generate_key_ex(root_keypair, 2048, e, NULL);
  389. RSA_generate_key_ex(host_keypair, 2048, e, NULL);
  390. BN_free(e);
  391. EVP_PKEY* root_pkey = EVP_PKEY_new();
  392. EVP_PKEY_assign_RSA(root_pkey, root_keypair);
  393. EVP_PKEY* host_pkey = EVP_PKEY_new();
  394. EVP_PKEY_assign_RSA(host_pkey, host_keypair);
  395. #endif
  396. /* generate root certificate */
  397. X509* root_cert = X509_new();
  398. {
  399. /* set serial number */
  400. ASN1_INTEGER* sn = ASN1_INTEGER_new();
  401. ASN1_INTEGER_set(sn, 0);
  402. X509_set_serialNumber(root_cert, sn);
  403. ASN1_INTEGER_free(sn);
  404. /* set version */
  405. X509_set_version(root_cert, 2);
  406. /* set x509v3 basic constraints */
  407. X509_add_ext_helper(root_cert, NID_basic_constraints, (char*)"critical,CA:TRUE");
  408. /* set key validity */
  409. ASN1_TIME* asn1time = ASN1_TIME_new();
  410. ASN1_TIME_set(asn1time, time(NULL));
  411. X509_set1_notBefore(root_cert, asn1time);
  412. ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10));
  413. X509_set1_notAfter(root_cert, asn1time);
  414. ASN1_TIME_free(asn1time);
  415. /* use root public key for root cert */
  416. X509_set_pubkey(root_cert, root_pkey);
  417. /* sign root cert with root private key */
  418. X509_sign(root_cert, root_pkey, EVP_sha1());
  419. }
  420. /* create host certificate */
  421. X509* host_cert = X509_new();
  422. {
  423. /* set serial number */
  424. ASN1_INTEGER* sn = ASN1_INTEGER_new();
  425. ASN1_INTEGER_set(sn, 0);
  426. X509_set_serialNumber(host_cert, sn);
  427. ASN1_INTEGER_free(sn);
  428. /* set version */
  429. X509_set_version(host_cert, 2);
  430. /* set x509v3 basic constraints */
  431. X509_add_ext_helper(host_cert, NID_basic_constraints, (char*)"critical,CA:FALSE");
  432. /* set x509v3 key usage */
  433. X509_add_ext_helper(host_cert, NID_key_usage, (char*)"critical,digitalSignature,keyEncipherment");
  434. /* set key validity */
  435. ASN1_TIME* asn1time = ASN1_TIME_new();
  436. ASN1_TIME_set(asn1time, time(NULL));
  437. X509_set1_notBefore(host_cert, asn1time);
  438. ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10));
  439. X509_set1_notAfter(host_cert, asn1time);
  440. ASN1_TIME_free(asn1time);
  441. /* use host public key for host cert */
  442. X509_set_pubkey(host_cert, host_pkey);
  443. /* sign host cert with root private key */
  444. X509_sign(host_cert, root_pkey, EVP_sha1());
  445. }
  446. if (root_cert && root_pkey && host_cert && host_pkey) {
  447. BIO* membp;
  448. char *bdata;
  449. membp = BIO_new(BIO_s_mem());
  450. if (PEM_write_bio_X509(membp, root_cert) > 0) {
  451. root_cert_pem.size = BIO_get_mem_data(membp, &bdata);
  452. root_cert_pem.data = (unsigned char*)malloc(root_cert_pem.size);
  453. if (root_cert_pem.data) {
  454. memcpy(root_cert_pem.data, bdata, root_cert_pem.size);
  455. }
  456. BIO_free(membp);
  457. membp = NULL;
  458. }
  459. membp = BIO_new(BIO_s_mem());
  460. if (PEM_write_bio_PrivateKey(membp, root_pkey, NULL, NULL, 0, 0, NULL) > 0) {
  461. root_key_pem.size = BIO_get_mem_data(membp, &bdata);
  462. root_key_pem.data = (unsigned char*)malloc(root_key_pem.size);
  463. if (root_key_pem.data) {
  464. memcpy(root_key_pem.data, bdata, root_key_pem.size);
  465. }
  466. BIO_free(membp);
  467. membp = NULL;
  468. }
  469. membp = BIO_new(BIO_s_mem());
  470. if (PEM_write_bio_X509(membp, host_cert) > 0) {
  471. host_cert_pem.size = BIO_get_mem_data(membp, &bdata);
  472. host_cert_pem.data = (unsigned char*)malloc(host_cert_pem.size);
  473. if (host_cert_pem.data) {
  474. memcpy(host_cert_pem.data, bdata, host_cert_pem.size);
  475. }
  476. BIO_free(membp);
  477. membp = NULL;
  478. }
  479. membp = BIO_new(BIO_s_mem());
  480. if (PEM_write_bio_PrivateKey(membp, host_pkey, NULL, NULL, 0, 0, NULL) > 0) {
  481. host_key_pem.size = BIO_get_mem_data(membp, &bdata);
  482. host_key_pem.data = (unsigned char*)malloc(host_key_pem.size);
  483. if (host_key_pem.data) {
  484. memcpy(host_key_pem.data, bdata, host_key_pem.size);
  485. }
  486. BIO_free(membp);
  487. membp = NULL;
  488. }
  489. }
  490. EVP_PKEY *pubkey = NULL;
  491. {
  492. BIO *membp = BIO_new_mem_buf(public_key.data, public_key.size);
  493. #if OPENSSL_VERSION_NUMBER >= 0x30000000L
  494. if (!PEM_read_bio_PUBKEY(membp, &pubkey, NULL, NULL)) {
  495. debug_info("WARNING: Could not read public key");
  496. }
  497. #else
  498. RSA *rsa_pubkey = NULL;
  499. if (!PEM_read_bio_RSAPublicKey(membp, &rsa_pubkey, NULL, NULL)) {
  500. debug_info("WARNING: Could not read public key");
  501. } else {
  502. pubkey = EVP_PKEY_new();
  503. EVP_PKEY_assign_RSA(pubkey, rsa_pubkey);
  504. }
  505. #endif
  506. BIO_free(membp);
  507. }
  508. X509* dev_cert = X509_new();
  509. if (pubkey && dev_cert) {
  510. /* generate device certificate */
  511. ASN1_INTEGER* sn = ASN1_INTEGER_new();
  512. ASN1_INTEGER_set(sn, 0);
  513. X509_set_serialNumber(dev_cert, sn);
  514. ASN1_INTEGER_free(sn);
  515. X509_set_version(dev_cert, 2);
  516. X509_add_ext_helper(dev_cert, NID_basic_constraints, (char*)"critical,CA:FALSE");
  517. ASN1_TIME* asn1time = ASN1_TIME_new();
  518. ASN1_TIME_set(asn1time, time(NULL));
  519. X509_set1_notBefore(dev_cert, asn1time);
  520. ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10));
  521. X509_set1_notAfter(dev_cert, asn1time);
  522. ASN1_TIME_free(asn1time);
  523. X509_set_pubkey(dev_cert, pubkey);
  524. X509_add_ext_helper(dev_cert, NID_subject_key_identifier, (char*)"hash");
  525. X509_add_ext_helper(dev_cert, NID_key_usage, (char*)"critical,digitalSignature,keyEncipherment");
  526. /* sign device certificate with root private key */
  527. if (X509_sign(dev_cert, root_pkey, EVP_sha1())) {
  528. /* if signing succeeded, export in PEM format */
  529. BIO* membp = BIO_new(BIO_s_mem());
  530. if (PEM_write_bio_X509(membp, dev_cert) > 0) {
  531. char *bdata = NULL;
  532. dev_cert_pem.size = BIO_get_mem_data(membp, &bdata);
  533. dev_cert_pem.data = (unsigned char*)malloc(dev_cert_pem.size);
  534. if (dev_cert_pem.data) {
  535. memcpy(dev_cert_pem.data, bdata, dev_cert_pem.size);
  536. }
  537. BIO_free(membp);
  538. membp = NULL;
  539. }
  540. } else {
  541. debug_info("ERROR: Signing device certificate with root private key failed!");
  542. }
  543. }
  544. X509_free(dev_cert);
  545. EVP_PKEY_free(pubkey);
  546. EVP_PKEY_free(root_pkey);
  547. EVP_PKEY_free(host_pkey);
  548. X509_free(host_cert);
  549. X509_free(root_cert);
  550. #elif defined(HAVE_GNUTLS)
  551. gnutls_x509_privkey_t root_privkey;
  552. gnutls_x509_crt_t root_cert;
  553. gnutls_x509_privkey_t host_privkey;
  554. gnutls_x509_crt_t host_cert;
  555. /* use less secure random to speed up key generation */
  556. gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM);
  557. gnutls_x509_privkey_init(&root_privkey);
  558. gnutls_x509_privkey_init(&host_privkey);
  559. gnutls_x509_crt_init(&root_cert);
  560. gnutls_x509_crt_init(&host_cert);
  561. /* generate root key */
  562. gnutls_x509_privkey_generate(root_privkey, GNUTLS_PK_RSA, 2048, 0);
  563. gnutls_x509_privkey_generate(host_privkey, GNUTLS_PK_RSA, 2048, 0);
  564. /* generate certificates */
  565. gnutls_x509_crt_set_key(root_cert, root_privkey);
  566. gnutls_x509_crt_set_serial(root_cert, "\x01", 1);
  567. gnutls_x509_crt_set_version(root_cert, 3);
  568. gnutls_x509_crt_set_ca_status(root_cert, 1);
  569. gnutls_x509_crt_set_activation_time(root_cert, time(NULL));
  570. gnutls_x509_crt_set_expiration_time(root_cert, time(NULL) + (60 * 60 * 24 * 365 * 10));
  571. gnutls_x509_crt_sign2(root_cert, root_cert, root_privkey, GNUTLS_DIG_SHA1, 0);
  572. gnutls_x509_crt_set_key(host_cert, host_privkey);
  573. gnutls_x509_crt_set_serial(host_cert, "\x01", 1);
  574. gnutls_x509_crt_set_version(host_cert, 3);
  575. gnutls_x509_crt_set_ca_status(host_cert, 0);
  576. gnutls_x509_crt_set_key_usage(host_cert, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE);
  577. gnutls_x509_crt_set_activation_time(host_cert, time(NULL));
  578. gnutls_x509_crt_set_expiration_time(host_cert, time(NULL) + (60 * 60 * 24 * 365 * 10));
  579. gnutls_x509_crt_sign2(host_cert, root_cert, root_privkey, GNUTLS_DIG_SHA1, 0);
  580. /* export to PEM format */
  581. size_t root_key_export_size = 0;
  582. size_t host_key_export_size = 0;
  583. gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, NULL, &root_key_export_size);
  584. gnutls_x509_privkey_export(host_privkey, GNUTLS_X509_FMT_PEM, NULL, &host_key_export_size);
  585. root_key_pem.data = gnutls_malloc(root_key_export_size);
  586. host_key_pem.data = gnutls_malloc(host_key_export_size);
  587. gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, root_key_pem.data, &root_key_export_size);
  588. root_key_pem.size = root_key_export_size;
  589. gnutls_x509_privkey_export(host_privkey, GNUTLS_X509_FMT_PEM, host_key_pem.data, &host_key_export_size);
  590. host_key_pem.size = host_key_export_size;
  591. size_t root_cert_export_size = 0;
  592. size_t host_cert_export_size = 0;
  593. gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, NULL, &root_cert_export_size);
  594. gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, NULL, &host_cert_export_size);
  595. root_cert_pem.data = gnutls_malloc(root_cert_export_size);
  596. host_cert_pem.data = gnutls_malloc(host_cert_export_size);
  597. gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, root_cert_pem.data, &root_cert_export_size);
  598. root_cert_pem.size = root_cert_export_size;
  599. gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size);
  600. host_cert_pem.size = host_cert_export_size;
  601. gnutls_datum_t modulus = { NULL, 0 };
  602. gnutls_datum_t exponent = { NULL, 0 };
  603. /* now decode the PEM encoded key */
  604. gnutls_datum_t der_pub_key = { NULL, 0 };
  605. int gnutls_error = gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &public_key, &der_pub_key);
  606. if (GNUTLS_E_SUCCESS == gnutls_error) {
  607. /* initalize asn.1 parser */
  608. ASN1_TYPE pkcs1 = ASN1_TYPE_EMPTY;
  609. if (ASN1_SUCCESS == asn1_array2tree(pkcs1_asn1_tab, &pkcs1, NULL)) {
  610. ASN1_TYPE asn1_pub_key = ASN1_TYPE_EMPTY;
  611. asn1_create_element(pkcs1, "PKCS1.RSAPublicKey", &asn1_pub_key);
  612. if (ASN1_SUCCESS == asn1_der_decoding(&asn1_pub_key, der_pub_key.data, der_pub_key.size, NULL)) {
  613. /* get size to read */
  614. int ret1 = asn1_read_value(asn1_pub_key, "modulus", NULL, (int*)&modulus.size);
  615. int ret2 = asn1_read_value(asn1_pub_key, "publicExponent", NULL, (int*)&exponent.size);
  616. modulus.data = gnutls_malloc(modulus.size);
  617. exponent.data = gnutls_malloc(exponent.size);
  618. ret1 = asn1_read_value(asn1_pub_key, "modulus", modulus.data, (int*)&modulus.size);
  619. ret2 = asn1_read_value(asn1_pub_key, "publicExponent", exponent.data, (int*)&exponent.size);
  620. if (ret1 != ASN1_SUCCESS || ret2 != ASN1_SUCCESS) {
  621. gnutls_free(modulus.data);
  622. modulus.data = NULL;
  623. modulus.size = 0;
  624. gnutls_free(exponent.data);
  625. exponent.data = NULL;
  626. exponent.size = 0;
  627. }
  628. }
  629. if (asn1_pub_key)
  630. asn1_delete_structure(&asn1_pub_key);
  631. }
  632. if (pkcs1)
  633. asn1_delete_structure(&pkcs1);
  634. } else {
  635. debug_info("ERROR: Could not parse public key: %s", gnutls_strerror(gnutls_error));
  636. }
  637. /* generate device certificate */
  638. if (modulus.data && 0 != modulus.size && exponent.data && 0 != exponent.size) {
  639. gnutls_datum_t prime_p = { (unsigned char*)"\x00\xca\x4a\x03\x13\xdf\x9d\x7a\xfd", 9 };
  640. gnutls_datum_t prime_q = { (unsigned char*)"\x00\xf2\xff\xe0\x15\xd1\x60\x37\x63", 9 };
  641. gnutls_datum_t coeff = { (unsigned char*)"\x32\x07\xf1\x68\x57\xdf\x9a\xf4", 8 };
  642. gnutls_x509_privkey_t fake_privkey;
  643. gnutls_x509_crt_t dev_cert;
  644. gnutls_x509_privkey_init(&fake_privkey);
  645. gnutls_x509_crt_init(&dev_cert);
  646. gnutls_error = gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &exponent, &prime_p, &prime_q, &coeff);
  647. if (GNUTLS_E_SUCCESS == gnutls_error) {
  648. /* now generate device certificate */
  649. gnutls_x509_crt_set_key(dev_cert, fake_privkey);
  650. gnutls_x509_crt_set_serial(dev_cert, "\x01", 1);
  651. gnutls_x509_crt_set_version(dev_cert, 3);
  652. gnutls_x509_crt_set_ca_status(dev_cert, 0);
  653. gnutls_x509_crt_set_activation_time(dev_cert, time(NULL));
  654. gnutls_x509_crt_set_expiration_time(dev_cert, time(NULL) + (60 * 60 * 24 * 365 * 10));
  655. /* use custom hash generation for compatibility with the "Apple ecosystem" */
  656. const gnutls_digest_algorithm_t dig_sha1 = GNUTLS_DIG_SHA1;
  657. size_t hash_size = gnutls_hash_get_len(dig_sha1);
  658. unsigned char hash[hash_size];
  659. if (gnutls_hash_fast(dig_sha1, der_pub_key.data, der_pub_key.size, (unsigned char*)&hash) < 0) {
  660. debug_info("ERROR: Failed to generate SHA1 for public key");
  661. } else {
  662. gnutls_x509_crt_set_subject_key_id(dev_cert, hash, hash_size);
  663. }
  664. gnutls_x509_crt_set_key_usage(dev_cert, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT);
  665. gnutls_error = gnutls_x509_crt_sign2(dev_cert, root_cert, root_privkey, GNUTLS_DIG_SHA1, 0);
  666. if (GNUTLS_E_SUCCESS == gnutls_error) {
  667. /* if everything went well, export in PEM format */
  668. size_t export_size = 0;
  669. gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &export_size);
  670. dev_cert_pem.data = gnutls_malloc(export_size);
  671. gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_cert_pem.data, &export_size);
  672. dev_cert_pem.size = export_size;
  673. } else {
  674. debug_info("ERROR: Signing device certificate with root private key failed: %s", gnutls_strerror(gnutls_error));
  675. }
  676. } else {
  677. debug_info("ERROR: Failed to import RSA key data: %s", gnutls_strerror(gnutls_error));
  678. }
  679. gnutls_x509_crt_deinit(dev_cert);
  680. gnutls_x509_privkey_deinit(fake_privkey);
  681. }
  682. gnutls_x509_crt_deinit(root_cert);
  683. gnutls_x509_crt_deinit(host_cert);
  684. gnutls_x509_privkey_deinit(root_privkey);
  685. gnutls_x509_privkey_deinit(host_privkey);
  686. gnutls_free(modulus.data);
  687. gnutls_free(exponent.data);
  688. gnutls_free(der_pub_key.data);
  689. #elif defined(HAVE_MBEDTLS)
  690. time_t now = time(NULL);
  691. struct tm* timestamp = gmtime(&now);
  692. char notbefore[16];
  693. strftime(notbefore, sizeof(notbefore), "%Y%m%d%H%M%S", timestamp);
  694. time_t then = now + 60 * 60 * 24 * 365 * 10;
  695. char notafter[16];
  696. timestamp = gmtime(&then);
  697. strftime(notafter, sizeof(notafter), "%Y%m%d%H%M%S", timestamp);
  698. mbedtls_mpi sn;
  699. mbedtls_mpi_init(&sn);
  700. mbedtls_mpi_lset(&sn, 1); /* 0 doesn't work, so we have to use 1 (like GnuTLS) */
  701. mbedtls_ctr_drbg_context ctr_drbg;
  702. mbedtls_ctr_drbg_init(&ctr_drbg);
  703. mbedtls_pk_context root_pkey;
  704. mbedtls_pk_init(&root_pkey);
  705. mbedtls_pk_context host_pkey;
  706. mbedtls_pk_init(&host_pkey);
  707. mbedtls_pk_context dev_public_key;
  708. mbedtls_pk_init(&dev_public_key);
  709. mbedtls_entropy_context entropy;
  710. mbedtls_entropy_init(&entropy);
  711. mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)"limd", 4);
  712. /* ----- root key & cert ----- */
  713. ret = mbedtls_pk_setup(&root_pkey, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
  714. if (ret != 0) {
  715. debug_info("mbedtls_pk_setup returned -0x%04x", -ret);
  716. goto cleanup;
  717. }
  718. ret = mbedtls_rsa_gen_key(mbedtls_pk_rsa(root_pkey), mbedtls_ctr_drbg_random, &ctr_drbg, 2048, 65537);
  719. if (ret != 0) {
  720. debug_info("mbedtls_rsa_gen_key returned -0x%04x", -ret);
  721. goto cleanup;
  722. }
  723. mbedtls_x509write_cert cert;
  724. mbedtls_x509write_crt_init(&cert);
  725. /* set serial number */
  726. mbedtls_x509write_crt_set_serial(&cert, &sn);
  727. /* set version */
  728. mbedtls_x509write_crt_set_version(&cert, 2);
  729. /* set x509v3 basic constraints */
  730. _mbedtls_x509write_crt_set_basic_constraints_critical(&cert, 1, -1);
  731. /* use root public key for root cert */
  732. mbedtls_x509write_crt_set_subject_key(&cert, &root_pkey);
  733. /* set x509v3 subject key identifier */
  734. mbedtls_x509write_crt_set_subject_key_identifier(&cert);
  735. /* set key validity */
  736. mbedtls_x509write_crt_set_validity(&cert, notbefore, notafter);
  737. /* sign root cert with root private key */
  738. mbedtls_x509write_crt_set_issuer_key(&cert, &root_pkey);
  739. mbedtls_x509write_crt_set_md_alg(&cert, MBEDTLS_MD_SHA1);
  740. unsigned char outbuf[16384];
  741. /* write root private key */
  742. mbedtls_pk_write_key_pem(&root_pkey, outbuf, sizeof(outbuf));
  743. root_key_pem.size = strlen((const char*)outbuf);
  744. root_key_pem.data = malloc(root_key_pem.size+1);
  745. memcpy(root_key_pem.data, outbuf, root_key_pem.size);
  746. root_key_pem.data[root_key_pem.size] = '\0';
  747. /* write root certificate */
  748. mbedtls_x509write_crt_pem(&cert, outbuf, sizeof(outbuf), mbedtls_ctr_drbg_random, &ctr_drbg);
  749. root_cert_pem.size = strlen((const char*)outbuf);
  750. root_cert_pem.data = malloc(root_cert_pem.size+1);
  751. memcpy(root_cert_pem.data, outbuf, root_cert_pem.size);
  752. root_cert_pem.data[root_cert_pem.size] = '\0';
  753. mbedtls_x509write_crt_free(&cert);
  754. /* ----- host key & cert ----- */
  755. ret = mbedtls_pk_setup(&host_pkey, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
  756. if (ret != 0) {
  757. debug_info("mbedtls_pk_setup returned -0x%04x", -ret);
  758. goto cleanup;
  759. }
  760. ret = mbedtls_rsa_gen_key(mbedtls_pk_rsa(host_pkey), mbedtls_ctr_drbg_random, &ctr_drbg, 2048, 65537);
  761. if (ret != 0) {
  762. debug_info("mbedtls_rsa_gen_key returned -0x%04x", -ret);
  763. goto cleanup;
  764. }
  765. mbedtls_x509write_crt_init(&cert);
  766. /* set serial number */
  767. mbedtls_x509write_crt_set_serial(&cert, &sn);
  768. /* set version */
  769. mbedtls_x509write_crt_set_version(&cert, 2);
  770. /* set x509v3 basic constraints */
  771. _mbedtls_x509write_crt_set_basic_constraints_critical(&cert, 0, -1);
  772. /* use host public key for host cert */
  773. mbedtls_x509write_crt_set_subject_key(&cert, &host_pkey);
  774. /* set x509v3 subject key identifier */
  775. mbedtls_x509write_crt_set_subject_key_identifier(&cert);
  776. /* set x509v3 key usage */
  777. mbedtls_x509write_crt_set_key_usage(&cert, MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_ENCIPHERMENT);
  778. /* set key validity */
  779. mbedtls_x509write_crt_set_validity(&cert, notbefore, notafter);
  780. /* sign host cert with root private key */
  781. mbedtls_x509write_crt_set_issuer_key(&cert, &root_pkey);
  782. mbedtls_x509write_crt_set_md_alg(&cert, MBEDTLS_MD_SHA1);
  783. /* write host private key */
  784. mbedtls_pk_write_key_pem(&host_pkey, outbuf, sizeof(outbuf));
  785. host_key_pem.size = strlen((const char*)outbuf);
  786. host_key_pem.data = malloc(host_key_pem.size+1);
  787. memcpy(host_key_pem.data, outbuf, host_key_pem.size);
  788. host_key_pem.data[host_key_pem.size] = '\0';
  789. /* write host certificate */
  790. mbedtls_x509write_crt_pem(&cert, outbuf, sizeof(outbuf), mbedtls_ctr_drbg_random, &ctr_drbg);
  791. host_cert_pem.size = strlen((const char*)outbuf);
  792. host_cert_pem.data = malloc(host_cert_pem.size+1);
  793. memcpy(host_cert_pem.data, outbuf, host_cert_pem.size);
  794. host_cert_pem.data[host_cert_pem.size] = '\0';
  795. mbedtls_x509write_crt_free(&cert);
  796. /* ----- device certificate ----- */
  797. unsigned char* pubkey_data = malloc(public_key.size+1);
  798. if (!pubkey_data) {
  799. debug_info("malloc() failed\n");
  800. goto cleanup;
  801. }
  802. memcpy(pubkey_data, public_key.data, public_key.size);
  803. pubkey_data[public_key.size] = '\0';
  804. int pr = mbedtls_pk_parse_public_key(&dev_public_key, pubkey_data, public_key.size+1);
  805. free(pubkey_data);
  806. if (pr != 0) {
  807. debug_info("Failed to read device public key: -0x%x\n", -pr);
  808. goto cleanup;
  809. }
  810. mbedtls_x509write_crt_init(&cert);
  811. /* set serial number */
  812. mbedtls_x509write_crt_set_serial(&cert, &sn);
  813. /* set version */
  814. mbedtls_x509write_crt_set_version(&cert, 2);
  815. /* set x509v3 basic constraints */
  816. _mbedtls_x509write_crt_set_basic_constraints_critical(&cert, 0, -1);
  817. /* use root public key for dev cert subject key */
  818. mbedtls_x509write_crt_set_subject_key(&cert, &dev_public_key);
  819. /* set x509v3 subject key identifier */
  820. mbedtls_x509write_crt_set_subject_key_identifier(&cert);
  821. /* set x509v3 key usage */
  822. mbedtls_x509write_crt_set_key_usage(&cert, MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_ENCIPHERMENT);
  823. /* set key validity */
  824. mbedtls_x509write_crt_set_validity(&cert, notbefore, notafter);
  825. /* sign device certificate with root private key */
  826. mbedtls_x509write_crt_set_issuer_key(&cert, &root_pkey);
  827. mbedtls_x509write_crt_set_md_alg(&cert, MBEDTLS_MD_SHA1);
  828. /* write device certificate */
  829. mbedtls_x509write_crt_pem(&cert, outbuf, sizeof(outbuf), mbedtls_ctr_drbg_random, &ctr_drbg);
  830. dev_cert_pem.size = strlen((const char*)outbuf);
  831. dev_cert_pem.data = malloc(dev_cert_pem.size+1);
  832. memcpy(dev_cert_pem.data, outbuf, dev_cert_pem.size);
  833. dev_cert_pem.data[dev_cert_pem.size] = '\0';
  834. mbedtls_x509write_crt_free(&cert);
  835. /* cleanup */
  836. cleanup:
  837. mbedtls_mpi_free(&sn);
  838. mbedtls_pk_free(&dev_public_key);
  839. mbedtls_entropy_free(&entropy);
  840. mbedtls_pk_free(&host_pkey);
  841. mbedtls_pk_free(&root_pkey);
  842. mbedtls_ctr_drbg_free(&ctr_drbg);
  843. #endif
  844. /* make sure that we have all we need */
  845. if (root_cert_pem.data && 0 != root_cert_pem.size
  846. && root_key_pem.data && 0 != root_key_pem.size
  847. && host_cert_pem.data && 0 != host_cert_pem.size
  848. && host_key_pem.data && 0 != host_key_pem.size
  849. && dev_cert_pem.data && 0 != dev_cert_pem.size) {
  850. /* now set keys and certificates */
  851. pair_record_set_item_from_key_data(pair_record, USERPREF_DEVICE_CERTIFICATE_KEY, &dev_cert_pem);
  852. pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, &host_key_pem);
  853. pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_CERTIFICATE_KEY, &host_cert_pem);
  854. pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_key_pem);
  855. pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert_pem);
  856. ret = USERPREF_E_SUCCESS;
  857. }
  858. free(dev_cert_pem.data);
  859. free(root_key_pem.data);
  860. free(root_cert_pem.data);
  861. free(host_key_pem.data);
  862. free(host_cert_pem.data);
  863. return ret;
  864. }
  865. /**
  866. * Private function which import the given key into a gnutls structure.
  867. *
  868. * @param name The name of the private key to import.
  869. * @param key the gnutls key structure.
  870. *
  871. * @return 1 if the key was successfully imported.
  872. */
  873. #if defined(HAVE_OPENSSL) || defined(HAVE_MBEDTLS)
  874. userpref_error_t pair_record_import_key_with_name(plist_t pair_record, const char* name, key_data_t* key)
  875. #elif defined(HAVE_GNUTLS)
  876. userpref_error_t pair_record_import_key_with_name(plist_t pair_record, const char* name, gnutls_x509_privkey_t key)
  877. #endif
  878. {
  879. #if defined(HAVE_OPENSSL) || defined(HAVE_MBEDTLS)
  880. if (!key)
  881. return USERPREF_E_SUCCESS;
  882. #endif
  883. userpref_error_t ret = USERPREF_E_INVALID_CONF;
  884. #if defined(HAVE_OPENSSL) || defined(HAVE_MBEDTLS)
  885. ret = pair_record_get_item_as_key_data(pair_record, name, key);
  886. #elif defined(HAVE_GNUTLS)
  887. key_data_t pem = { NULL, 0 };
  888. ret = pair_record_get_item_as_key_data(pair_record, name, &pem);
  889. if (ret == USERPREF_E_SUCCESS && GNUTLS_E_SUCCESS == gnutls_x509_privkey_import(key, &pem, GNUTLS_X509_FMT_PEM))
  890. ret = USERPREF_E_SUCCESS;
  891. else
  892. ret = USERPREF_E_SSL_ERROR;
  893. if (pem.data)
  894. free(pem.data);
  895. #endif
  896. return ret;
  897. }
  898. /**
  899. * Private function which import the given certificate into a gnutls structure.
  900. *
  901. * @param name The name of the certificate to import.
  902. * @param cert the gnutls certificate structure.
  903. *
  904. * @return IDEVICE_E_SUCCESS if the certificate was successfully imported.
  905. */
  906. #if defined(HAVE_OPENSSL) || defined(HAVE_MBEDTLS)
  907. userpref_error_t pair_record_import_crt_with_name(plist_t pair_record, const char* name, key_data_t* cert)
  908. #else
  909. userpref_error_t pair_record_import_crt_with_name(plist_t pair_record, const char* name, gnutls_x509_crt_t cert)
  910. #endif
  911. {
  912. #if defined(HAVE_OPENSSL) || defined(HAVE_MBEDTLS)
  913. if (!cert)
  914. return USERPREF_E_SUCCESS;
  915. #endif
  916. userpref_error_t ret = USERPREF_E_INVALID_CONF;
  917. #if defined(HAVE_OPENSSL) || defined(HAVE_MBEDTLS)
  918. ret = pair_record_get_item_as_key_data(pair_record, name, cert);
  919. #elif defined(HAVE_GNUTLS)
  920. key_data_t pem = { NULL, 0 };
  921. ret = pair_record_get_item_as_key_data(pair_record, name, &pem);
  922. if (ret == USERPREF_E_SUCCESS && GNUTLS_E_SUCCESS == gnutls_x509_crt_import(cert, &pem, GNUTLS_X509_FMT_PEM))
  923. ret = USERPREF_E_SUCCESS;
  924. else
  925. ret = USERPREF_E_SSL_ERROR;
  926. if (pem.data)
  927. free(pem.data);
  928. #endif
  929. return ret;
  930. }
  931. userpref_error_t pair_record_get_host_id(plist_t pair_record, char** host_id)
  932. {
  933. plist_t node = plist_dict_get_item(pair_record, USERPREF_HOST_ID_KEY);
  934. if (node && plist_get_node_type(node) == PLIST_STRING) {
  935. plist_get_string_val(node, host_id);
  936. }
  937. return USERPREF_E_SUCCESS;
  938. }
  939. userpref_error_t pair_record_set_host_id(plist_t pair_record, const char* host_id)
  940. {
  941. plist_dict_set_item(pair_record, USERPREF_HOST_ID_KEY, plist_new_string(host_id));
  942. return USERPREF_E_SUCCESS;
  943. }
  944. userpref_error_t pair_record_get_item_as_key_data(plist_t pair_record, const char* name, key_data_t *value)
  945. {
  946. if (!pair_record || !value)
  947. return USERPREF_E_INVALID_ARG;
  948. userpref_error_t ret = USERPREF_E_SUCCESS;
  949. char* buffer = NULL;
  950. uint64_t length = 0;
  951. plist_t node = plist_dict_get_item(pair_record, name);
  952. if (node && plist_get_node_type(node) == PLIST_DATA) {
  953. plist_get_data_val(node, &buffer, &length);
  954. value->data = (unsigned char*)malloc(length+1);
  955. memcpy(value->data, buffer, length);
  956. value->data[length] = '\0';
  957. value->size = length+1;
  958. free(buffer);
  959. buffer = NULL;
  960. } else {
  961. ret = USERPREF_E_INVALID_CONF;
  962. }
  963. if (buffer)
  964. free(buffer);
  965. return ret;
  966. }
  967. userpref_error_t pair_record_set_item_from_key_data(plist_t pair_record, const char* name, key_data_t *value)
  968. {
  969. userpref_error_t ret = USERPREF_E_SUCCESS;
  970. if (!pair_record || !value) {
  971. return USERPREF_E_INVALID_ARG;
  972. }
  973. /* set new item */
  974. plist_dict_set_item(pair_record, name, plist_new_data((char*)value->data, value->size));
  975. return ret;
  976. }