From patchwork Fri Jul 10 00:24:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 241159 List-Id: U-Boot discussion From: takahiro.akashi at linaro.org (AKASHI Takahiro) Date: Fri, 10 Jul 2020 09:24:46 +0900 Subject: [PATCH v3 5/8] lib: crypto: add pkcs7_digest() In-Reply-To: <20200710002449.26680-1-takahiro.akashi@linaro.org> References: <20200710002449.26680-1-takahiro.akashi@linaro.org> Message-ID: <20200710002449.26680-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 | 92 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 3 deletions(-) diff --git a/lib/crypto/pkcs7_verify.c b/lib/crypto/pkcs7_verify.c index a893fa3b586b..a32e841cb22b 100644 --- a/lib/crypto/pkcs7_verify.c +++ b/lib/crypto/pkcs7_verify.c @@ -7,10 +7,12 @@ #define pr_fmt(fmt) "PKCS7: "fmt #ifdef __UBOOT__ +#include #include #include #include #include +#include #include #include #else @@ -26,15 +28,99 @@ #endif /* - * Digest the relevant parts of the PKCS#7 data + * pkcs7_digest - Digest the relevant parts of the PKCS#7 data + * @pkcs7: PKCS7 Signed Data + * @sinfo: PKCS7 Signed Info + * + * Digest the relevant parts of the PKCS#7 data, @pkcs7, using signature + * information in @sinfo. But if there are authentication attributes, + * i.e. signed image case, the digest must be calculated against + * the authentication attributes. + * + * Return: 0 - on success, non-zero error code - otherwise */ #ifdef __UBOOT__ 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) {