Commit 77d0910d authored by David Howells's avatar David Howells

X.509: Retain the key verification data

Retain the key verification data (ie. the struct public_key_signature)
including the digest and the key identifiers.

Note that this means that we need to take a separate copy of the digest in
x509_get_sig_params() rather than lumping it in with the crypto layer data.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent a022ec02
...@@ -80,16 +80,16 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, ...@@ -80,16 +80,16 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
might_sleep(); might_sleep();
last = x509; last = x509;
sig = &last->sig; sig = last->sig;
} }
/* No match - see if the root certificate has a signer amongst the /* No match - see if the root certificate has a signer amongst the
* trusted keys. * trusted keys.
*/ */
if (last && (last->akid_id || last->akid_skid)) { if (last && (last->sig->auth_ids[0] || last->sig->auth_ids[1])) {
key = x509_request_asymmetric_key(trust_keyring, key = x509_request_asymmetric_key(trust_keyring,
last->akid_id, last->sig->auth_ids[0],
last->akid_skid, last->sig->auth_ids[1],
false); false);
if (!IS_ERR(key)) { if (!IS_ERR(key)) {
x509 = last; x509 = last;
......
...@@ -174,6 +174,7 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7, ...@@ -174,6 +174,7 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
struct pkcs7_signed_info *sinfo) struct pkcs7_signed_info *sinfo)
{ {
struct public_key_signature *sig;
struct x509_certificate *x509 = sinfo->signer, *p; struct x509_certificate *x509 = sinfo->signer, *p;
struct asymmetric_key_id *auth; struct asymmetric_key_id *auth;
int ret; int ret;
...@@ -193,14 +194,15 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, ...@@ -193,14 +194,15 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
goto maybe_missing_crypto_in_x509; goto maybe_missing_crypto_in_x509;
pr_debug("- issuer %s\n", x509->issuer); pr_debug("- issuer %s\n", x509->issuer);
if (x509->akid_id) sig = x509->sig;
if (sig->auth_ids[0])
pr_debug("- authkeyid.id %*phN\n", pr_debug("- authkeyid.id %*phN\n",
x509->akid_id->len, x509->akid_id->data); sig->auth_ids[0]->len, sig->auth_ids[0]->data);
if (x509->akid_skid) if (sig->auth_ids[1])
pr_debug("- authkeyid.skid %*phN\n", pr_debug("- authkeyid.skid %*phN\n",
x509->akid_skid->len, x509->akid_skid->data); sig->auth_ids[1]->len, sig->auth_ids[1]->data);
if ((!x509->akid_id && !x509->akid_skid) || if ((!x509->sig->auth_ids[0] && !x509->sig->auth_ids[1]) ||
strcmp(x509->subject, x509->issuer) == 0) { strcmp(x509->subject, x509->issuer) == 0) {
/* If there's no authority certificate specified, then /* If there's no authority certificate specified, then
* the certificate must be self-signed and is the root * the certificate must be self-signed and is the root
...@@ -224,7 +226,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, ...@@ -224,7 +226,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
/* Look through the X.509 certificates in the PKCS#7 message's /* Look through the X.509 certificates in the PKCS#7 message's
* list to see if the next one is there. * list to see if the next one is there.
*/ */
auth = x509->akid_id; auth = sig->auth_ids[0];
if (auth) { if (auth) {
pr_debug("- want %*phN\n", auth->len, auth->data); pr_debug("- want %*phN\n", auth->len, auth->data);
for (p = pkcs7->certs; p; p = p->next) { for (p = pkcs7->certs; p; p = p->next) {
...@@ -234,7 +236,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, ...@@ -234,7 +236,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
goto found_issuer_check_skid; goto found_issuer_check_skid;
} }
} else { } else {
auth = x509->akid_skid; auth = sig->auth_ids[1];
pr_debug("- want %*phN\n", auth->len, auth->data); pr_debug("- want %*phN\n", auth->len, auth->data);
for (p = pkcs7->certs; p; p = p->next) { for (p = pkcs7->certs; p; p = p->next) {
if (!p->skid) if (!p->skid)
...@@ -254,8 +256,8 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, ...@@ -254,8 +256,8 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
/* We matched issuer + serialNumber, but if there's an /* We matched issuer + serialNumber, but if there's an
* authKeyId.keyId, that must match the CA subjKeyId also. * authKeyId.keyId, that must match the CA subjKeyId also.
*/ */
if (x509->akid_skid && if (sig->auth_ids[1] &&
!asymmetric_key_id_same(p->skid, x509->akid_skid)) { !asymmetric_key_id_same(p->skid, sig->auth_ids[1])) {
pr_warn("Sig %u: X.509 chain contains auth-skid nonmatch (%u->%u)\n", pr_warn("Sig %u: X.509 chain contains auth-skid nonmatch (%u->%u)\n",
sinfo->index, x509->index, p->index); sinfo->index, x509->index, p->index);
return -EKEYREJECTED; return -EKEYREJECTED;
......
...@@ -48,14 +48,11 @@ void x509_free_certificate(struct x509_certificate *cert) ...@@ -48,14 +48,11 @@ void x509_free_certificate(struct x509_certificate *cert)
{ {
if (cert) { if (cert) {
public_key_free(cert->pub); public_key_free(cert->pub);
public_key_signature_free(cert->sig);
kfree(cert->issuer); kfree(cert->issuer);
kfree(cert->subject); kfree(cert->subject);
kfree(cert->id); kfree(cert->id);
kfree(cert->skid); kfree(cert->skid);
kfree(cert->akid_id);
kfree(cert->akid_skid);
kfree(cert->sig.digest);
kfree(cert->sig.s);
kfree(cert); kfree(cert);
} }
} }
...@@ -78,6 +75,9 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) ...@@ -78,6 +75,9 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL); cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL);
if (!cert->pub) if (!cert->pub)
goto error_no_ctx; goto error_no_ctx;
cert->sig = kzalloc(sizeof(struct public_key_signature), GFP_KERNEL);
if (!cert->sig)
goto error_no_ctx;
ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL); ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL);
if (!ctx) if (!ctx)
goto error_no_ctx; goto error_no_ctx;
...@@ -188,33 +188,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen, ...@@ -188,33 +188,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
return -ENOPKG; /* Unsupported combination */ return -ENOPKG; /* Unsupported combination */
case OID_md4WithRSAEncryption: case OID_md4WithRSAEncryption:
ctx->cert->sig.hash_algo = "md4"; ctx->cert->sig->hash_algo = "md4";
ctx->cert->sig.pkey_algo = "rsa"; ctx->cert->sig->pkey_algo = "rsa";
break; break;
case OID_sha1WithRSAEncryption: case OID_sha1WithRSAEncryption:
ctx->cert->sig.hash_algo = "sha1"; ctx->cert->sig->hash_algo = "sha1";
ctx->cert->sig.pkey_algo = "rsa"; ctx->cert->sig->pkey_algo = "rsa";
break; break;
case OID_sha256WithRSAEncryption: case OID_sha256WithRSAEncryption:
ctx->cert->sig.hash_algo = "sha256"; ctx->cert->sig->hash_algo = "sha256";
ctx->cert->sig.pkey_algo = "rsa"; ctx->cert->sig->pkey_algo = "rsa";
break; break;
case OID_sha384WithRSAEncryption: case OID_sha384WithRSAEncryption:
ctx->cert->sig.hash_algo = "sha384"; ctx->cert->sig->hash_algo = "sha384";
ctx->cert->sig.pkey_algo = "rsa"; ctx->cert->sig->pkey_algo = "rsa";
break; break;
case OID_sha512WithRSAEncryption: case OID_sha512WithRSAEncryption:
ctx->cert->sig.hash_algo = "sha512"; ctx->cert->sig->hash_algo = "sha512";
ctx->cert->sig.pkey_algo = "rsa"; ctx->cert->sig->pkey_algo = "rsa";
break; break;
case OID_sha224WithRSAEncryption: case OID_sha224WithRSAEncryption:
ctx->cert->sig.hash_algo = "sha224"; ctx->cert->sig->hash_algo = "sha224";
ctx->cert->sig.pkey_algo = "rsa"; ctx->cert->sig->pkey_algo = "rsa";
break; break;
} }
...@@ -572,14 +572,14 @@ int x509_akid_note_kid(void *context, size_t hdrlen, ...@@ -572,14 +572,14 @@ int x509_akid_note_kid(void *context, size_t hdrlen,
pr_debug("AKID: keyid: %*phN\n", (int)vlen, value); pr_debug("AKID: keyid: %*phN\n", (int)vlen, value);
if (ctx->cert->akid_skid) if (ctx->cert->sig->auth_ids[1])
return 0; return 0;
kid = asymmetric_key_generate_id(value, vlen, "", 0); kid = asymmetric_key_generate_id(value, vlen, "", 0);
if (IS_ERR(kid)) if (IS_ERR(kid))
return PTR_ERR(kid); return PTR_ERR(kid);
pr_debug("authkeyid %*phN\n", kid->len, kid->data); pr_debug("authkeyid %*phN\n", kid->len, kid->data);
ctx->cert->akid_skid = kid; ctx->cert->sig->auth_ids[1] = kid;
return 0; return 0;
} }
...@@ -611,7 +611,7 @@ int x509_akid_note_serial(void *context, size_t hdrlen, ...@@ -611,7 +611,7 @@ int x509_akid_note_serial(void *context, size_t hdrlen,
pr_debug("AKID: serial: %*phN\n", (int)vlen, value); pr_debug("AKID: serial: %*phN\n", (int)vlen, value);
if (!ctx->akid_raw_issuer || ctx->cert->akid_id) if (!ctx->akid_raw_issuer || ctx->cert->sig->auth_ids[0])
return 0; return 0;
kid = asymmetric_key_generate_id(value, kid = asymmetric_key_generate_id(value,
...@@ -622,6 +622,6 @@ int x509_akid_note_serial(void *context, size_t hdrlen, ...@@ -622,6 +622,6 @@ int x509_akid_note_serial(void *context, size_t hdrlen,
return PTR_ERR(kid); return PTR_ERR(kid);
pr_debug("authkeyid %*phN\n", kid->len, kid->data); pr_debug("authkeyid %*phN\n", kid->len, kid->data);
ctx->cert->akid_id = kid; ctx->cert->sig->auth_ids[0] = kid;
return 0; return 0;
} }
...@@ -17,13 +17,11 @@ struct x509_certificate { ...@@ -17,13 +17,11 @@ struct x509_certificate {
struct x509_certificate *next; struct x509_certificate *next;
struct x509_certificate *signer; /* Certificate that signed this one */ struct x509_certificate *signer; /* Certificate that signed this one */
struct public_key *pub; /* Public key details */ struct public_key *pub; /* Public key details */
struct public_key_signature sig; /* Signature parameters */ struct public_key_signature *sig; /* Signature parameters */
char *issuer; /* Name of certificate issuer */ char *issuer; /* Name of certificate issuer */
char *subject; /* Name of certificate subject */ char *subject; /* Name of certificate subject */
struct asymmetric_key_id *id; /* Issuer + Serial number */ struct asymmetric_key_id *id; /* Issuer + Serial number */
struct asymmetric_key_id *skid; /* Subject + subjectKeyId (optional) */ struct asymmetric_key_id *skid; /* Subject + subjectKeyId (optional) */
struct asymmetric_key_id *akid_id; /* CA AuthKeyId matching ->id (optional) */
struct asymmetric_key_id *akid_skid; /* CA AuthKeyId matching ->skid (optional) */
time64_t valid_from; time64_t valid_from;
time64_t valid_to; time64_t valid_to;
const void *tbs; /* Signed data */ const void *tbs; /* Signed data */
......
...@@ -153,30 +153,29 @@ EXPORT_SYMBOL_GPL(x509_request_asymmetric_key); ...@@ -153,30 +153,29 @@ EXPORT_SYMBOL_GPL(x509_request_asymmetric_key);
*/ */
int x509_get_sig_params(struct x509_certificate *cert) int x509_get_sig_params(struct x509_certificate *cert)
{ {
struct public_key_signature *sig = cert->sig;
struct crypto_shash *tfm; struct crypto_shash *tfm;
struct shash_desc *desc; struct shash_desc *desc;
size_t digest_size, desc_size; size_t desc_size;
void *digest;
int ret; int ret;
pr_devel("==>%s()\n", __func__); pr_devel("==>%s()\n", __func__);
if (cert->unsupported_crypto) if (cert->unsupported_crypto)
return -ENOPKG; return -ENOPKG;
if (cert->sig.s) if (sig->s)
return 0; return 0;
cert->sig.s = kmemdup(cert->raw_sig, cert->raw_sig_size, sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL);
GFP_KERNEL); if (!sig->s)
if (!cert->sig.s)
return -ENOMEM; return -ENOMEM;
cert->sig.s_size = cert->raw_sig_size; sig->s_size = cert->raw_sig_size;
/* Allocate the hashing algorithm we're going to need and find out how /* Allocate the hashing algorithm we're going to need and find out how
* big the hash operational data will be. * big the hash operational data will be.
*/ */
tfm = crypto_alloc_shash(cert->sig.hash_algo, 0, 0); tfm = crypto_alloc_shash(sig->hash_algo, 0, 0);
if (IS_ERR(tfm)) { if (IS_ERR(tfm)) {
if (PTR_ERR(tfm) == -ENOENT) { if (PTR_ERR(tfm) == -ENOENT) {
cert->unsupported_crypto = true; cert->unsupported_crypto = true;
...@@ -186,29 +185,28 @@ int x509_get_sig_params(struct x509_certificate *cert) ...@@ -186,29 +185,28 @@ int x509_get_sig_params(struct x509_certificate *cert)
} }
desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
digest_size = crypto_shash_digestsize(tfm); sig->digest_size = crypto_shash_digestsize(tfm);
/* We allocate the hash operational data storage on the end of the
* digest storage space.
*/
ret = -ENOMEM; ret = -ENOMEM;
digest = kzalloc(ALIGN(digest_size, __alignof__(*desc)) + desc_size, sig->digest = kmalloc(sig->digest_size, GFP_KERNEL);
GFP_KERNEL); if (!sig->digest)
if (!digest)
goto error; goto error;
cert->sig.digest = digest; desc = kzalloc(desc_size, GFP_KERNEL);
cert->sig.digest_size = digest_size; if (!desc)
goto error;
desc = PTR_ALIGN(digest + digest_size, __alignof__(*desc));
desc->tfm = tfm; desc->tfm = tfm;
desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
ret = crypto_shash_init(desc); ret = crypto_shash_init(desc);
if (ret < 0) if (ret < 0)
goto error; goto error_2;
might_sleep(); might_sleep();
ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest); ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest);
error_2:
kfree(desc);
error: error:
crypto_free_shash(tfm); crypto_free_shash(tfm);
pr_devel("<==%s() = %d\n", __func__, ret); pr_devel("<==%s() = %d\n", __func__, ret);
...@@ -230,7 +228,7 @@ int x509_check_signature(const struct public_key *pub, ...@@ -230,7 +228,7 @@ int x509_check_signature(const struct public_key *pub,
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = public_key_verify_signature(pub, &cert->sig); ret = public_key_verify_signature(pub, cert->sig);
if (ret == -ENOPKG) if (ret == -ENOPKG)
cert->unsupported_crypto = true; cert->unsupported_crypto = true;
pr_debug("Cert Verification: %d\n", ret); pr_debug("Cert Verification: %d\n", ret);
...@@ -250,17 +248,18 @@ EXPORT_SYMBOL_GPL(x509_check_signature); ...@@ -250,17 +248,18 @@ EXPORT_SYMBOL_GPL(x509_check_signature);
static int x509_validate_trust(struct x509_certificate *cert, static int x509_validate_trust(struct x509_certificate *cert,
struct key *trust_keyring) struct key *trust_keyring)
{ {
struct public_key_signature *sig = cert->sig;
struct key *key; struct key *key;
int ret = 1; int ret = 1;
if (!trust_keyring) if (!trust_keyring)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (ca_keyid && !asymmetric_key_id_partial(cert->akid_skid, ca_keyid)) if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid))
return -EPERM; return -EPERM;
key = x509_request_asymmetric_key(trust_keyring, key = x509_request_asymmetric_key(trust_keyring,
cert->akid_id, cert->akid_skid, sig->auth_ids[0], sig->auth_ids[1],
false); false);
if (!IS_ERR(key)) { if (!IS_ERR(key)) {
if (!use_builtin_keys if (!use_builtin_keys
...@@ -292,8 +291,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) ...@@ -292,8 +291,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
pr_devel("Cert Subject: %s\n", cert->subject); pr_devel("Cert Subject: %s\n", cert->subject);
if (!cert->pub->pkey_algo || if (!cert->pub->pkey_algo ||
!cert->sig.pkey_algo || !cert->sig->pkey_algo ||
!cert->sig.hash_algo) { !cert->sig->hash_algo) {
ret = -ENOPKG; ret = -ENOPKG;
goto error_free_cert; goto error_free_cert;
} }
...@@ -301,15 +300,15 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) ...@@ -301,15 +300,15 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo); pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo);
pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to); pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);
pr_devel("Cert Signature: %s + %s\n", pr_devel("Cert Signature: %s + %s\n",
cert->sig.pkey_algo, cert->sig->pkey_algo,
cert->sig.hash_algo); cert->sig->hash_algo);
cert->pub->id_type = "X509"; cert->pub->id_type = "X509";
/* Check the signature on the key if it appears to be self-signed */ /* Check the signature on the key if it appears to be self-signed */
if ((!cert->akid_skid && !cert->akid_id) || if ((!cert->sig->auth_ids[0] && !cert->sig->auth_ids[1]) ||
asymmetric_key_id_same(cert->skid, cert->akid_skid) || asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]) ||
asymmetric_key_id_same(cert->id, cert->akid_id)) { asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0])) {
ret = x509_check_signature(cert->pub, cert); /* self-signed */ ret = x509_check_signature(cert->pub, cert); /* self-signed */
if (ret < 0) if (ret < 0)
goto error_free_cert; goto error_free_cert;
...@@ -353,6 +352,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) ...@@ -353,6 +352,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
prep->payload.data[asym_subtype] = &public_key_subtype; prep->payload.data[asym_subtype] = &public_key_subtype;
prep->payload.data[asym_key_ids] = kids; prep->payload.data[asym_key_ids] = kids;
prep->payload.data[asym_crypto] = cert->pub; prep->payload.data[asym_crypto] = cert->pub;
prep->payload.data[asym_auth] = cert->sig;
prep->description = desc; prep->description = desc;
prep->quotalen = 100; prep->quotalen = 100;
...@@ -360,6 +360,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) ...@@ -360,6 +360,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
cert->pub = NULL; cert->pub = NULL;
cert->id = NULL; cert->id = NULL;
cert->skid = NULL; cert->skid = NULL;
cert->sig = NULL;
desc = NULL; desc = NULL;
ret = 0; ret = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment