Commit 340cd3a2 authored by David Howells's avatar David Howells

KEYS: Generalise x509_request_asymmetric_key()

Generalise x509_request_asymmetric_key().  It doesn't really have any
dependencies on X.509 features as it uses generalised IDs and the
public_key structs that contain data extracted from X.509.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 4a54d9d3
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
* 2 of the Licence, or (at your option) any later version. * 2 of the Licence, or (at your option) any later version.
*/ */
#include <keys/asymmetric-type.h>
extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id); extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id);
extern int __asymmetric_key_hex_to_key_id(const char *id, extern int __asymmetric_key_hex_to_key_id(const char *id,
......
...@@ -51,9 +51,9 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, ...@@ -51,9 +51,9 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
/* Look to see if this certificate is present in the trusted /* Look to see if this certificate is present in the trusted
* keys. * keys.
*/ */
key = x509_request_asymmetric_key(trust_keyring, key = request_asymmetric_key(trust_keyring,
x509->id, x509->skid, x509->id, x509->skid,
false); false);
if (!IS_ERR(key)) { if (!IS_ERR(key)) {
/* One of the X.509 certificates in the PKCS#7 message /* One of the X.509 certificates in the PKCS#7 message
* is apparently the same as one we already trust. * is apparently the same as one we already trust.
...@@ -84,10 +84,10 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, ...@@ -84,10 +84,10 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
* trusted keys. * trusted keys.
*/ */
if (last && (last->sig->auth_ids[0] || last->sig->auth_ids[1])) { if (last && (last->sig->auth_ids[0] || last->sig->auth_ids[1])) {
key = x509_request_asymmetric_key(trust_keyring, key = request_asymmetric_key(trust_keyring,
last->sig->auth_ids[0], last->sig->auth_ids[0],
last->sig->auth_ids[1], last->sig->auth_ids[1],
false); false);
if (!IS_ERR(key)) { if (!IS_ERR(key)) {
x509 = last; x509 = last;
pr_devel("sinfo %u: Root cert %u signer is key %x\n", pr_devel("sinfo %u: Root cert %u signer is key %x\n",
...@@ -101,10 +101,10 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, ...@@ -101,10 +101,10 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
/* As a last resort, see if we have a trusted public key that matches /* As a last resort, see if we have a trusted public key that matches
* the signed info directly. * the signed info directly.
*/ */
key = x509_request_asymmetric_key(trust_keyring, key = request_asymmetric_key(trust_keyring,
sinfo->sig->auth_ids[0], sinfo->sig->auth_ids[0],
NULL, NULL,
false); false);
if (!IS_ERR(key)) { if (!IS_ERR(key)) {
pr_devel("sinfo %u: Direct signer is key %x\n", pr_devel("sinfo %u: Direct signer is key %x\n",
sinfo->index, key_serial(key)); sinfo->index, key_serial(key));
......
/* Instantiate a public key crypto key from an X.509 Certificate /* Validate one public key against another to determine trust chaining.
* *
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com) * Written by David Howells (dhowells@redhat.com)
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
...@@ -9,17 +9,10 @@ ...@@ -9,17 +9,10 @@
* 2 of the Licence, or (at your option) any later version. * 2 of the Licence, or (at your option) any later version.
*/ */
#define pr_fmt(fmt) "X.509: "fmt #define pr_fmt(fmt) "PKEY: "fmt
#include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mpi.h>
#include <linux/asn1_decoder.h>
#include <keys/asymmetric-subtype.h>
#include <keys/asymmetric-parser.h>
#include <keys/system_keyring.h>
#include <crypto/hash.h>
#include "asymmetric_keys.h" #include "asymmetric_keys.h"
#include "public_key.h" #include "public_key.h"
#include "x509_parser.h" #include "x509_parser.h"
...@@ -63,21 +56,20 @@ __setup("ca_keys=", ca_keys_setup); ...@@ -63,21 +56,20 @@ __setup("ca_keys=", ca_keys_setup);
#endif #endif
/** /**
* x509_request_asymmetric_key - Request a key by X.509 certificate params. * request_asymmetric_key - Request a key by ID.
* @keyring: The keys to search. * @keyring: The keys to search.
* @id: The issuer & serialNumber to look for or NULL. * @id_0: The first ID to look for or NULL.
* @skid: The subjectKeyIdentifier to look for or NULL. * @id_1: The second ID to look for or NULL.
* @partial: Use partial match if true, exact if false. * @partial: Use partial match if true, exact if false.
* *
* Find a key in the given keyring by identifier. The preferred identifier is * Find a key in the given keyring by identifier. The preferred identifier is
* the issuer + serialNumber and the fallback identifier is the * the id_0 and the fallback identifier is the id_1. If both are given, the
* subjectKeyIdentifier. If both are given, the lookup is by the former, but * lookup is by the former, but the latter must also match.
* the latter must also match.
*/ */
struct key *x509_request_asymmetric_key(struct key *keyring, struct key *request_asymmetric_key(struct key *keyring,
const struct asymmetric_key_id *id, const struct asymmetric_key_id *id_0,
const struct asymmetric_key_id *skid, const struct asymmetric_key_id *id_1,
bool partial) bool partial)
{ {
struct key *key; struct key *key;
key_ref_t ref; key_ref_t ref;
...@@ -85,12 +77,12 @@ struct key *x509_request_asymmetric_key(struct key *keyring, ...@@ -85,12 +77,12 @@ struct key *x509_request_asymmetric_key(struct key *keyring,
char *req, *p; char *req, *p;
int len; int len;
if (id) { if (id_0) {
lookup = id->data; lookup = id_0->data;
len = id->len; len = id_0->len;
} else { } else {
lookup = skid->data; lookup = id_1->data;
len = skid->len; len = id_1->len;
} }
/* Construct an identifier "id:<keyid>". */ /* Construct an identifier "id:<keyid>". */
...@@ -130,14 +122,15 @@ struct key *x509_request_asymmetric_key(struct key *keyring, ...@@ -130,14 +122,15 @@ struct key *x509_request_asymmetric_key(struct key *keyring,
} }
key = key_ref_to_ptr(ref); key = key_ref_to_ptr(ref);
if (id && skid) { if (id_0 && id_1) {
const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
if (!kids->id[1]) {
pr_debug("issuer+serial match, but expected SKID missing\n"); if (!kids->id[0]) {
pr_debug("First ID matches, but second is missing\n");
goto reject; goto reject;
} }
if (!asymmetric_key_id_same(skid, kids->id[1])) { if (!asymmetric_key_id_same(id_1, kids->id[1])) {
pr_debug("issuer+serial match, but SKID does not\n"); pr_debug("First ID matches, but second does not\n");
goto reject; goto reject;
} }
} }
...@@ -149,7 +142,7 @@ struct key *x509_request_asymmetric_key(struct key *keyring, ...@@ -149,7 +142,7 @@ struct key *x509_request_asymmetric_key(struct key *keyring,
key_put(key); key_put(key);
return ERR_PTR(-EKEYREJECTED); return ERR_PTR(-EKEYREJECTED);
} }
EXPORT_SYMBOL_GPL(x509_request_asymmetric_key); EXPORT_SYMBOL_GPL(request_asymmetric_key);
/* /*
* Check the new certificate against the ones in the trust keyring. If one of * Check the new certificate against the ones in the trust keyring. If one of
...@@ -177,9 +170,8 @@ int x509_validate_trust(struct x509_certificate *cert, ...@@ -177,9 +170,8 @@ int x509_validate_trust(struct x509_certificate *cert,
if (cert->unsupported_sig) if (cert->unsupported_sig)
return -ENOPKG; return -ENOPKG;
key = x509_request_asymmetric_key(trust_keyring, key = request_asymmetric_key(trust_keyring,
sig->auth_ids[0], sig->auth_ids[1], sig->auth_ids[0], sig->auth_ids[1], false);
false);
if (IS_ERR(key)) if (IS_ERR(key))
return PTR_ERR(key); return PTR_ERR(key);
......
...@@ -102,9 +102,9 @@ extern int verify_signature(const struct key *key, ...@@ -102,9 +102,9 @@ extern int verify_signature(const struct key *key,
const struct public_key_signature *sig); const struct public_key_signature *sig);
struct asymmetric_key_id; struct asymmetric_key_id;
extern struct key *x509_request_asymmetric_key(struct key *keyring, extern struct key *request_asymmetric_key(struct key *keyring,
const struct asymmetric_key_id *id, const struct asymmetric_key_id *id_0,
const struct asymmetric_key_id *skid, const struct asymmetric_key_id *id_1,
bool partial); bool partial);
#endif /* _LINUX_PUBLIC_KEY_H */ #endif /* _LINUX_PUBLIC_KEY_H */
...@@ -24,7 +24,8 @@ ...@@ -24,7 +24,8 @@
/* /*
* Request an asymmetric key. * Request an asymmetric key.
*/ */
static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) static struct key *ds_request_asymmetric_key(struct key *keyring,
uint32_t keyid)
{ {
struct key *key; struct key *key;
char name[12]; char name[12];
...@@ -97,7 +98,7 @@ int asymmetric_verify(struct key *keyring, const char *sig, ...@@ -97,7 +98,7 @@ int asymmetric_verify(struct key *keyring, const char *sig,
if (hdr->hash_algo >= PKEY_HASH__LAST) if (hdr->hash_algo >= PKEY_HASH__LAST)
return -ENOPKG; return -ENOPKG;
key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid)); key = ds_request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid));
if (IS_ERR(key)) if (IS_ERR(key))
return PTR_ERR(key); return PTR_ERR(key);
......
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