summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2014-03-21 18:14:15 +0100
committerGravatar Nikias Bassen2014-03-21 18:14:15 +0100
commit03ad1dc56830bd6e921e58ecce2b8b0fd3aea675 (patch)
treee8d806acde618ba817a165b14943dd1ffec47256
parent1a0ce00184f560556d5e823dc8b1258a79ed5aaa (diff)
downloadlibimobiledevice-03ad1dc56830bd6e921e58ecce2b8b0fd3aea675.tar.gz
libimobiledevice-03ad1dc56830bd6e921e58ecce2b8b0fd3aea675.tar.bz2
userpref: merge pair_record_generate_from_device_public_key() into pair_record_generate_keys_and_certs()
-rw-r--r--common/userpref.c387
-rw-r--r--common/userpref.h3
-rw-r--r--src/lockdown.c16
3 files changed, 140 insertions, 266 deletions
diff --git a/common/userpref.c b/common/userpref.c
index 5a00d28..cb74945 100644
--- a/common/userpref.c
+++ b/common/userpref.c
@@ -43,8 +43,10 @@
43#include <openssl/x509v3.h> 43#include <openssl/x509v3.h>
44#else 44#else
45#include <gnutls/gnutls.h> 45#include <gnutls/gnutls.h>
46#include <gnutls/crypto.h>
46#include <gnutls/x509.h> 47#include <gnutls/x509.h>
47#include <gcrypt.h> 48#include <gcrypt.h>
49#include <libtasn1.h>
48#endif 50#endif
49 51
50#include <dirent.h> 52#include <dirent.h>
@@ -389,19 +391,27 @@ static int X509_add_ext_helper(X509 *cert, int nid, char *value)
389#endif 391#endif
390 392
391/** 393/**
392 * Private function which generate private keys and certificates. 394 * Private function to generate required private keys and certificates.
395 *
396 * @param pair_record a #PLIST_DICT that will be filled with the keys
397 * and certificates
398 * @param public_key the public key to use (device public key)
393 * 399 *
394 * @return 1 if keys were successfully generated, 0 otherwise 400 * @return 1 if keys were successfully generated, 0 otherwise
395 */ 401 */
396userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record) 402userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_data_t public_key)
397{ 403{
398 userpref_error_t ret = USERPREF_E_SSL_ERROR; 404 userpref_error_t ret = USERPREF_E_SSL_ERROR;
399 405
406 key_data_t dev_cert_pem = { NULL, 0 };
400 key_data_t root_key_pem = { NULL, 0 }; 407 key_data_t root_key_pem = { NULL, 0 };
401 key_data_t root_cert_pem = { NULL, 0 }; 408 key_data_t root_cert_pem = { NULL, 0 };
402 key_data_t host_key_pem = { NULL, 0 }; 409 key_data_t host_key_pem = { NULL, 0 };
403 key_data_t host_cert_pem = { NULL, 0 }; 410 key_data_t host_cert_pem = { NULL, 0 };
404 411
412 if (!pair_record || !public_key.data)
413 return USERPREF_E_INVALID_ARG;
414
405 debug_info("Generating keys and certificates..."); 415 debug_info("Generating keys and certificates...");
406 416
407#ifdef HAVE_OPENSSL 417#ifdef HAVE_OPENSSL
@@ -531,6 +541,63 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record)
531 } 541 }
532 } 542 }
533 543
544 RSA *pubkey = NULL;
545 {
546 BIO *membp = BIO_new_mem_buf(public_key.data, public_key.size);
547 if (!PEM_read_bio_RSAPublicKey(membp, &pubkey, NULL, NULL)) {
548 debug_info("Could not read public key");
549 }
550 BIO_free(membp);
551 }
552
553 X509* dev_cert = X509_new();
554 if (pubkey && dev_cert) {
555 /* generate device certificate */
556 ASN1_INTEGER* sn = ASN1_INTEGER_new();
557 ASN1_INTEGER_set(sn, 0);
558 X509_set_serialNumber(dev_cert, sn);
559 ASN1_INTEGER_free(sn);
560 X509_set_version(dev_cert, 2);
561
562 X509_add_ext_helper(dev_cert, NID_basic_constraints, (char*)"critical,CA:FALSE");
563
564 ASN1_TIME* asn1time = ASN1_TIME_new();
565 ASN1_TIME_set(asn1time, time(NULL));
566 X509_set_notBefore(dev_cert, asn1time);
567 ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10));
568 X509_set_notAfter(dev_cert, asn1time);
569 ASN1_TIME_free(asn1time);
570
571 EVP_PKEY* pkey = EVP_PKEY_new();
572 EVP_PKEY_assign_RSA(pkey, pubkey);
573 X509_set_pubkey(dev_cert, pkey);
574 EVP_PKEY_free(pkey);
575
576 X509_add_ext_helper(dev_cert, NID_subject_key_identifier, (char*)"hash");
577 X509_add_ext_helper(dev_cert, NID_key_usage, (char*)"critical,digitalSignature,keyEncipherment");
578
579 /* sign device certificate with root private key */
580 if (X509_sign(dev_cert, root_pkey, EVP_sha1())) {
581 /* if signing succeeded, export in PEM format */
582 BIO* membp = BIO_new(BIO_s_mem());
583 if (PEM_write_bio_X509(membp, dev_cert) > 0) {
584 char *bdata = NULL;
585 dev_cert_pem.size = BIO_get_mem_data(membp, &bdata);
586 dev_cert_pem.data = (unsigned char*)malloc(dev_cert_pem.size);
587 if (dev_cert_pem.data) {
588 memcpy(dev_cert_pem.data, bdata, dev_cert_pem.size);
589 }
590 BIO_free(membp);
591 membp = NULL;
592 }
593 } else {
594 debug_info("ERROR: Signing device certificate with root private key failed!");
595 }
596 }
597
598 X509V3_EXT_cleanup();
599 X509_free(dev_cert);
600
534 EVP_PKEY_free(root_pkey); 601 EVP_PKEY_free(root_pkey);
535 EVP_PKEY_free(host_pkey); 602 EVP_PKEY_free(host_pkey);
536 603
@@ -605,175 +672,8 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record)
605 gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size); 672 gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size);
606 host_cert_pem.size = host_cert_export_size; 673 host_cert_pem.size = host_cert_export_size;
607 674
608 /* restore gnutls env */ 675 ret = USERPREF_E_UNKNOWN_ERROR;
609 gnutls_global_deinit();
610 gnutls_global_init();
611#endif
612 if (NULL != root_cert_pem.data && 0 != root_cert_pem.size &&
613 NULL != host_cert_pem.data && 0 != host_cert_pem.size)
614 ret = USERPREF_E_SUCCESS;
615
616 /* now set keys and certificates */
617 pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, &host_key_pem);
618 pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_CERTIFICATE_KEY, &host_cert_pem);
619 pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_key_pem);
620 pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert_pem);
621
622 if (root_key_pem.data)
623 free(root_key_pem.data);
624 if (root_cert_pem.data)
625 free(root_cert_pem.data);
626 if (host_key_pem.data)
627 free(host_key_pem.data);
628 if (host_cert_pem.data)
629 free(host_cert_pem.data);
630
631 return ret;
632}
633
634/**
635 * Generates the device certificate from the public key as well as the host
636 * and root certificates.
637 *
638 * @param pair_record The pair record to use for lookup of key pairs
639 * @param public_key The public key of the device to use for generation.
640 *
641 * @return USERPREF_E_SUCCESS on success, USERPREF_E_INVALID_ARG when a
642 * parameter is NULL, USERPREF_E_INVALID_CONF if the internal configuration
643 * system failed, USERPREF_E_SSL_ERROR if the certificates could not be
644 * generated
645 */
646userpref_error_t pair_record_generate_from_device_public_key(plist_t pair_record, key_data_t public_key)
647{
648 if (!pair_record || !public_key.data)
649 return USERPREF_E_INVALID_ARG;
650
651 userpref_error_t uret = USERPREF_E_UNKNOWN_ERROR;
652
653#ifdef HAVE_OPENSSL
654 BIO *membio = BIO_new_mem_buf(public_key.data, public_key.size);
655 RSA *pubkey = NULL;
656 if (!PEM_read_bio_RSAPublicKey(membio, &pubkey, NULL, NULL)) {
657 debug_info("Could not read public key");
658 }
659 BIO_free(membio);
660
661 /* now generate certificates */
662 key_data_t root_privkey, host_privkey;
663 key_data_t root_cert, host_cert;
664
665 X509* dev_cert = X509_new();
666
667 root_cert.data = NULL;
668 root_cert.size = 0;
669 host_cert.data = NULL;
670 host_cert.size = 0;
671
672 root_privkey.data = NULL;
673 root_privkey.size = 0;
674 host_privkey.data = NULL;
675 host_privkey.size = 0;
676
677 uret = pair_record_import_crt_with_name(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert);
678 uret = pair_record_import_crt_with_name(pair_record, USERPREF_HOST_CERTIFICATE_KEY, &host_cert);
679 uret = pair_record_import_key_with_name(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_privkey);
680 uret = pair_record_import_key_with_name(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, &host_privkey);
681
682 if (USERPREF_E_SUCCESS == uret) {
683 /* generate device certificate */
684 ASN1_INTEGER* sn = ASN1_INTEGER_new();
685 ASN1_INTEGER_set(sn, 0);
686 X509_set_serialNumber(dev_cert, sn);
687 ASN1_INTEGER_free(sn);
688 X509_set_version(dev_cert, 2);
689
690 X509_add_ext_helper(dev_cert, NID_basic_constraints, (char*)"critical,CA:FALSE");
691
692 ASN1_TIME* asn1time = ASN1_TIME_new();
693 ASN1_TIME_set(asn1time, time(NULL));
694 X509_set_notBefore(dev_cert, asn1time);
695 ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10));
696 X509_set_notAfter(dev_cert, asn1time);
697 ASN1_TIME_free(asn1time);
698
699 /* read root certificate */
700 BIO* membp;
701 X509* rootCert = NULL;
702 membp = BIO_new_mem_buf(root_cert.data, root_cert.size);
703 PEM_read_bio_X509(membp, &rootCert, NULL, NULL);
704 BIO_free(membp);
705 if (!rootCert) {
706 debug_info("Could not read RootCertificate");
707 } else {
708 debug_info("RootCertificate loaded");
709 EVP_PKEY* pkey = EVP_PKEY_new();
710 EVP_PKEY_assign_RSA(pkey, pubkey);
711 X509_set_pubkey(dev_cert, pkey);
712 EVP_PKEY_free(pkey);
713 X509_free(rootCert);
714 }
715
716 X509_add_ext_helper(dev_cert, NID_subject_key_identifier, (char*)"hash");
717 X509_add_ext_helper(dev_cert, NID_key_usage, (char*)"critical,digitalSignature,keyEncipherment");
718 676
719 /* read root private key */
720 EVP_PKEY* rootPriv = NULL;
721 membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size);
722 PEM_read_bio_PrivateKey(membp, &rootPriv, NULL, NULL);
723 BIO_free(membp);
724 if (!rootPriv) {
725 debug_info("Could not read RootPrivateKey");
726 } else {
727 debug_info("RootPrivateKey loaded");
728 if (X509_sign(dev_cert, rootPriv, EVP_sha1())) {
729 uret = USERPREF_E_SUCCESS;
730 } else {
731 debug_info("signing failed");
732 }
733 EVP_PKEY_free(rootPriv);
734 }
735
736 if (USERPREF_E_SUCCESS == uret) {
737 /* if everything went well, export in PEM format */
738 key_data_t pem_root_cert = { NULL, 0 };
739 key_data_t pem_host_cert = { NULL, 0 };
740
741 uret = pair_record_import_crt_with_name(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &pem_root_cert);
742 uret = pair_record_import_crt_with_name(pair_record, USERPREF_HOST_CERTIFICATE_KEY, &pem_host_cert);
743
744 if (USERPREF_E_SUCCESS == uret) {
745 /* set new keys and certs in pair record */
746 membp = BIO_new(BIO_s_mem());
747 if (membp && PEM_write_bio_X509(membp, dev_cert) > 0) {
748 void *datap;
749 int size = BIO_get_mem_data(membp, &datap);
750 plist_dict_set_item(pair_record, USERPREF_DEVICE_CERTIFICATE_KEY, plist_new_data(datap, size));
751 }
752 if (membp)
753 BIO_free(membp);
754
755 plist_dict_set_item(pair_record, USERPREF_HOST_CERTIFICATE_KEY, plist_new_data((char*)pem_host_cert.data, pem_host_cert.size));
756 plist_dict_set_item(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, plist_new_data((char*)pem_root_cert.data, pem_root_cert.size));
757 plist_dict_set_item(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, plist_new_data((char*)root_privkey.data, root_privkey.size));
758 plist_dict_set_item(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, plist_new_data((char*)host_privkey.data, host_privkey.size));
759
760 free(pem_root_cert.data);
761 free(pem_host_cert.data);
762 }
763 }
764 }
765 X509V3_EXT_cleanup();
766 X509_free(dev_cert);
767
768 if (root_cert.data)
769 free(root_cert.data);
770 if (host_cert.data)
771 free(host_cert.data);
772 if (root_privkey.data)
773 free(root_privkey.data);
774 if (host_privkey.data)
775 free(host_privkey.data);
776#else
777 gnutls_datum_t modulus = { NULL, 0 }; 677 gnutls_datum_t modulus = { NULL, 0 };
778 gnutls_datum_t exponent = { NULL, 0 }; 678 gnutls_datum_t exponent = { NULL, 0 };
779 679
@@ -800,7 +700,7 @@ userpref_error_t pair_record_generate_from_device_public_key(plist_t pair_record
800 ret1 = asn1_read_value(asn1_pub_key, "modulus", modulus.data, (int*)&modulus.size); 700 ret1 = asn1_read_value(asn1_pub_key, "modulus", modulus.data, (int*)&modulus.size);
801 ret2 = asn1_read_value(asn1_pub_key, "publicExponent", exponent.data, (int*)&exponent.size); 701 ret2 = asn1_read_value(asn1_pub_key, "publicExponent", exponent.data, (int*)&exponent.size);
802 if (ASN1_SUCCESS == ret1 && ASN1_SUCCESS == ret2) 702 if (ASN1_SUCCESS == ret1 && ASN1_SUCCESS == ret2)
803 uret = USERPREF_E_SUCCESS; 703 ret = USERPREF_E_SUCCESS;
804 } 704 }
805 if (asn1_pub_key) 705 if (asn1_pub_key)
806 asn1_delete_structure(&asn1_pub_key); 706 asn1_delete_structure(&asn1_pub_key);
@@ -810,83 +710,45 @@ userpref_error_t pair_record_generate_from_device_public_key(plist_t pair_record
810 } 710 }
811 711
812 /* now generate certificates */ 712 /* now generate certificates */
813 if (USERPREF_E_SUCCESS == uret && 0 != modulus.size && 0 != exponent.size) { 713 if (USERPREF_E_SUCCESS == ret && 0 != modulus.size && 0 != exponent.size) {
814
815 gnutls_global_init();
816 gnutls_datum_t essentially_null = { (unsigned char*)strdup("abababababababab"), strlen("abababababababab") }; 714 gnutls_datum_t essentially_null = { (unsigned char*)strdup("abababababababab"), strlen("abababababababab") };
817 715
818 gnutls_x509_privkey_t fake_privkey, root_privkey, host_privkey; 716 gnutls_x509_privkey_t fake_privkey;
819 gnutls_x509_crt_t dev_cert, root_cert, host_cert; 717 gnutls_x509_crt_t dev_cert;
820 718
821 gnutls_x509_privkey_init(&fake_privkey); 719 gnutls_x509_privkey_init(&fake_privkey);
822 gnutls_x509_privkey_init(&root_privkey);
823 gnutls_x509_privkey_init(&host_privkey);
824
825 gnutls_x509_crt_init(&dev_cert); 720 gnutls_x509_crt_init(&dev_cert);
826 gnutls_x509_crt_init(&root_cert);
827 gnutls_x509_crt_init(&host_cert);
828
829 if (GNUTLS_E_SUCCESS ==
830 gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &essentially_null, &essentially_null,
831 &essentially_null, &essentially_null)) {
832
833 uret = pair_record_import_crt_with_name(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, root_cert);
834 uret = pair_record_import_crt_with_name(pair_record, USERPREF_HOST_CERTIFICATE_KEY, host_cert);
835 uret = pair_record_import_key_with_name(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, root_privkey);
836 uret = pair_record_import_key_with_name(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, host_privkey);
837
838 if (USERPREF_E_SUCCESS == uret) {
839 /* generate device certificate */
840 gnutls_x509_crt_set_key(dev_cert, fake_privkey);
841 gnutls_x509_crt_set_serial(dev_cert, "\x00", 1);
842 gnutls_x509_crt_set_version(dev_cert, 3);
843 gnutls_x509_crt_set_ca_status(dev_cert, 0);
844 gnutls_x509_crt_set_activation_time(dev_cert, time(NULL));
845 gnutls_x509_crt_set_expiration_time(dev_cert, time(NULL) + (60 * 60 * 24 * 365 * 10));
846
847 /* use custom hash generation for compatibility with the "Apple ecosystem" */
848 const gnutls_digest_algorithm_t dig_sha1 = GNUTLS_DIG_SHA1;
849 size_t hash_size = gnutls_hash_get_len(dig_sha1);
850 unsigned char hash[hash_size];
851 if (gnutls_hash_fast(dig_sha1, der_pub_key.data, der_pub_key.size, (unsigned char*)&hash) < 0) {
852 debug_info("ERROR: Failed to generate SHA1 for public key");
853 } else {
854 gnutls_x509_crt_set_subject_key_id(dev_cert, hash, hash_size);
855 }
856 721
857 gnutls_x509_crt_set_key_usage(dev_cert, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT); 722 if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &essentially_null, &essentially_null, &essentially_null, &essentially_null)) {
858 gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey); 723 /* generate device certificate */
859 724 gnutls_x509_crt_set_key(dev_cert, fake_privkey);
860 if (LOCKDOWN_E_SUCCESS == ret) { 725 gnutls_x509_crt_set_serial(dev_cert, "\x00", 1);
861 /* if everything went well, export in PEM format */ 726 gnutls_x509_crt_set_version(dev_cert, 3);
862 size_t export_size = 0; 727 gnutls_x509_crt_set_ca_status(dev_cert, 0);
863 gnutls_datum_t dev_pem = { NULL, 0 }; 728 gnutls_x509_crt_set_activation_time(dev_cert, time(NULL));
864 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &export_size); 729 gnutls_x509_crt_set_expiration_time(dev_cert, time(NULL) + (60 * 60 * 24 * 365 * 10));
865 dev_pem.data = gnutls_malloc(export_size); 730
866 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_pem.data, &export_size); 731 /* use custom hash generation for compatibility with the "Apple ecosystem" */
867 dev_pem.size = export_size; 732 const gnutls_digest_algorithm_t dig_sha1 = GNUTLS_DIG_SHA1;
868 733 size_t hash_size = gnutls_hash_get_len(dig_sha1);
869 gnutls_datum_t pem_root_cert = { NULL, 0 }; 734 unsigned char hash[hash_size];
870 gnutls_datum_t pem_host_cert = { NULL, 0 }; 735 if (gnutls_hash_fast(dig_sha1, der_pub_key.data, der_pub_key.size, (unsigned char*)&hash) < 0) {
871 736 debug_info("ERROR: Failed to generate SHA1 for public key");
872 uret = pair_record_import_crt_with_name(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &pem_root_cert); 737 } else {
873 uret = pair_record_import_crt_with_name(pair_record, USERPREF_HOST_CERTIFICATE_KEY, &pem_host_cert); 738 gnutls_x509_crt_set_subject_key_id(dev_cert, hash, hash_size);
874 739 }
875 if (USERPREF_E_SUCCESS == uret) { 740
876 /* set new keys and certs in pair record */ 741 gnutls_x509_crt_set_key_usage(dev_cert, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT);
877 plist_dict_set_item(pair_record, USERPREF_DEVICE_CERTIFICATE_KEY, plist_new_data(dev_pem.data, dev_pem.size)); 742 gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey);
878 plist_dict_set_item(pair_record, USERPREF_HOST_CERTIFICATE_KEY, plist_new_data(pem_host_cert.data, pem_host_cert.size)); 743
879 plist_dict_set_item(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, plist_new_data(pem_root_cert.data, pem_root_cert.size)); 744 if (USERPREF_E_SUCCESS == ret) {
880 plist_dict_set_item(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, plist_new_data(root_privkey.data, root_privkey.size)); 745 /* if everything went well, export in PEM format */
881 plist_dict_set_item(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, plist_new_data(host_privkey.data, host_privkey.size)); 746 size_t export_size = 0;
882 747 gnutls_datum_t dev_pem = { NULL, 0 };
883 gnutls_free(pem_root_cert.data); 748 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &export_size);
884 gnutls_free(pem_host_cert.data); 749 dev_pem.data = gnutls_malloc(export_size);
885 750 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_pem.data, &export_size);
886 if (dev_pem.data) 751 dev_pem.size = export_size;
887 gnutls_free(dev_pem.data);
888 }
889 }
890 } 752 }
891 } 753 }
892 754
@@ -894,19 +756,46 @@ userpref_error_t pair_record_generate_from_device_public_key(plist_t pair_record
894 free(essentially_null.data); 756 free(essentially_null.data);
895 757
896 gnutls_x509_crt_deinit(dev_cert); 758 gnutls_x509_crt_deinit(dev_cert);
897 gnutls_x509_crt_deinit(root_cert);
898 gnutls_x509_crt_deinit(host_cert);
899 gnutls_x509_privkey_deinit(fake_privkey); 759 gnutls_x509_privkey_deinit(fake_privkey);
900 gnutls_x509_privkey_deinit(root_privkey);
901 gnutls_x509_privkey_deinit(host_privkey);
902 } 760 }
903 761
762 gnutls_x509_crt_deinit(root_cert);
763 gnutls_x509_crt_deinit(host_cert);
764 gnutls_x509_privkey_deinit(root_privkey);
765 gnutls_x509_privkey_deinit(host_privkey);
766
904 gnutls_free(modulus.data); 767 gnutls_free(modulus.data);
905 gnutls_free(exponent.data); 768 gnutls_free(exponent.data);
906 769
907 gnutls_free(der_pub_key.data); 770 gnutls_free(der_pub_key.data);
771
772 /* restore gnutls env */
773 gnutls_global_deinit();
774 gnutls_global_init();
908#endif 775#endif
909 return uret; 776 if (NULL != root_cert_pem.data && 0 != root_cert_pem.size &&
777 NULL != host_cert_pem.data && 0 != host_cert_pem.size)
778 ret = USERPREF_E_SUCCESS;
779
780 /* now set keys and certificates */
781 pair_record_set_item_from_key_data(pair_record, USERPREF_DEVICE_CERTIFICATE_KEY, &dev_cert_pem);
782 pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, &host_key_pem);
783 pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_CERTIFICATE_KEY, &host_cert_pem);
784 pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_key_pem);
785 pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert_pem);
786
787 if (dev_cert_pem.data)
788 free(dev_cert_pem.data);
789 if (root_key_pem.data)
790 free(root_key_pem.data);
791 if (root_cert_pem.data)
792 free(root_cert_pem.data);
793 if (host_key_pem.data)
794 free(host_key_pem.data);
795 if (host_cert_pem.data)
796 free(host_cert_pem.data);
797
798 return ret;
910} 799}
911 800
912/** 801/**
@@ -933,7 +822,7 @@ userpref_error_t pair_record_import_key_with_name(plist_t pair_record, const cha
933 ret = pair_record_get_item_as_key_data(pair_record, name, key); 822 ret = pair_record_get_item_as_key_data(pair_record, name, key);
934#else 823#else
935 key_data_t pem = { NULL, 0 }; 824 key_data_t pem = { NULL, 0 };
936 ret = pair_record_get_item_as_key_data(pair_record, name, pem); 825 ret = pair_record_get_item_as_key_data(pair_record, name, &pem);
937 if (ret == USERPREF_E_SUCCESS && GNUTLS_E_SUCCESS == gnutls_x509_privkey_import(key, &pem, GNUTLS_X509_FMT_PEM)) 826 if (ret == USERPREF_E_SUCCESS && GNUTLS_E_SUCCESS == gnutls_x509_privkey_import(key, &pem, GNUTLS_X509_FMT_PEM))
938 ret = USERPREF_E_SUCCESS; 827 ret = USERPREF_E_SUCCESS;
939 else 828 else
@@ -970,7 +859,7 @@ userpref_error_t pair_record_import_crt_with_name(plist_t pair_record, const cha
970 ret = pair_record_get_item_as_key_data(pair_record, name, cert); 859 ret = pair_record_get_item_as_key_data(pair_record, name, cert);
971#else 860#else
972 key_data_t pem = { NULL, 0 }; 861 key_data_t pem = { NULL, 0 };
973 ret = pair_record_get_item_as_key_data(pair_record, name, pem); 862 ret = pair_record_get_item_as_key_data(pair_record, name, &pem);
974 if (ret == USERPREF_E_SUCCESS && GNUTLS_E_SUCCESS == gnutls_x509_crt_import(cert, &pem, GNUTLS_X509_FMT_PEM)) 863 if (ret == USERPREF_E_SUCCESS && GNUTLS_E_SUCCESS == gnutls_x509_crt_import(cert, &pem, GNUTLS_X509_FMT_PEM))
975 ret = USERPREF_E_SUCCESS; 864 ret = USERPREF_E_SUCCESS;
976 else 865 else
diff --git a/common/userpref.h b/common/userpref.h
index a39417a..d9ce015 100644
--- a/common/userpref.h
+++ b/common/userpref.h
@@ -75,8 +75,7 @@ userpref_error_t userpref_read_pair_record(const char *udid, plist_t *pair_recor
75userpref_error_t userpref_save_pair_record(const char *udid, plist_t pair_record); 75userpref_error_t userpref_save_pair_record(const char *udid, plist_t pair_record);
76userpref_error_t userpref_delete_pair_record(const char *udid); 76userpref_error_t userpref_delete_pair_record(const char *udid);
77 77
78LIBIMOBILEDEVICE_INTERNAL userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record); 78LIBIMOBILEDEVICE_INTERNAL userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_data_t public_key);
79LIBIMOBILEDEVICE_INTERNAL userpref_error_t pair_record_generate_from_device_public_key(plist_t pair_record, key_data_t public_key);
80#ifdef HAVE_OPENSSL 79#ifdef HAVE_OPENSSL
81LIBIMOBILEDEVICE_INTERNAL userpref_error_t pair_record_import_key_with_name(plist_t pair_record, const char* name, key_data_t* key); 80LIBIMOBILEDEVICE_INTERNAL userpref_error_t pair_record_import_key_with_name(plist_t pair_record, const char* name, key_data_t* key);
82LIBIMOBILEDEVICE_INTERNAL userpref_error_t pair_record_import_crt_with_name(plist_t pair_record, const char* name, key_data_t* cert); 81LIBIMOBILEDEVICE_INTERNAL userpref_error_t pair_record_import_crt_with_name(plist_t pair_record, const char* name, key_data_t* cert);
diff --git a/src/lockdown.c b/src/lockdown.c
index aff682a..0efe30e 100644
--- a/src/lockdown.c
+++ b/src/lockdown.c
@@ -852,21 +852,7 @@ static lockdownd_error_t pair_record_generate(lockdownd_client_t client, plist_t
852 *pair_record = plist_new_dict(); 852 *pair_record = plist_new_dict();
853 853
854 userpref_error_t uret = USERPREF_E_SUCCESS; 854 userpref_error_t uret = USERPREF_E_SUCCESS;
855 uret = pair_record_generate_keys_and_certs(*pair_record); 855 uret = pair_record_generate_keys_and_certs(*pair_record, public_key);
856 switch(uret) {
857 case USERPREF_E_INVALID_ARG:
858 ret = LOCKDOWN_E_INVALID_ARG;
859 break;
860 case USERPREF_E_INVALID_CONF:
861 ret = LOCKDOWN_E_INVALID_CONF;
862 break;
863 case USERPREF_E_SSL_ERROR:
864 ret = LOCKDOWN_E_SSL_ERROR;
865 default:
866 break;
867 }
868
869 uret = pair_record_generate_from_device_public_key(*pair_record, public_key);
870 switch(uret) { 856 switch(uret) {
871 case USERPREF_E_INVALID_ARG: 857 case USERPREF_E_INVALID_ARG:
872 ret = LOCKDOWN_E_INVALID_ARG; 858 ret = LOCKDOWN_E_INVALID_ARG;