diff options
Diffstat (limited to 'crypto/asymmetric_keys/pkcs7_verify.c')
-rw-r--r-- | crypto/asymmetric_keys/pkcs7_verify.c | 65 |
1 files changed, 63 insertions, 2 deletions
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index 404f89a0f852..d20c0b4b880e 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -70,9 +70,15 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, * message digest attribute amongst them which corresponds to the * digest we just calculated. */ - if (sinfo->msgdigest) { + if (sinfo->authattrs) { u8 tag; + if (!sinfo->msgdigest) { + pr_warn("Sig %u: No messageDigest\n", sinfo->index); + ret = -EKEYREJECTED; + goto error; + } + if (sinfo->msgdigest_len != sinfo->sig.digest_size) { pr_debug("Sig %u: Invalid digest size (%u)\n", sinfo->index, sinfo->msgdigest_len); @@ -314,6 +320,18 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, pr_devel("Using X.509[%u] for sig %u\n", sinfo->signer->index, sinfo->index); + /* Check that the PKCS#7 signing time is valid according to the X.509 + * certificate. We can't, however, check against the system clock + * since that may not have been set yet and may be wrong. + */ + if (test_bit(sinfo_has_signing_time, &sinfo->aa_set)) { + if (sinfo->signing_time < sinfo->signer->valid_from || + sinfo->signing_time > sinfo->signer->valid_to) { + pr_warn("Message signed outside of X.509 validity window\n"); + return -EKEYREJECTED; + } + } + /* Verify the PKCS#7 binary against the key */ ret = public_key_verify_signature(sinfo->signer->pub, &sinfo->sig); if (ret < 0) @@ -328,6 +346,7 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, /** * pkcs7_verify - Verify a PKCS#7 message * @pkcs7: The PKCS#7 message to be verified + * @usage: The use to which the key is being put * * Verify a PKCS#7 message is internally consistent - that is, the data digest * matches the digest in the AuthAttrs and any signature in the message or one @@ -339,6 +358,9 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, * * Returns, in order of descending priority: * + * (*) -EKEYREJECTED if a key was selected that had a usage restriction at + * odds with the specified usage, or: + * * (*) -EKEYREJECTED if a signature failed to match for which we found an * appropriate X.509 certificate, or: * @@ -350,7 +372,8 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, * (*) 0 if all the signature chains that don't incur -ENOPKG can be verified * (note that a signature chain may be of zero length), or: */ -int pkcs7_verify(struct pkcs7_message *pkcs7) +int pkcs7_verify(struct pkcs7_message *pkcs7, + enum key_being_used_for usage) { struct pkcs7_signed_info *sinfo; struct x509_certificate *x509; @@ -359,6 +382,44 @@ int pkcs7_verify(struct pkcs7_message *pkcs7) kenter(""); + switch (usage) { + case VERIFYING_MODULE_SIGNATURE: + if (pkcs7->data_type != OID_data) { + pr_warn("Invalid module sig (not pkcs7-data)\n"); + return -EKEYREJECTED; + } + if (pkcs7->have_authattrs) { + pr_warn("Invalid module sig (has authattrs)\n"); + return -EKEYREJECTED; + } + break; + case VERIFYING_FIRMWARE_SIGNATURE: + if (pkcs7->data_type != OID_data) { + pr_warn("Invalid firmware sig (not pkcs7-data)\n"); + return -EKEYREJECTED; + } + if (!pkcs7->have_authattrs) { + pr_warn("Invalid firmware sig (missing authattrs)\n"); + return -EKEYREJECTED; + } + break; + case VERIFYING_KEXEC_PE_SIGNATURE: + if (pkcs7->data_type != OID_msIndirectData) { + pr_warn("Invalid kexec sig (not Authenticode)\n"); + return -EKEYREJECTED; + } + /* Authattr presence checked in parser */ + break; + case VERIFYING_UNSPECIFIED_SIGNATURE: + if (pkcs7->data_type != OID_data) { + pr_warn("Invalid unspecified sig (not pkcs7-data)\n"); + return -EKEYREJECTED; + } + break; + default: + return -EINVAL; + } + for (n = 0, x509 = pkcs7->certs; x509; x509 = x509->next, n++) { ret = x509_get_sig_params(x509); if (ret < 0) |