Blame SOURCES/0001-userpref-GnuTLS-Fix-pairing-record-generation-and-im.patch

612eec
From 23069d10341ce637fdad7321d447c53752dba48c Mon Sep 17 00:00:00 2001
612eec
From: Nikias Bassen <nikias@gmx.li>
612eec
Date: Fri, 4 Nov 2016 02:11:39 +0100
612eec
Subject: [PATCH] userpref: [GnuTLS] Fix pairing record generation and improve
612eec
 error handling
612eec
612eec
In newer GnuTLS versions the parameters supplied to
612eec
gnutls_x509_privkey_import_rsa_raw() are actually checked for somewhat
612eec
sane values. Since we were passing the same values for all parameters,
612eec
this check fails and the device certificate is never generated.
612eec
However due to missing checks the pairing record was saved anyway, with
612eec
an empty device certificate. This led to TLS errors during communication,
612eec
leading to the "GnuTLS: Error in pull function" error message appearing
612eec
and the communication to fail.
612eec
This commit fixes the issue by passing some sane values, and also improves
612eec
the overall error handling during generation of the paring record.
612eec
---
612eec
 common/userpref.c | 85 +++++++++++++++++++++++++++++--------------------------
612eec
 1 file changed, 45 insertions(+), 40 deletions(-)
612eec
612eec
diff --git a/common/userpref.c b/common/userpref.c
612eec
index d22c7f5..3ae503a 100644
612eec
--- a/common/userpref.c
612eec
+++ b/common/userpref.c
612eec
@@ -643,15 +643,13 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da
612eec
 	gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size);
612eec
 	host_cert_pem.size = host_cert_export_size;
612eec
 
612eec
-	ret = USERPREF_E_UNKNOWN_ERROR;
612eec
-
612eec
 	gnutls_datum_t modulus = { NULL, 0 };
612eec
 	gnutls_datum_t exponent = { NULL, 0 };
612eec
 
612eec
 	/* now decode the PEM encoded key */
612eec
-	gnutls_datum_t der_pub_key;
612eec
-	if (GNUTLS_E_SUCCESS == gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &public_key, &der_pub_key)) {
612eec
-
612eec
+	gnutls_datum_t der_pub_key = { NULL, 0 };
612eec
+	int gnutls_error = gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &public_key, &der_pub_key);
612eec
+	if (GNUTLS_E_SUCCESS == gnutls_error) {
612eec
 		/* initalize asn.1 parser */
612eec
 		ASN1_TYPE pkcs1 = ASN1_TYPE_EMPTY;
612eec
 		if (ASN1_SUCCESS == asn1_array2tree(pkcs1_asn1_tab, &pkcs1, NULL)) {
612eec
@@ -670,8 +668,14 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da
612eec
 
612eec
 				ret1 = asn1_read_value(asn1_pub_key, "modulus", modulus.data, (int*)&modulus.size);
612eec
 				ret2 = asn1_read_value(asn1_pub_key, "publicExponent", exponent.data, (int*)&exponent.size);
612eec
-				if (ASN1_SUCCESS == ret1 && ASN1_SUCCESS == ret2)
612eec
-					ret = USERPREF_E_SUCCESS;
612eec
+				if (ret1 != ASN1_SUCCESS || ret2 != ASN1_SUCCESS) {
612eec
+					gnutls_free(modulus.data);
612eec
+					modulus.data = NULL;
612eec
+					modulus.size = 0;
612eec
+					gnutls_free(exponent.data);
612eec
+					exponent.data = NULL;
612eec
+					exponent.size = 0;
612eec
+				}
612eec
 			}
612eec
 			if (asn1_pub_key)
612eec
 				asn1_delete_structure(&asn1_pub_key);
612eec
@@ -679,12 +683,15 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da
612eec
 		if (pkcs1)
612eec
 			asn1_delete_structure(&pkcs1);
612eec
 	} else {
612eec
-		debug_info("WARNING: Could not read public key");
612eec
+		debug_info("ERROR: Could not parse public key: %s", gnutls_strerror(gnutls_error));
612eec
 	}
612eec
 
