KEYS: Overhaul key identification when searching for asymmetric keys

Make use of the new match string preparsing to overhaul key identification
when searching for asymmetric keys.  The following changes are made:

 (1) Use the previously created asymmetric_key_id struct to hold the following
     key IDs derived from the X.509 certificate or PKCS#7 message:

	id: serial number + issuer
	skid: subjKeyId + subject
	authority: authKeyId + issuer

 (2) Replace the hex fingerprint attached to key->type_data[1] with an
     asymmetric_key_ids struct containing the id and the skid (if present).

 (3) Make the asymmetric_type match data preparse select one of two searches:

     (a) An iterative search for the key ID given if prefixed with "id:".  The
     	 prefix is expected to be followed by a hex string giving the ID to
     	 search for.  The criterion key ID is checked against all key IDs
     	 recorded on the key.

     (b) A direct search if the key ID is not prefixed with "id:".  This will
     	 look for an exact match on the key description.

 (4) Make x509_request_asymmetric_key() take a key ID.  This is then converted
     into "id:<hex>" and passed into keyring_search() where match preparsing
     will turn it back into a binary ID.

 (5) X.509 certificate verification then takes the authority key ID and looks
     up a key that matches it to find the public key for the certificate
     signature.

 (6) PKCS#7 certificate verification then takes the id key ID and looks up a
     key that matches it to find the public key for the signed information
     block signature.

Additional changes:

 (1) Multiple subjKeyId and authKeyId values on an X.509 certificate cause the
     cert to be rejected with -EBADMSG.

 (2) The 'fingerprint' ID is gone.  This was primarily intended to convey PGP
     public key fingerprints.  If PGP is supported in future, this should
     generate a key ID that carries the fingerprint.

 (3) Th ca_keyid= kernel command line option is now converted to a key ID and
     used to match the authority key ID.  Possibly this should only match the
     actual authKeyId part and not the issuer as well.

Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index c62cf80..57e90fa 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -131,8 +131,7 @@
 	struct x509_certificate *x509;
 	unsigned certix = 1;
 
-	kenter("%u,%u,%u",
-	       sinfo->index, sinfo->raw_serial_size, sinfo->raw_issuer_size);
+	kenter("%u", sinfo->index);
 
 	for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) {
 		/* I'm _assuming_ that the generator of the PKCS#7 message will
@@ -140,21 +139,11 @@
 		 * PKCS#7 message - but I can't be 100% sure of that.  It's
 		 * possible this will need element-by-element comparison.
 		 */
-		if (x509->raw_serial_size != sinfo->raw_serial_size ||
-		    memcmp(x509->raw_serial, sinfo->raw_serial,
-			   sinfo->raw_serial_size) != 0)
+		if (!asymmetric_key_id_same(x509->id, sinfo->signing_cert_id))
 			continue;
 		pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
 			 sinfo->index, certix);
 
-		if (x509->raw_issuer_size != sinfo->raw_issuer_size ||
-		    memcmp(x509->raw_issuer, sinfo->raw_issuer,
-			   sinfo->raw_issuer_size) != 0) {
-			pr_warn("Sig %u: X.509 subject and PKCS#7 issuer don't match\n",
-				sinfo->index);
-			continue;
-		}
-
 		if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) {
 			pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
 				sinfo->index);
@@ -164,8 +153,10 @@
 		sinfo->signer = x509;
 		return 0;
 	}
+
 	pr_warn("Sig %u: Issuing X.509 cert not found (#%*ph)\n",
-		sinfo->index, sinfo->raw_serial_size, sinfo->raw_serial);
+		sinfo->index,
+		sinfo->signing_cert_id->len, sinfo->signing_cert_id->data);
 	return -ENOKEY;
 }
 
@@ -184,7 +175,9 @@
 		p->seen = false;
 
 	for (;;) {
-		pr_debug("verify %s: %s\n", x509->subject, x509->fingerprint);
+		pr_debug("verify %s: %*phN\n",
+			 x509->subject,
+			 x509->raw_serial_size, x509->raw_serial);
 		x509->seen = true;
 		ret = x509_get_sig_params(x509);
 		if (ret < 0)
@@ -192,7 +185,8 @@
 
 		pr_debug("- issuer %s\n", x509->issuer);
 		if (x509->authority)
-			pr_debug("- authkeyid %s\n", x509->authority);
+			pr_debug("- authkeyid %*phN\n",
+				 x509->authority->len, x509->authority->data);
 
 		if (!x509->authority ||
 		    strcmp(x509->subject, x509->issuer) == 0) {
@@ -218,13 +212,14 @@
 		/* Look through the X.509 certificates in the PKCS#7 message's
 		 * list to see if the next one is there.
 		 */
-		pr_debug("- want %s\n", x509->authority);
+		pr_debug("- want %*phN\n",
+			 x509->authority->len, x509->authority->data);
 		for (p = pkcs7->certs; p; p = p->next) {
-			pr_debug("- cmp [%u] %s\n", p->index, p->fingerprint);
-			if (p->raw_subject_size == x509->raw_issuer_size &&
-			    strcmp(p->fingerprint, x509->authority) == 0 &&
-			    memcmp(p->raw_subject, x509->raw_issuer,
-				   x509->raw_issuer_size) == 0)
+			if (!p->skid)
+				continue;
+			pr_debug("- cmp [%u] %*phN\n",
+				 p->index, p->skid->len, p->skid->data);
+			if (asymmetric_key_id_same(p->skid, x509->authority))
 				goto found_issuer;
 		}
 
@@ -233,7 +228,7 @@
 		return 0;
 
 	found_issuer:
-		pr_debug("- issuer %s\n", p->subject);
+		pr_debug("- subject %s\n", p->subject);
 		if (p->seen) {
 			pr_warn("Sig %u: X.509 chain contains loop\n",
 				sinfo->index);
@@ -304,7 +299,8 @@
 		ret = x509_get_sig_params(x509);
 		if (ret < 0)
 			return ret;
-		pr_debug("X.509[%u] %s\n", n, x509->authority);
+		pr_debug("X.509[%u] %*phN\n",
+			 n, x509->authority->len, x509->authority->data);
 	}
 
 	for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {