mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-16 17:23:55 +08:00
KEYS: Restore partial ID matching functionality for asymmetric keys
Bring back the functionality whereby an asymmetric key can be matched with a partial match on one of its IDs. Whilst we're at it, allow for the possibility of having an increased number of IDs. Reported-by: Dmitry Kasatkin <d.kasatkin@samsung.com> Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com> Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
parent
dd2f6c4481
commit
f1b731dbc2
@ -9,9 +9,6 @@
|
|||||||
* 2 of the Licence, or (at your option) any later version.
|
* 2 of the Licence, or (at your option) any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern bool asymmetric_match_key_ids(const struct asymmetric_key_ids *kids,
|
|
||||||
const struct asymmetric_key_id *match_id);
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
|
@ -65,23 +65,44 @@ bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(asymmetric_key_id_same);
|
EXPORT_SYMBOL_GPL(asymmetric_key_id_same);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* asymmetric_key_id_partial - Return true if two asymmetric keys IDs
|
||||||
|
* partially match
|
||||||
|
* @kid_1, @kid_2: The key IDs to compare
|
||||||
|
*/
|
||||||
|
bool asymmetric_key_id_partial(const struct asymmetric_key_id *kid1,
|
||||||
|
const struct asymmetric_key_id *kid2)
|
||||||
|
{
|
||||||
|
if (!kid1 || !kid2)
|
||||||
|
return false;
|
||||||
|
if (kid1->len < kid2->len)
|
||||||
|
return false;
|
||||||
|
return memcmp(kid1->data + (kid1->len - kid2->len),
|
||||||
|
kid2->data, kid2->len) == 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(asymmetric_key_id_partial);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* asymmetric_match_key_ids - Search asymmetric key IDs
|
* asymmetric_match_key_ids - Search asymmetric key IDs
|
||||||
* @kids: The list of key IDs to check
|
* @kids: The list of key IDs to check
|
||||||
* @match_id: The key ID we're looking for
|
* @match_id: The key ID we're looking for
|
||||||
|
* @match: The match function to use
|
||||||
*/
|
*/
|
||||||
bool asymmetric_match_key_ids(const struct asymmetric_key_ids *kids,
|
static bool asymmetric_match_key_ids(
|
||||||
const struct asymmetric_key_id *match_id)
|
const struct asymmetric_key_ids *kids,
|
||||||
|
const struct asymmetric_key_id *match_id,
|
||||||
|
bool (*match)(const struct asymmetric_key_id *kid1,
|
||||||
|
const struct asymmetric_key_id *kid2))
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!kids || !match_id)
|
if (!kids || !match_id)
|
||||||
return false;
|
return false;
|
||||||
if (asymmetric_key_id_same(kids->id[0], match_id))
|
for (i = 0; i < ARRAY_SIZE(kids->id); i++)
|
||||||
return true;
|
if (match(kids->id[i], match_id))
|
||||||
if (asymmetric_key_id_same(kids->id[1], match_id))
|
return true;
|
||||||
return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(asymmetric_match_key_ids);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* asymmetric_key_hex_to_key_id - Convert a hex string into a key ID.
|
* asymmetric_key_hex_to_key_id - Convert a hex string into a key ID.
|
||||||
@ -113,7 +134,7 @@ struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Match asymmetric keys by ID.
|
* Match asymmetric keys by an exact match on an ID.
|
||||||
*/
|
*/
|
||||||
static bool asymmetric_key_cmp(const struct key *key,
|
static bool asymmetric_key_cmp(const struct key *key,
|
||||||
const struct key_match_data *match_data)
|
const struct key_match_data *match_data)
|
||||||
@ -121,7 +142,21 @@ static bool asymmetric_key_cmp(const struct key *key,
|
|||||||
const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
|
const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
|
||||||
const struct asymmetric_key_id *match_id = match_data->preparsed;
|
const struct asymmetric_key_id *match_id = match_data->preparsed;
|
||||||
|
|
||||||
return asymmetric_match_key_ids(kids, match_id);
|
return asymmetric_match_key_ids(kids, match_id,
|
||||||
|
asymmetric_key_id_same);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Match asymmetric keys by a partial match on an IDs.
|
||||||
|
*/
|
||||||
|
static bool asymmetric_key_cmp_partial(const struct key *key,
|
||||||
|
const struct key_match_data *match_data)
|
||||||
|
{
|
||||||
|
const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
|
||||||
|
const struct asymmetric_key_id *match_id = match_data->preparsed;
|
||||||
|
|
||||||
|
return asymmetric_match_key_ids(kids, match_id,
|
||||||
|
asymmetric_key_id_partial);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -131,7 +166,8 @@ static bool asymmetric_key_cmp(const struct key *key,
|
|||||||
* There are some specifiers for matching key IDs rather than by the key
|
* There are some specifiers for matching key IDs rather than by the key
|
||||||
* description:
|
* description:
|
||||||
*
|
*
|
||||||
* "id:<id>" - request a key by any available ID
|
* "id:<id>" - find a key by partial match on any available ID
|
||||||
|
* "ex:<id>" - find a key by exact match on any available ID
|
||||||
*
|
*
|
||||||
* These have to be searched by iteration rather than by direct lookup because
|
* These have to be searched by iteration rather than by direct lookup because
|
||||||
* the key is hashed according to its description.
|
* the key is hashed according to its description.
|
||||||
@ -141,6 +177,8 @@ static int asymmetric_key_match_preparse(struct key_match_data *match_data)
|
|||||||
struct asymmetric_key_id *match_id;
|
struct asymmetric_key_id *match_id;
|
||||||
const char *spec = match_data->raw_data;
|
const char *spec = match_data->raw_data;
|
||||||
const char *id;
|
const char *id;
|
||||||
|
bool (*cmp)(const struct key *, const struct key_match_data *) =
|
||||||
|
asymmetric_key_cmp;
|
||||||
|
|
||||||
if (!spec || !*spec)
|
if (!spec || !*spec)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -148,6 +186,11 @@ static int asymmetric_key_match_preparse(struct key_match_data *match_data)
|
|||||||
spec[1] == 'd' &&
|
spec[1] == 'd' &&
|
||||||
spec[2] == ':') {
|
spec[2] == ':') {
|
||||||
id = spec + 3;
|
id = spec + 3;
|
||||||
|
cmp = asymmetric_key_cmp_partial;
|
||||||
|
} else if (spec[0] == 'e' &&
|
||||||
|
spec[1] == 'x' &&
|
||||||
|
spec[2] == ':') {
|
||||||
|
id = spec + 3;
|
||||||
} else {
|
} else {
|
||||||
goto default_match;
|
goto default_match;
|
||||||
}
|
}
|
||||||
@ -157,7 +200,7 @@ static int asymmetric_key_match_preparse(struct key_match_data *match_data)
|
|||||||
return PTR_ERR(match_id);
|
return PTR_ERR(match_id);
|
||||||
|
|
||||||
match_data->preparsed = match_id;
|
match_data->preparsed = match_id;
|
||||||
match_data->cmp = asymmetric_key_cmp;
|
match_data->cmp = cmp;
|
||||||
match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE;
|
match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -251,6 +294,7 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
|
|||||||
{
|
{
|
||||||
struct asymmetric_key_subtype *subtype = prep->type_data[0];
|
struct asymmetric_key_subtype *subtype = prep->type_data[0];
|
||||||
struct asymmetric_key_ids *kids = prep->type_data[1];
|
struct asymmetric_key_ids *kids = prep->type_data[1];
|
||||||
|
int i;
|
||||||
|
|
||||||
pr_devel("==>%s()\n", __func__);
|
pr_devel("==>%s()\n", __func__);
|
||||||
|
|
||||||
@ -259,8 +303,8 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
|
|||||||
module_put(subtype->owner);
|
module_put(subtype->owner);
|
||||||
}
|
}
|
||||||
if (kids) {
|
if (kids) {
|
||||||
kfree(kids->id[0]);
|
for (i = 0; i < ARRAY_SIZE(kids->id); i++)
|
||||||
kfree(kids->id[1]);
|
kfree(kids->id[i]);
|
||||||
kfree(kids);
|
kfree(kids);
|
||||||
}
|
}
|
||||||
kfree(prep->description);
|
kfree(prep->description);
|
||||||
|
@ -54,7 +54,8 @@ 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, x509->id);
|
key = x509_request_asymmetric_key(trust_keyring, x509->id,
|
||||||
|
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.
|
||||||
@ -85,7 +86,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
|
|||||||
* trusted keys.
|
* trusted keys.
|
||||||
*/
|
*/
|
||||||
if (last && last->authority) {
|
if (last && last->authority) {
|
||||||
key = x509_request_asymmetric_key(trust_keyring, last->authority);
|
key = x509_request_asymmetric_key(trust_keyring, last->authority,
|
||||||
|
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",
|
||||||
@ -100,7 +102,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
|
|||||||
* the signed info directly.
|
* the signed info directly.
|
||||||
*/
|
*/
|
||||||
key = x509_request_asymmetric_key(trust_keyring,
|
key = x509_request_asymmetric_key(trust_keyring,
|
||||||
sinfo->signing_cert_id);
|
sinfo->signing_cert_id,
|
||||||
|
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));
|
||||||
|
@ -53,13 +53,15 @@ __setup("ca_keys=", ca_keys_setup);
|
|||||||
* x509_request_asymmetric_key - Request a key by X.509 certificate params.
|
* x509_request_asymmetric_key - Request a key by X.509 certificate params.
|
||||||
* @keyring: The keys to search.
|
* @keyring: The keys to search.
|
||||||
* @kid: The key ID.
|
* @kid: The key ID.
|
||||||
|
* @partial: Use partial match if true, exact if false.
|
||||||
*
|
*
|
||||||
* Find a key in the given keyring by subject name and key ID. These might,
|
* Find a key in the given keyring by subject name and key ID. These might,
|
||||||
* for instance, be the issuer name and the authority key ID of an X.509
|
* for instance, be the issuer name and the authority key ID of an X.509
|
||||||
* certificate that needs to be verified.
|
* certificate that needs to be verified.
|
||||||
*/
|
*/
|
||||||
struct key *x509_request_asymmetric_key(struct key *keyring,
|
struct key *x509_request_asymmetric_key(struct key *keyring,
|
||||||
const struct asymmetric_key_id *kid)
|
const struct asymmetric_key_id *kid,
|
||||||
|
bool partial)
|
||||||
{
|
{
|
||||||
key_ref_t key;
|
key_ref_t key;
|
||||||
char *id, *p;
|
char *id, *p;
|
||||||
@ -69,8 +71,13 @@ struct key *x509_request_asymmetric_key(struct key *keyring,
|
|||||||
if (!id)
|
if (!id)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
*p++ = 'i';
|
if (partial) {
|
||||||
*p++ = 'd';
|
*p++ = 'i';
|
||||||
|
*p++ = 'd';
|
||||||
|
} else {
|
||||||
|
*p++ = 'e';
|
||||||
|
*p++ = 'x';
|
||||||
|
}
|
||||||
*p++ = ':';
|
*p++ = ':';
|
||||||
p = bin2hex(p, kid->data, kid->len);
|
p = bin2hex(p, kid->data, kid->len);
|
||||||
*p = 0;
|
*p = 0;
|
||||||
@ -207,10 +214,11 @@ static int x509_validate_trust(struct x509_certificate *cert,
|
|||||||
if (!trust_keyring)
|
if (!trust_keyring)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (ca_keyid && !asymmetric_key_id_same(cert->authority, ca_keyid))
|
if (ca_keyid && !asymmetric_key_id_partial(cert->authority, ca_keyid))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
key = x509_request_asymmetric_key(trust_keyring, cert->authority);
|
key = x509_request_asymmetric_key(trust_keyring, cert->authority,
|
||||||
|
false);
|
||||||
if (!IS_ERR(key)) {
|
if (!IS_ERR(key)) {
|
||||||
if (!use_builtin_keys
|
if (!use_builtin_keys
|
||||||
|| test_bit(KEY_FLAG_BUILTIN, &key->flags))
|
|| test_bit(KEY_FLAG_BUILTIN, &key->flags))
|
||||||
|
@ -101,6 +101,7 @@ extern int verify_signature(const struct key *key,
|
|||||||
|
|
||||||
struct asymmetric_key_id;
|
struct asymmetric_key_id;
|
||||||
extern struct key *x509_request_asymmetric_key(struct key *keyring,
|
extern struct key *x509_request_asymmetric_key(struct key *keyring,
|
||||||
const struct asymmetric_key_id *kid);
|
const struct asymmetric_key_id *kid,
|
||||||
|
bool partial);
|
||||||
|
|
||||||
#endif /* _LINUX_PUBLIC_KEY_H */
|
#endif /* _LINUX_PUBLIC_KEY_H */
|
||||||
|
@ -51,6 +51,9 @@ struct asymmetric_key_ids {
|
|||||||
extern bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
|
extern bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
|
||||||
const struct asymmetric_key_id *kid2);
|
const struct asymmetric_key_id *kid2);
|
||||||
|
|
||||||
|
extern bool asymmetric_key_id_partial(const struct asymmetric_key_id *kid1,
|
||||||
|
const struct asymmetric_key_id *kid2);
|
||||||
|
|
||||||
extern struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1,
|
extern struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1,
|
||||||
size_t len_1,
|
size_t len_1,
|
||||||
const void *val_2,
|
const void *val_2,
|
||||||
|
Loading…
Reference in New Issue
Block a user