diff options
| author | 2016-11-04 02:11:39 +0100 | |
|---|---|---|
| committer | 2016-11-04 02:11:39 +0100 | |
| commit | 23069d10341ce637fdad7321d447c53752dba48c (patch) | |
| tree | cf5066bc1a2c21dc222bb97a975ba5fecb10f138 | |
| parent | 8c37b9ca13211c197f3452356b73114c39f549fd (diff) | |
| download | libimobiledevice-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.
| -rw-r--r-- | common/userpref.c | 85 |
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 | } |
