diff options
author | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2015-09-13 11:10:12 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2015-09-13 11:10:12 -0300 |
commit | 64af4a27c71a2e29a1ea4f7ee1848dec09f146df (patch) | |
tree | 656970a5239e257a9a4ba5b333d8b547233c6b94 /crypto/asymmetric_keys/x509_public_key.c | |
parent | 2d361b75fadcca0a45fc1dccc96c3c74ce80dd6c (diff) | |
parent | fc4d0d2a1b069a231939ca4b01a3d003e77c723a (diff) | |
download | linux-crypto-64af4a27c71a2e29a1ea4f7ee1848dec09f146df.tar.gz linux-crypto-64af4a27c71a2e29a1ea4f7ee1848dec09f146df.zip |
Merge tag 'v4.3-rc1' into patchwork
Linux 4.3-rc1
* tag 'v4.3-rc1': (11838 commits)
Linux 4.3-rc1
blk: rq_data_dir() should not return a boolean
writeback: plug writeback in wb_writeback() and writeback_inodes_wb()
thermal: fix intel PCH thermal driver mismerge
ARCv2: [axs103_smp] Reduce clk for SMP FPGA configs
revert "ocfs2/dlm: use list_for_each_entry instead of list_for_each"
mm/early_ioremap: add explicit #include of asm/early_ioremap.h
fs/seq_file: convert int seq_vprint/seq_printf/etc... returns to void
selftests: enhance membarrier syscall test
selftests: add membarrier syscall test
sys_membarrier(): system-wide memory barrier (generic, x86)
MODSIGN: fix a compilation warning in extract-cert
Revert "writeback: plug writeback at a high level"
scsi_dh: fix randconfig build error
target: use stringify.h instead of own definition
target/user: Fix UFLAG_UNKNOWN_OP handling
target: Remove no-op conditional
target/user: Remove unused variable
target: Fix max_cmd_sn increment w/o cmdsn mutex regressions
target: Attach EXTENDED_COPY local I/O descriptors to xcopy_pt_sess
...
Diffstat (limited to '')
-rw-r--r-- | crypto/asymmetric_keys/x509_public_key.c | 95 |
1 files changed, 60 insertions, 35 deletions
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 24f17e6c..6d88dd15 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -65,23 +65,37 @@ __setup("ca_keys=", ca_keys_setup); /** * x509_request_asymmetric_key - Request a key by X.509 certificate params. * @keyring: The keys to search. - * @kid: The key ID. + * @id: The issuer & serialNumber to look for or NULL. + * @skid: The subjectKeyIdentifier to look for or NULL. * @partial: Use partial match if true, exact if false. * - * 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 - * certificate that needs to be verified. + * Find a key in the given keyring by identifier. The preferred identifier is + * the issuer + serialNumber and the fallback identifier is the + * subjectKeyIdentifier. If both are given, the lookup is by the former, but + * the latter must also match. */ struct key *x509_request_asymmetric_key(struct key *keyring, - const struct asymmetric_key_id *kid, + const struct asymmetric_key_id *id, + const struct asymmetric_key_id *skid, bool partial) { - key_ref_t key; - char *id, *p; - + struct key *key; + key_ref_t ref; + const char *lookup; + char *req, *p; + int len; + + if (id) { + lookup = id->data; + len = id->len; + } else { + lookup = skid->data; + len = skid->len; + } + /* Construct an identifier "id:<keyid>". */ - p = id = kmalloc(2 + 1 + kid->len * 2 + 1, GFP_KERNEL); - if (!id) + p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL); + if (!req) return ERR_PTR(-ENOMEM); if (partial) { @@ -92,32 +106,48 @@ struct key *x509_request_asymmetric_key(struct key *keyring, *p++ = 'x'; } *p++ = ':'; - p = bin2hex(p, kid->data, kid->len); + p = bin2hex(p, lookup, len); *p = 0; - pr_debug("Look up: \"%s\"\n", id); + pr_debug("Look up: \"%s\"\n", req); - key = keyring_search(make_key_ref(keyring, 1), - &key_type_asymmetric, id); - if (IS_ERR(key)) - pr_debug("Request for key '%s' err %ld\n", id, PTR_ERR(key)); - kfree(id); + ref = keyring_search(make_key_ref(keyring, 1), + &key_type_asymmetric, req); + if (IS_ERR(ref)) + pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref)); + kfree(req); - if (IS_ERR(key)) { - switch (PTR_ERR(key)) { + if (IS_ERR(ref)) { + switch (PTR_ERR(ref)) { /* Hide some search errors */ case -EACCES: case -ENOTDIR: case -EAGAIN: return ERR_PTR(-ENOKEY); default: - return ERR_CAST(key); + return ERR_CAST(ref); + } + } + + key = key_ref_to_ptr(ref); + if (id && skid) { + const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); + if (!kids->id[1]) { + pr_debug("issuer+serial match, but expected SKID missing\n"); + goto reject; + } + if (!asymmetric_key_id_same(skid, kids->id[1])) { + pr_debug("issuer+serial match, but SKID does not\n"); + goto reject; } } + + pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key)); + return key; - pr_devel("<==%s() = 0 [%x]\n", __func__, - key_serial(key_ref_to_ptr(key))); - return key_ref_to_ptr(key); +reject: + key_put(key); + return ERR_PTR(-EKEYREJECTED); } EXPORT_SYMBOL_GPL(x509_request_asymmetric_key); @@ -227,10 +257,11 @@ static int x509_validate_trust(struct x509_certificate *cert, if (!trust_keyring) return -EOPNOTSUPP; - if (ca_keyid && !asymmetric_key_id_partial(cert->authority, ca_keyid)) + if (ca_keyid && !asymmetric_key_id_partial(cert->akid_skid, ca_keyid)) return -EPERM; - key = x509_request_asymmetric_key(trust_keyring, cert->authority, + key = x509_request_asymmetric_key(trust_keyring, + cert->akid_id, cert->akid_skid, false); if (!IS_ERR(key)) { if (!use_builtin_keys @@ -271,14 +302,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) } pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); - pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", - cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, - cert->valid_from.tm_mday, cert->valid_from.tm_hour, - cert->valid_from.tm_min, cert->valid_from.tm_sec); - pr_devel("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", - cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1, - cert->valid_to.tm_mday, cert->valid_to.tm_hour, - cert->valid_to.tm_min, cert->valid_to.tm_sec); + pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to); pr_devel("Cert Signature: %s + %s\n", pkey_algo_name[cert->sig.pkey_algo], hash_algo_name[cert->sig.pkey_hash_algo]); @@ -287,8 +311,9 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) cert->pub->id_type = PKEY_ID_X509; /* Check the signature on the key if it appears to be self-signed */ - if (!cert->authority || - asymmetric_key_id_same(cert->skid, cert->authority)) { + if ((!cert->akid_skid && !cert->akid_id) || + asymmetric_key_id_same(cert->skid, cert->akid_skid) || + asymmetric_key_id_same(cert->id, cert->akid_id)) { ret = x509_check_signature(cert->pub, cert); /* self-signed */ if (ret < 0) goto error_free_cert; |