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>
This commit is contained in:
Thiago Jung Bauermann 2019-06-27 23:19:26 -03:00 committed by Mimi Zohar
parent 2a7bf67118
commit e201af16d1
2 changed files with 37 additions and 0 deletions

View File

@ -12,6 +12,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/asn1.h> #include <linux/asn1.h>
#include <crypto/hash.h> #include <crypto/hash.h>
#include <crypto/hash_info.h>
#include <crypto/public_key.h> #include <crypto/public_key.h>
#include "pkcs7_parser.h" #include "pkcs7_parser.h"
@ -29,6 +30,10 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo); kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo);
/* The digest was calculated already. */
if (sig->digest)
return 0;
if (!sinfo->sig->hash_algo) if (!sinfo->sig->hash_algo)
return -ENOPKG; return -ENOPKG;
@ -117,6 +122,34 @@ error_no_desc:
return ret; return ret;
} }
int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf, u32 *len,
enum hash_algo *hash_algo)
{
struct pkcs7_signed_info *sinfo = pkcs7->signed_infos;
int i, ret;
/*
* This function doesn't support messages with more than one signature.
*/
if (sinfo == NULL || sinfo->next != NULL)
return -EBADMSG;
ret = pkcs7_digest(pkcs7, sinfo);
if (ret)
return ret;
*buf = sinfo->sig->digest;
*len = sinfo->sig->digest_size;
for (i = 0; i < HASH_ALGO__LAST; i++)
if (!strcmp(hash_algo_name[i], sinfo->sig->hash_algo)) {
*hash_algo = i;
break;
}
return 0;
}
/* /*
* Find the key (X.509 certificate) to use to verify a PKCS#7 message. PKCS#7 * Find the key (X.509 certificate) to use to verify a PKCS#7 message. PKCS#7
* uses the issuer's name and the issuing certificate serial number for * uses the issuer's name and the issuing certificate serial number for

View File

@ -9,6 +9,7 @@
#define _CRYPTO_PKCS7_H #define _CRYPTO_PKCS7_H
#include <linux/verification.h> #include <linux/verification.h>
#include <linux/hash_info.h>
#include <crypto/public_key.h> #include <crypto/public_key.h>
struct key; struct key;
@ -40,4 +41,7 @@ extern int pkcs7_verify(struct pkcs7_message *pkcs7,
extern int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7, extern int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7,
const void *data, size_t datalen); const void *data, size_t datalen);
extern int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf,
u32 *len, enum hash_algo *hash_algo);
#endif /* _CRYPTO_PKCS7_H */ #endif /* _CRYPTO_PKCS7_H */