Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PKCS#7: Introduce pkcs7_get_digest()

IMA will need to access the digest of the PKCS7 message (as calculated by
the kernel) before the signature is verified, so introduce
pkcs7_get_digest() for that purpose.

Also, modify pkcs7_digest() to detect when the digest was already
calculated so that it doesn't have to do redundant work. Verifying that
sinfo->sig->digest isn't NULL is sufficient because both places which
allocate sinfo->sig (pkcs7_parse_message() and pkcs7_note_signed_info())
use kzalloc() so sig->digest is always initialized to zero.

Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
Cc: David Howells <dhowells@redhat.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>

authored by

Thiago Jung Bauermann and committed by
Mimi Zohar
e201af16 2a7bf671

+37
+33
crypto/asymmetric_keys/pkcs7_verify.c
··· 12 12 #include <linux/err.h> 13 13 #include <linux/asn1.h> 14 14 #include <crypto/hash.h> 15 + #include <crypto/hash_info.h> 15 16 #include <crypto/public_key.h> 16 17 #include "pkcs7_parser.h" 17 18 ··· 29 28 int ret; 30 29 31 30 kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo); 31 + 32 + /* The digest was calculated already. */ 33 + if (sig->digest) 34 + return 0; 32 35 33 36 if (!sinfo->sig->hash_algo) 34 37 return -ENOPKG; ··· 120 115 crypto_free_shash(tfm); 121 116 kleave(" = %d", ret); 122 117 return ret; 118 + } 119 + 120 + int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf, u32 *len, 121 + enum hash_algo *hash_algo) 122 + { 123 + struct pkcs7_signed_info *sinfo = pkcs7->signed_infos; 124 + int i, ret; 125 + 126 + /* 127 + * This function doesn't support messages with more than one signature. 128 + */ 129 + if (sinfo == NULL || sinfo->next != NULL) 130 + return -EBADMSG; 131 + 132 + ret = pkcs7_digest(pkcs7, sinfo); 133 + if (ret) 134 + return ret; 135 + 136 + *buf = sinfo->sig->digest; 137 + *len = sinfo->sig->digest_size; 138 + 139 + for (i = 0; i < HASH_ALGO__LAST; i++) 140 + if (!strcmp(hash_algo_name[i], sinfo->sig->hash_algo)) { 141 + *hash_algo = i; 142 + break; 143 + } 144 + 145 + return 0; 123 146 } 124 147 125 148 /*
+4
include/crypto/pkcs7.h
··· 9 9 #define _CRYPTO_PKCS7_H 10 10 11 11 #include <linux/verification.h> 12 + #include <linux/hash_info.h> 12 13 #include <crypto/public_key.h> 13 14 14 15 struct key; ··· 40 39 41 40 extern int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7, 42 41 const void *data, size_t datalen); 42 + 43 + extern int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf, 44 + u32 *len, enum hash_algo *hash_algo); 43 45 44 46 #endif /* _CRYPTO_PKCS7_H */