// SPDX-License-Identifier: GPL-2.0-or-later1/* Instantiate a public key crypto key from an X.509 Certificate2*3* Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved.4* Written by David Howells ([email protected])5*/67#define pr_fmt(fmt) "ASYM: "fmt8#include <linux/module.h>9#include <linux/kernel.h>10#include <linux/err.h>11#include <crypto/public_key.h>12#include "asymmetric_keys.h"1314static bool use_builtin_keys;15static struct asymmetric_key_id *ca_keyid;1617#ifndef MODULE18static struct {19struct asymmetric_key_id id;20unsigned char data[10];21} cakey;2223static int __init ca_keys_setup(char *str)24{25if (!str) /* default system keyring */26return 1;2728if (strncmp(str, "id:", 3) == 0) {29struct asymmetric_key_id *p = &cakey.id;30size_t hexlen = (strlen(str) - 3) / 2;31int ret;3233if (hexlen == 0 || hexlen > sizeof(cakey.data)) {34pr_err("Missing or invalid ca_keys id\n");35return 1;36}3738ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen);39if (ret < 0)40pr_err("Unparsable ca_keys id hex string\n");41else42ca_keyid = p; /* owner key 'id:xxxxxx' */43} else if (strcmp(str, "builtin") == 0) {44use_builtin_keys = true;45}4647return 1;48}49__setup("ca_keys=", ca_keys_setup);50#endif5152/**53* restrict_link_by_signature - Restrict additions to a ring of public keys54* @dest_keyring: Keyring being linked to.55* @type: The type of key being added.56* @payload: The payload of the new key.57* @trust_keyring: A ring of keys that can be used to vouch for the new cert.58*59* Check the new certificate against the ones in the trust keyring. If one of60* those is the signing key and validates the new certificate, then mark the61* new certificate as being trusted.62*63* Returns 0 if the new certificate was accepted, -ENOKEY if we couldn't find a64* matching parent certificate in the trusted list, -EKEYREJECTED if the65* signature check fails or the key is blacklisted, -ENOPKG if the signature66* uses unsupported crypto, or some other error if there is a matching67* certificate but the signature check cannot be performed.68*/69int restrict_link_by_signature(struct key *dest_keyring,70const struct key_type *type,71const union key_payload *payload,72struct key *trust_keyring)73{74const struct public_key_signature *sig;75struct key *key;76int ret;7778pr_devel("==>%s()\n", __func__);7980if (!trust_keyring)81return -ENOKEY;8283if (type != &key_type_asymmetric)84return -EOPNOTSUPP;8586sig = payload->data[asym_auth];87if (!sig)88return -ENOPKG;89if (!sig->auth_ids[0] && !sig->auth_ids[1] && !sig->auth_ids[2])90return -ENOKEY;9192if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid))93return -EPERM;9495/* See if we have a key that signed this one. */96key = find_asymmetric_key(trust_keyring,97sig->auth_ids[0], sig->auth_ids[1],98sig->auth_ids[2], false);99if (IS_ERR(key))100return -ENOKEY;101102if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags))103ret = -ENOKEY;104else if (IS_BUILTIN(CONFIG_SECONDARY_TRUSTED_KEYRING_SIGNED_BY_BUILTIN) &&105!strcmp(dest_keyring->description, ".secondary_trusted_keys") &&106!test_bit(KEY_FLAG_BUILTIN, &key->flags))107ret = -ENOKEY;108else109ret = verify_signature(key, sig);110key_put(key);111return ret;112}113114/**115* restrict_link_by_ca - Restrict additions to a ring of CA keys116* @dest_keyring: Keyring being linked to.117* @type: The type of key being added.118* @payload: The payload of the new key.119* @trust_keyring: Unused.120*121* Check if the new certificate is a CA. If it is a CA, then mark the new122* certificate as being ok to link.123*124* Returns 0 if the new certificate was accepted, -ENOKEY if the125* certificate is not a CA. -ENOPKG if the signature uses unsupported126* crypto, or some other error if there is a matching certificate but127* the signature check cannot be performed.128*/129int restrict_link_by_ca(struct key *dest_keyring,130const struct key_type *type,131const union key_payload *payload,132struct key *trust_keyring)133{134const struct public_key *pkey;135136if (type != &key_type_asymmetric)137return -EOPNOTSUPP;138139pkey = payload->data[asym_crypto];140if (!pkey)141return -ENOPKG;142if (!test_bit(KEY_EFLAG_CA, &pkey->key_eflags))143return -ENOKEY;144if (!test_bit(KEY_EFLAG_KEYCERTSIGN, &pkey->key_eflags))145return -ENOKEY;146if (!IS_ENABLED(CONFIG_INTEGRITY_CA_MACHINE_KEYRING_MAX))147return 0;148if (test_bit(KEY_EFLAG_DIGITALSIG, &pkey->key_eflags))149return -ENOKEY;150151return 0;152}153154/**155* restrict_link_by_digsig - Restrict additions to a ring of digsig keys156* @dest_keyring: Keyring being linked to.157* @type: The type of key being added.158* @payload: The payload of the new key.159* @trust_keyring: A ring of keys that can be used to vouch for the new cert.160*161* Check if the new certificate has digitalSignature usage set. If it is,162* then mark the new certificate as being ok to link. Afterwards verify163* the new certificate against the ones in the trust_keyring.164*165* Returns 0 if the new certificate was accepted, -ENOKEY if the166* certificate is not a digsig. -ENOPKG if the signature uses unsupported167* crypto, or some other error if there is a matching certificate but168* the signature check cannot be performed.169*/170int restrict_link_by_digsig(struct key *dest_keyring,171const struct key_type *type,172const union key_payload *payload,173struct key *trust_keyring)174{175const struct public_key *pkey;176177if (type != &key_type_asymmetric)178return -EOPNOTSUPP;179180pkey = payload->data[asym_crypto];181182if (!pkey)183return -ENOPKG;184185if (!test_bit(KEY_EFLAG_DIGITALSIG, &pkey->key_eflags))186return -ENOKEY;187188if (test_bit(KEY_EFLAG_CA, &pkey->key_eflags))189return -ENOKEY;190191if (test_bit(KEY_EFLAG_KEYCERTSIGN, &pkey->key_eflags))192return -ENOKEY;193194return restrict_link_by_signature(dest_keyring, type, payload,195trust_keyring);196}197198static bool match_either_id(const struct asymmetric_key_id **pair,199const struct asymmetric_key_id *single)200{201return (asymmetric_key_id_same(pair[0], single) ||202asymmetric_key_id_same(pair[1], single));203}204205static int key_or_keyring_common(struct key *dest_keyring,206const struct key_type *type,207const union key_payload *payload,208struct key *trusted, bool check_dest)209{210const struct public_key_signature *sig;211struct key *key = NULL;212int ret;213214pr_devel("==>%s()\n", __func__);215216if (!dest_keyring)217return -ENOKEY;218else if (dest_keyring->type != &key_type_keyring)219return -EOPNOTSUPP;220221if (!trusted && !check_dest)222return -ENOKEY;223224if (type != &key_type_asymmetric)225return -EOPNOTSUPP;226227sig = payload->data[asym_auth];228if (!sig)229return -ENOPKG;230if (!sig->auth_ids[0] && !sig->auth_ids[1] && !sig->auth_ids[2])231return -ENOKEY;232233if (trusted) {234if (trusted->type == &key_type_keyring) {235/* See if we have a key that signed this one. */236key = find_asymmetric_key(trusted, sig->auth_ids[0],237sig->auth_ids[1],238sig->auth_ids[2], false);239if (IS_ERR(key))240key = NULL;241} else if (trusted->type == &key_type_asymmetric) {242const struct asymmetric_key_id **signer_ids;243244signer_ids = (const struct asymmetric_key_id **)245asymmetric_key_ids(trusted)->id;246247/*248* The auth_ids come from the candidate key (the249* one that is being considered for addition to250* dest_keyring) and identify the key that was251* used to sign.252*253* The signer_ids are identifiers for the254* signing key specified for dest_keyring.255*256* The first auth_id is the preferred id, 2nd and257* 3rd are the fallbacks. If exactly one of258* auth_ids[0] and auth_ids[1] is present, it may259* match either signer_ids[0] or signed_ids[1].260* If both are present the first one may match261* either signed_id but the second one must match262* the second signer_id. If neither of them is263* available, auth_ids[2] is matched against264* signer_ids[2] as a fallback.265*/266if (!sig->auth_ids[0] && !sig->auth_ids[1]) {267if (asymmetric_key_id_same(signer_ids[2],268sig->auth_ids[2]))269key = __key_get(trusted);270271} else if (!sig->auth_ids[0] || !sig->auth_ids[1]) {272const struct asymmetric_key_id *auth_id;273274auth_id = sig->auth_ids[0] ?: sig->auth_ids[1];275if (match_either_id(signer_ids, auth_id))276key = __key_get(trusted);277278} else if (asymmetric_key_id_same(signer_ids[1],279sig->auth_ids[1]) &&280match_either_id(signer_ids,281sig->auth_ids[0])) {282key = __key_get(trusted);283}284} else {285return -EOPNOTSUPP;286}287}288289if (check_dest && !key) {290/* See if the destination has a key that signed this one. */291key = find_asymmetric_key(dest_keyring, sig->auth_ids[0],292sig->auth_ids[1], sig->auth_ids[2],293false);294if (IS_ERR(key))295key = NULL;296}297298if (!key)299return -ENOKEY;300301ret = key_validate(key);302if (ret == 0)303ret = verify_signature(key, sig);304305key_put(key);306return ret;307}308309/**310* restrict_link_by_key_or_keyring - Restrict additions to a ring of public311* keys using the restrict_key information stored in the ring.312* @dest_keyring: Keyring being linked to.313* @type: The type of key being added.314* @payload: The payload of the new key.315* @trusted: A key or ring of keys that can be used to vouch for the new cert.316*317* Check the new certificate only against the key or keys passed in the data318* parameter. If one of those is the signing key and validates the new319* certificate, then mark the new certificate as being ok to link.320*321* Returns 0 if the new certificate was accepted, -ENOKEY if we322* couldn't find a matching parent certificate in the trusted list,323* -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses324* unsupported crypto, or some other error if there is a matching certificate325* but the signature check cannot be performed.326*/327int restrict_link_by_key_or_keyring(struct key *dest_keyring,328const struct key_type *type,329const union key_payload *payload,330struct key *trusted)331{332return key_or_keyring_common(dest_keyring, type, payload, trusted,333false);334}335336/**337* restrict_link_by_key_or_keyring_chain - Restrict additions to a ring of338* public keys using the restrict_key information stored in the ring.339* @dest_keyring: Keyring being linked to.340* @type: The type of key being added.341* @payload: The payload of the new key.342* @trusted: A key or ring of keys that can be used to vouch for the new cert.343*344* Check the new certificate against the key or keys passed in the data345* parameter and against the keys already linked to the destination keyring. If346* one of those is the signing key and validates the new certificate, then mark347* the new certificate as being ok to link.348*349* Returns 0 if the new certificate was accepted, -ENOKEY if we350* couldn't find a matching parent certificate in the trusted list,351* -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses352* unsupported crypto, or some other error if there is a matching certificate353* but the signature check cannot be performed.354*/355int restrict_link_by_key_or_keyring_chain(struct key *dest_keyring,356const struct key_type *type,357const union key_payload *payload,358struct key *trusted)359{360return key_or_keyring_common(dest_keyring, type, payload, trusted,361true);362}363364365