612eec
-	/* now generate certificates */
612eec
-	if (USERPREF_E_SUCCESS == ret && 0 != modulus.size && 0 != exponent.size) {
612eec
-		gnutls_datum_t essentially_null = { (unsigned char*)strdup("abababababababab"), strlen("abababababababab") };
612eec
+	/* generate device certificate */
612eec
+	if (modulus.data && 0 != modulus.size && exponent.data && 0 != exponent.size) {
612eec
+
612eec
+		gnutls_datum_t prime_p = { (unsigned char*)"\x00\xca\x4a\x03\x13\xdf\x9d\x7a\xfd", 9 };
612eec
+		gnutls_datum_t prime_q = { (unsigned char*)"\x00\xf2\xff\xe0\x15\xd1\x60\x37\x63", 9 };
612eec
+		gnutls_datum_t coeff = { (unsigned char*)"\x32\x07\xf1\x68\x57\xdf\x9a\xf4", 8 };
612eec
 
612eec
 		gnutls_x509_privkey_t fake_privkey;
612eec
 		gnutls_x509_crt_t dev_cert;
612eec
@@ -692,8 +699,9 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da
612eec
 		gnutls_x509_privkey_init(&fake_privkey);
612eec
 		gnutls_x509_crt_init(&dev_cert);
612eec
 
612eec
-		if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &essentially_null, &essentially_null, &essentially_null, &essentially_null)) {
612eec
-			/* generate device certificate */
612eec
+		gnutls_error = gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &exponent, &prime_p, &prime_q, &coeff);
612eec
+		if (GNUTLS_E_SUCCESS == gnutls_error) {
612eec
+			/* now generate device certificate */
612eec
 			gnutls_x509_crt_set_key(dev_cert, fake_privkey);
612eec
 			gnutls_x509_crt_set_serial(dev_cert, "\x00", 1);
612eec
 			gnutls_x509_crt_set_version(dev_cert, 3);
612eec
@@ -712,9 +720,8 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da
612eec
 			}
612eec
 
612eec
 			gnutls_x509_crt_set_key_usage(dev_cert, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT);
612eec
-			gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey);
612eec
-
612eec
-			if (USERPREF_E_SUCCESS == ret) {
612eec
+			gnutls_error = gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey);
612eec
+			if (GNUTLS_E_SUCCESS == gnutls_error) {
612eec
 				/* if everything went well, export in PEM format */
612eec
 				size_t export_size = 0;
612eec
 				gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &export_size);
612eec
@@ -722,13 +729,11 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da
612eec
 				gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_cert_pem.data, &export_size);
612eec
 				dev_cert_pem.size = export_size;
612eec
 			} else {
612eec
-				debug_info("ERROR: Signing device certificate with root private key failed!");
612eec
+				debug_info("ERROR: Signing device certificate with root private key failed: %s", gnutls_strerror(gnutls_error));
612eec
 			}
612eec
+		} else {
612eec
+			debug_info("ERROR: Failed to import RSA key data: %s", gnutls_strerror(gnutls_error));
612eec
 		}
612eec
-
612eec
-		if (essentially_null.data)
612eec
-			free(essentially_null.data);
612eec
-
612eec
 		gnutls_x509_crt_deinit(dev_cert);
612eec
 		gnutls_x509_privkey_deinit(fake_privkey);
612eec
 	}
612eec
@@ -743,27 +748,27 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da
612eec
 
612eec
 	gnutls_free(der_pub_key.data);
612eec
 #endif
612eec
-	if (NULL != root_cert_pem.data && 0 != root_cert_pem.size &&
612eec
-		NULL != host_cert_pem.data && 0 != host_cert_pem.size)
612eec
+
612eec
+	/* make sure that we have all we need */
612eec
+	if (root_cert_pem.data && 0 != root_cert_pem.size
612eec
+	    && root_key_pem.data && 0 != root_key_pem.size
612eec
+	    && host_cert_pem.data && 0 != host_cert_pem.size
612eec
+	    && host_key_pem.data && 0 != host_key_pem.size
612eec
+	    && dev_cert_pem.data && 0 != dev_cert_pem.size) {
612eec
+		/* now set keys and certificates */
612eec
+		pair_record_set_item_from_key_data(pair_record, USERPREF_DEVICE_CERTIFICATE_KEY, &dev_cert_pem);
612eec
+		pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, &host_key_pem);
612eec
+		pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_CERTIFICATE_KEY, &host_cert_pem);
612eec
+		pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_key_pem);
612eec
+		pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert_pem);
612eec
 		ret = USERPREF_E_SUCCESS;
612eec
+	}
612eec
 
612eec
-	/* now set keys and certificates */
612eec
-	pair_record_set_item_from_key_data(pair_record, USERPREF_DEVICE_CERTIFICATE_KEY, &dev_cert_pem);
612eec
-	pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, &host_key_pem);
612eec
-	pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_CERTIFICATE_KEY, &host_cert_pem);
612eec
-	pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_key_pem);
612eec
-	pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert_pem);
612eec
-
612eec
-	if (dev_cert_pem.data)
612eec
-		free(dev_cert_pem.data);
612eec
-	if (root_key_pem.data)
612eec
-		free(root_key_pem.data);
612eec
-	if (root_cert_pem.data)
612eec
-		free(root_cert_pem.data);
612eec
-	if (host_key_pem.data)
612eec
-		free(host_key_pem.data);
612eec
-	if (host_cert_pem.data)
612eec
-		free(host_cert_pem.data);
612eec
+	free(dev_cert_pem.data);
612eec
+	free(root_key_pem.data);
612eec
+	free(root_cert_pem.data);
612eec
+	free(host_key_pem.data);
612eec
+	free(host_cert_pem.data);
612eec
 
612eec
 	return ret;
612eec
 }
612eec
-- 
612eec
2.9.3
612eec