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>
This commit is contained in:
David Howells
2014-09-16 17:36:13 +01:00
父節點 7901c1a8ef
當前提交 46963b774d
共有 10 個文件被更改,包括 197 次插入185 次删除

查看文件

@@ -131,8 +131,7 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
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 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
* 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 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
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 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
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 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
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 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
/* 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 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
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 @@ int pkcs7_verify(struct pkcs7_message *pkcs7)
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) {