From patchwork Tue Jun 9 05:13:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 241972 List-Id: U-Boot discussion From: takahiro.akashi at linaro.org (AKASHI Takahiro) Date: Tue, 9 Jun 2020 14:13:58 +0900 Subject: [PATCH 5/8] lib: crypto: add pkcs7_digest() In-Reply-To: <20200609051401.18192-1-takahiro.akashi@linaro.org> References: <20200609051401.18192-1-takahiro.akashi@linaro.org> Message-ID: <20200609051401.18192-6-takahiro.akashi@linaro.org> This function was nullified when the file, pkcs7_verify.c, was imported because it calls further linux-specific interfaces inside, hence that could lead to more files being imported from linux. We need this function in pkcs7_verify_one() and so simply re-implement it here instead of re-using the code. Signed-off-by: AKASHI Takahiro --- lib/crypto/pkcs7_verify.c | 84 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/lib/crypto/pkcs7_verify.c b/lib/crypto/pkcs7_verify.c index 1e8600f7faca..8b5cd7a443ae 100644 --- a/lib/crypto/pkcs7_verify.c +++ b/lib/crypto/pkcs7_verify.c @@ -17,7 +17,10 @@ #include #endif #include -#ifndef __UBOOT__ +#ifdef __UBOOT__ +#include +#include +#else #include #include #endif @@ -35,9 +38,84 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, struct pkcs7_signed_info *sinfo) { - return 0; + struct public_key_signature *sig = sinfo->sig; + struct image_region regions[2]; + int ret = 0; + + /* The digest was calculated already. */ + if (sig->digest) + return 0; + + if (!sinfo->sig->hash_algo) + return -ENOPKG; + if (!strcmp(sinfo->sig->hash_algo, "sha256")) + sig->digest_size = SHA256_SUM_LEN; + else if (!strcmp(sinfo->sig->hash_algo, "sha1")) + sig->digest_size = SHA1_SUM_LEN; + else + return -ENOPKG; + + sig->digest = calloc(1, sig->digest_size); + if (!sig->digest) { + pr_warn("Sig %u: Out of memory\n", sinfo->index); + return -ENOMEM; + } + + regions[0].data = pkcs7->data; + regions[0].size = pkcs7->data_len; + + /* Digest the message [RFC2315 9.3] */ + hash_calculate(sinfo->sig->hash_algo, regions, 1, sig->digest); + + /* However, if there are authenticated attributes, there must be a + * message digest attribute amongst them which corresponds to the + * digest we just calculated. + */ + 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 != sig->digest_size) { + pr_debug("Sig %u: Invalid digest size (%u)\n", + sinfo->index, sinfo->msgdigest_len); + ret = -EBADMSG; + goto error; + } + + if (memcmp(sig->digest, sinfo->msgdigest, + sinfo->msgdigest_len) != 0) { + pr_debug("Sig %u: Message digest doesn't match\n", + sinfo->index); + ret = -EKEYREJECTED; + goto error; + } + + /* We then calculate anew, using the authenticated attributes + * as the contents of the digest instead. Note that we need to + * convert the attributes from a CONT.0 into a SET before we + * hash it. + */ + memset(sig->digest, 0, sig->digest_size); + + tag = 0x31; + regions[0].data = &tag; + regions[0].size = 1; + regions[1].data = sinfo->authattrs; + regions[1].size = sinfo->authattrs_len; + + hash_calculate(sinfo->sig->hash_algo, regions, 2, sig->digest); + + ret = 0; + } +error: + return ret; } -#else +#else /* !__UBOOT__ */ static int pkcs7_digest(struct pkcs7_message *pkcs7, struct pkcs7_signed_info *sinfo) {