summaryrefslogtreecommitdiffstats
path: root/common/userpref.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2016-11-04 02:11:39 +0100
committerGravatar Nikias Bassen2016-11-04 02:11:39 +0100
commit23069d10341ce637fdad7321d447c53752dba48c (patch)
treecf5066bc1a2c21dc222bb97a975ba5fecb10f138 /common/userpref.c
parent8c37b9ca13211c197f3452356b73114c39f549fd (diff)
downloadlibimobiledevice-23069d10341ce637fdad7321d447c53752dba48c.tar.gz
libimobiledevice-23069d10341ce637fdad7321d447c53752dba48c.tar.bz2
userpref: [GnuTLS] Fix pairing record generation and improve error handling
In newer GnuTLS versions the parameters supplied to gnutls_x509_privkey_import_rsa_raw() are actually checked for somewhat sane values. Since we were passing the same values for all parameters, this check fails and the device certificate is never generated. However due to missing checks the pairing record was saved anyway, with an empty device certificate. This led to TLS errors during communication, leading to the "GnuTLS: Error in pull function" error message appearing and the communication to fail. This commit fixes the issue by passing some sane values, and also improves the overall error handling during generation of the paring record.
Diffstat (limited to 'common/userpref.c')
-rw-r--r--common/userpref.c85
1 files changed, 45 insertions, 40 deletions
diff --git a/common/userpref.c b/common/userpref.c
index d22c7f5..3ae503a 100644
--- a/common/userpref.c
+++ b/common/userpref.c
@@ -643,15 +643,13 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da
643 gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size); 643 gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size);
644 host_cert_pem.size = host_cert_export_size; 644 host_cert_pem.size = host_cert_export_size;
645 645
646 ret = USERPREF_E_UNKNOWN_ERROR;
647
648 gnutls_datum_t modulus = { NULL, 0 }; 646 gnutls_datum_t modulus = { NULL, 0 };
649 gnutls_datum_t exponent = { NULL, 0 }; 647 gnutls_datum_t exponent = { NULL, 0 };
650 648
651 /* now decode the PEM encoded key */ 649 /* now decode the PEM encoded key */
652 gnutls_datum_t der_pub_key; 650 gnutls_datum_t der_pub_key = { NULL, 0 };
653 if (GNUTLS_E_SUCCESS == gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &public_key, &der_pub_key)) { 651 int gnutls_error = gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &public_key, &der_pub_key);
654 652 if (GNUTLS_E_SUCCESS == gnutls_error) {
655 /* initalize asn.1 parser */ 653 /* initalize asn.1 parser */
656 ASN1_TYPE pkcs1 = ASN1_TYPE_EMPTY; 654 ASN1_TYPE pkcs1 = ASN1_TYPE_EMPTY;
657 if (ASN1_SUCCESS == asn1_array2tree(pkcs1_asn1_tab, &pkcs1, NULL)) { 655 if (ASN1_SUCCESS == asn1_array2tree(pkcs1_asn1_tab, &pkcs1, NULL)) {
@@ -670,8 +668,14 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da
670 668
671 ret1 = asn1_read_value(asn1_pub_key, "modulus", modulus.data, (int*)&modulus.size); 669 ret1 = asn1_read_value(asn1_pub_key, "modulus", modulus.data, (int*)&modulus.size);
672 ret2 = asn1_read_value(asn1_pub_key, "publicExponent", exponent.data, (int*)&exponent.size); 670 ret2 = asn1_read_value(asn1_pub_key, "publicExponent", exponent.data, (int*)&exponent.size);
673 if (ASN1_SUCCESS == ret1 && ASN1_SUCCESS == ret2) 671 if (ret1 != ASN1_SUCCESS || ret2 != ASN1_SUCCESS) {
674 ret = USERPREF_E_SUCCESS; 672 gnutls_free(modulus.data);
673 modulus.data = NULL;
674 modulus.size = 0;
675 gnutls_free(exponent.data);
676 exponent.data = NULL;
677 exponent.size = 0;
678 }
675 } 679 }
676 if (asn1_pub_key) 680 if (asn1_pub_key)
677 asn1_delete_structure(&asn1_pub_key); 681 asn1_delete_structure(&asn1_pub_key);
@@ -679,12 +683,15 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da
679 if (pkcs1) 683 if (pkcs1)
680 asn1_delete_structure(&pkcs1); 684 asn1_delete_structure(&pkcs1);
681 } else { 685 } else {
682 debug_info("WARNING: Could not read public key"); 686 debug_info("ERROR: Could not parse public key: %s", gnutls_strerror(gnutls_error));
683 } 687 }
684 688
685 /* now generate certificates */ 689 /* generate device certificate */
686 if (USERPREF_E_SUCCESS == ret && 0 != modulus.size && 0 != exponent.size) { 690 if (modulus.data && 0 != modulus.size && exponent.data && 0 != exponent.size) {
687 gnutls_datum_t essentially_null = { (unsigned char*)strdup("abababababababab"), strlen("abababababababab") }; 691
692 gnutls_datum_t prime_p = { (unsigned char*)"\x00\xca\x4a\x03\x13\xdf\x9d\x7a\xfd", 9 };
693 gnutls_datum_t prime_q = { (unsigned char*)"\x00\xf2\xff\xe0\x15\xd1\x60\x37\x63", 9 };
694 gnutls_datum_t coeff = { (unsigned char*)"\x32\x07\xf1\x68\x57\xdf\x9a\xf4", 8 };
688 695
689 gnutls_x509_privkey_t fake_privkey; 696 gnutls_x509_privkey_t fake_privkey;
690 gnutls_x509_crt_t dev_cert; 697 gnutls_x509_crt_t dev_cert;
@@ -692,8 +699,9 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da
692 gnutls_x509_privkey_init(&fake_privkey); 699 gnutls_x509_privkey_init(&fake_privkey);
693 gnutls_x509_crt_init(&dev_cert); 700 gnutls_x509_crt_init(&dev_cert);
694 701
695 if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &essentially_null, &essentially_null, &essentially_null, &essentially_null)) { 702 gnutls_error = gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &exponent, &prime_p, &prime_q, &coeff);
696 /* generate device certificate */ 703 if (GNUTLS_E_SUCCESS == gnutls_error) {
704 /* now generate device certificate */
697 gnutls_x509_crt_set_key(dev_cert, fake_privkey); 705 gnutls_x509_crt_set_key(dev_cert, fake_privkey);
698 gnutls_x509_crt_set_serial(dev_cert, "\x00", 1); 706 gnutls_x509_crt_set_serial(dev_cert, "\x00", 1);
699 gnutls_x509_crt_set_version(dev_cert, 3); 707 gnutls_x509_crt_set_version(dev_cert, 3);
@@ -712,9 +720,8 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da
712 } 720 }
713 721
714 gnutls_x509_crt_set_key_usage(dev_cert, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT); 722 gnutls_x509_crt_set_key_usage(dev_cert, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT);
715 gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey); 723 gnutls_error = gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey);
716 724 if (GNUTLS_E_SUCCESS == gnutls_error) {
717 if (USERPREF_E_SUCCESS == ret) {
718 /* if everything went well, export in PEM format */ 725 /* if everything went well, export in PEM format */
719 size_t export_size = 0; 726 size_t export_size = 0;
720 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &export_size); 727 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &export_size);
@@ -722,13 +729,11 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da
722 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_cert_pem.data, &export_size); 729 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_cert_pem.data, &export_size);
723 dev_cert_pem.size = export_size; 730 dev_cert_pem.size = export_size;
724 } else { 731 } else {
725 debug_info("ERROR: Signing device certificate with root private key failed!"); 732 debug_info("ERROR: Signing device certificate with root private key failed: %s", gnutls_strerror(gnutls_error));
726 } 733 }
734 } else {
735 debug_info("ERROR: Failed to import RSA key data: %s", gnutls_strerror(gnutls_error));
727 } 736 }
728
729 if (essentially_null.data)
730 free(essentially_null.data);
731
732 gnutls_x509_crt_deinit(dev_cert); 737 gnutls_x509_crt_deinit(dev_cert);
733 gnutls_x509_privkey_deinit(fake_privkey); 738 gnutls_x509_privkey_deinit(fake_privkey);
734 } 739 }
@@ -743,27 +748,27 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da
743 748
744 gnutls_free(der_pub_key.data); 749 gnutls_free(der_pub_key.data);
745#endif 750#endif
746 if (NULL != root_cert_pem.data && 0 != root_cert_pem.size && 751
747 NULL != host_cert_pem.data && 0 != host_cert_pem.size) 752 /* make sure that we have all we need */
753 if (root_cert_pem.data && 0 != root_cert_pem.size
754 && root_key_pem.data && 0 != root_key_pem.size
755 && host_cert_pem.data && 0 != host_cert_pem.size
756 && host_key_pem.data && 0 != host_key_pem.size
757 && dev_cert_pem.data && 0 != dev_cert_pem.size) {
758 /* now set keys and certificates */
759 pair_record_set_item_from_key_data(pair_record, USERPREF_DEVICE_CERTIFICATE_KEY, &dev_cert_pem);
760 pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, &host_key_pem);
761 pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_CERTIFICATE_KEY, &host_cert_pem);
762 pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_key_pem);
763 pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert_pem);
748 ret = USERPREF_E_SUCCESS; 764 ret = USERPREF_E_SUCCESS;
765 }
749 766
750 /* now set keys and certificates */ 767 free(dev_cert_pem.data);
751 pair_record_set_item_from_key_data(pair_record, USERPREF_DEVICE_CERTIFICATE_KEY, &dev_cert_pem); 768 free(root_key_pem.data);
752 pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, &host_key_pem); 769 free(root_cert_pem.data);
753 pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_CERTIFICATE_KEY, &host_cert_pem); 770 free(host_key_pem.data);
754 pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_key_pem); 771 free(host_cert_pem.data);
755 pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert_pem);
756
757 if (dev_cert_pem.data)
758 free(dev_cert_pem.data);
759 if (root_key_pem.data)
760 free(root_key_pem.data);
761 if (root_cert_pem.data)
762 free(root_cert_pem.data);
763 if (host_key_pem.data)
764 free(host_key_pem.data);
765 if (host_cert_pem.data)
766 free(host_cert_pem.data);
767 772
768 return ret; 773 return ret;
769} 774}