Skip to content

Commit 566a117

Browse files
committed
PKCS#7: Make the signature a pointer rather than embedding it
Point to the public_key_signature struct from the pkcs7_signed_info struct rather than embedding it. This makes the code consistent with the X.509 signature handling and makes it possible to have a common cleanup function. We also save a copy of the digest in the signature without sharing the memory with the crypto layer metadata. Signed-off-by: David Howells <dhowells@redhat.com>
1 parent 77d0910 commit 566a117

File tree

4 files changed

+55
-48
lines changed

4 files changed

+55
-48
lines changed

crypto/asymmetric_keys/pkcs7_parser.c

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,7 @@ struct pkcs7_parse_context {
4444
static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
4545
{
4646
if (sinfo) {
47-
kfree(sinfo->sig.s);
48-
kfree(sinfo->sig.digest);
49-
kfree(sinfo->signing_cert_id);
47+
public_key_signature_free(sinfo->sig);
5048
kfree(sinfo);
5149
}
5250
}
@@ -125,6 +123,10 @@ struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
125123
ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
126124
if (!ctx->sinfo)
127125
goto out_no_sinfo;
126+
ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature),
127+
GFP_KERNEL);
128+
if (!ctx->sinfo->sig)
129+
goto out_no_sig;
128130

129131
ctx->data = (unsigned long)data;
130132
ctx->ppcerts = &ctx->certs;
@@ -150,6 +152,7 @@ struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
150152
ctx->certs = cert->next;
151153
x509_free_certificate(cert);
152154
}
155+
out_no_sig:
153156
pkcs7_free_signed_info(ctx->sinfo);
154157
out_no_sinfo:
155158
pkcs7_free_message(ctx->msg);
@@ -218,25 +221,26 @@ int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
218221

219222
switch (ctx->last_oid) {
220223
case OID_md4:
221-
ctx->sinfo->sig.hash_algo = "md4";
224+
ctx->sinfo->sig->hash_algo = "md4";
222225
break;
223226
case OID_md5:
224-
ctx->sinfo->sig.hash_algo = "md5";
227+
ctx->sinfo->sig->hash_algo = "md5";
225228
break;
226229
case OID_sha1:
227-
ctx->sinfo->sig.hash_algo = "sha1";
230+
ctx->sinfo->sig->hash_algo = "sha1";
228231
break;
229232
case OID_sha256:
230-
ctx->sinfo->sig.hash_algo = "sha256";
233+
ctx->sinfo->sig->hash_algo = "sha256";
231234
break;
232235
case OID_sha384:
233-
ctx->sinfo->sig.hash_algo = "sha384";
236+
ctx->sinfo->sig->hash_algo = "sha384";
234237
break;
235238
case OID_sha512:
236-
ctx->sinfo->sig.hash_algo = "sha512";
239+
ctx->sinfo->sig->hash_algo = "sha512";
237240
break;
238241
case OID_sha224:
239-
ctx->sinfo->sig.hash_algo = "sha224";
242+
ctx->sinfo->sig->hash_algo = "sha224";
243+
break;
240244
default:
241245
printk("Unsupported digest algo: %u\n", ctx->last_oid);
242246
return -ENOPKG;
@@ -255,7 +259,7 @@ int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
255259

256260
switch (ctx->last_oid) {
257261
case OID_rsaEncryption:
258-
ctx->sinfo->sig.pkey_algo = "rsa";
262+
ctx->sinfo->sig->pkey_algo = "rsa";
259263
break;
260264
default:
261265
printk("Unsupported pkey algo: %u\n", ctx->last_oid);
@@ -615,11 +619,11 @@ int pkcs7_sig_note_signature(void *context, size_t hdrlen,
615619
{
616620
struct pkcs7_parse_context *ctx = context;
617621

618-
ctx->sinfo->sig.s = kmemdup(value, vlen, GFP_KERNEL);
619-
if (!ctx->sinfo->sig.s)
622+
ctx->sinfo->sig->s = kmemdup(value, vlen, GFP_KERNEL);
623+
if (!ctx->sinfo->sig->s)
620624
return -ENOMEM;
621625

622-
ctx->sinfo->sig.s_size = vlen;
626+
ctx->sinfo->sig->s_size = vlen;
623627
return 0;
624628
}
625629

@@ -655,12 +659,16 @@ int pkcs7_note_signed_info(void *context, size_t hdrlen,
655659

656660
pr_devel("SINFO KID: %u [%*phN]\n", kid->len, kid->len, kid->data);
657661

658-
sinfo->signing_cert_id = kid;
662+
sinfo->sig->auth_ids[0] = kid;
659663
sinfo->index = ++ctx->sinfo_index;
660664
*ctx->ppsinfo = sinfo;
661665
ctx->ppsinfo = &sinfo->next;
662666
ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
663667
if (!ctx->sinfo)
664668
return -ENOMEM;
669+
ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature),
670+
GFP_KERNEL);
671+
if (!ctx->sinfo->sig)
672+
return -ENOMEM;
665673
return 0;
666674
}

crypto/asymmetric_keys/pkcs7_parser.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,17 @@ struct pkcs7_signed_info {
4141
#define sinfo_has_ms_statement_type 5
4242
time64_t signing_time;
4343

44-
/* Issuing cert serial number and issuer's name [PKCS#7 or CMS ver 1]
45-
* or issuing cert's SKID [CMS ver 3].
46-
*/
47-
struct asymmetric_key_id *signing_cert_id;
48-
4944
/* Message signature.
5045
*
5146
* This contains the generated digest of _either_ the Content Data or
5247
* the Authenticated Attributes [RFC2315 9.3]. If the latter, one of
5348
* the attributes contains the digest of the the Content Data within
5449
* it.
50+
*
51+
* THis also contains the issuing cert serial number and issuer's name
52+
* [PKCS#7 or CMS ver 1] or issuing cert's SKID [CMS ver 3].
5553
*/
56-
struct public_key_signature sig;
54+
struct public_key_signature *sig;
5755
};
5856

5957
struct pkcs7_message {

crypto/asymmetric_keys/pkcs7_trust.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
2727
struct pkcs7_signed_info *sinfo,
2828
struct key *trust_keyring)
2929
{
30-
struct public_key_signature *sig = &sinfo->sig;
30+
struct public_key_signature *sig = sinfo->sig;
3131
struct x509_certificate *x509, *last = NULL, *p;
3232
struct key *key;
3333
bool trusted;
@@ -105,7 +105,7 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
105105
* the signed info directly.
106106
*/
107107
key = x509_request_asymmetric_key(trust_keyring,
108-
sinfo->signing_cert_id,
108+
sinfo->sig->auth_ids[0],
109109
NULL,
110110
false);
111111
if (!IS_ERR(key)) {

crypto/asymmetric_keys/pkcs7_verify.c

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,45 +25,48 @@
2525
static int pkcs7_digest(struct pkcs7_message *pkcs7,
2626
struct pkcs7_signed_info *sinfo)
2727
{
28+
struct public_key_signature *sig = sinfo->sig;
2829
struct crypto_shash *tfm;
2930
struct shash_desc *desc;
30-
size_t digest_size, desc_size;
31-
void *digest;
31+
size_t desc_size;
3232
int ret;
3333

34-
kenter(",%u,%s", sinfo->index, sinfo->sig.hash_algo);
34+
kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo);
3535

36-
if (!sinfo->sig.hash_algo)
36+
if (!sinfo->sig->hash_algo)
3737
return -ENOPKG;
3838

3939
/* Allocate the hashing algorithm we're going to need and find out how
4040
* big the hash operational data will be.
4141
*/
42-
tfm = crypto_alloc_shash(sinfo->sig.hash_algo, 0, 0);
42+
tfm = crypto_alloc_shash(sinfo->sig->hash_algo, 0, 0);
4343
if (IS_ERR(tfm))
4444
return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
4545

4646
desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
47-
sinfo->sig.digest_size = digest_size = crypto_shash_digestsize(tfm);
47+
sig->digest_size = crypto_shash_digestsize(tfm);
4848

4949
ret = -ENOMEM;
50-
digest = kzalloc(ALIGN(digest_size, __alignof__(*desc)) + desc_size,
51-
GFP_KERNEL);
52-
if (!digest)
50+
sig->digest = kmalloc(sig->digest_size, GFP_KERNEL);
51+
if (!sig->digest)
52+
goto error_no_desc;
53+
54+
desc = kzalloc(desc_size, GFP_KERNEL);
55+
if (!desc)
5356
goto error_no_desc;
5457

55-
desc = PTR_ALIGN(digest + digest_size, __alignof__(*desc));
5658
desc->tfm = tfm;
5759
desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
5860

5961
/* Digest the message [RFC2315 9.3] */
6062
ret = crypto_shash_init(desc);
6163
if (ret < 0)
6264
goto error;
63-
ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len, digest);
65+
ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len,
66+
sig->digest);
6467
if (ret < 0)
6568
goto error;
66-
pr_devel("MsgDigest = [%*ph]\n", 8, digest);
69+
pr_devel("MsgDigest = [%*ph]\n", 8, sig->digest);
6770

6871
/* However, if there are authenticated attributes, there must be a
6972
* message digest attribute amongst them which corresponds to the
@@ -78,14 +81,15 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
7881
goto error;
7982
}
8083

81-
if (sinfo->msgdigest_len != sinfo->sig.digest_size) {
84+
if (sinfo->msgdigest_len != sig->digest_size) {
8285
pr_debug("Sig %u: Invalid digest size (%u)\n",
8386
sinfo->index, sinfo->msgdigest_len);
8487
ret = -EBADMSG;
8588
goto error;
8689
}
8790

88-
if (memcmp(digest, sinfo->msgdigest, sinfo->msgdigest_len) != 0) {
91+
if (memcmp(sig->digest, sinfo->msgdigest,
92+
sinfo->msgdigest_len) != 0) {
8993
pr_debug("Sig %u: Message digest doesn't match\n",
9094
sinfo->index);
9195
ret = -EKEYREJECTED;
@@ -97,7 +101,7 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
97101
* convert the attributes from a CONT.0 into a SET before we
98102
* hash it.
99103
*/
100-
memset(digest, 0, sinfo->sig.digest_size);
104+
memset(sig->digest, 0, sig->digest_size);
101105

102106
ret = crypto_shash_init(desc);
103107
if (ret < 0)
@@ -107,17 +111,14 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
107111
if (ret < 0)
108112
goto error;
109113
ret = crypto_shash_finup(desc, sinfo->authattrs,
110-
sinfo->authattrs_len, digest);
114+
sinfo->authattrs_len, sig->digest);
111115
if (ret < 0)
112116
goto error;
113-
pr_devel("AADigest = [%*ph]\n", 8, digest);
117+
pr_devel("AADigest = [%*ph]\n", 8, sig->digest);
114118
}
115119

116-
sinfo->sig.digest = digest;
117-
digest = NULL;
118-
119120
error:
120-
kfree(digest);
121+
kfree(desc);
121122
error_no_desc:
122123
crypto_free_shash(tfm);
123124
kleave(" = %d", ret);
@@ -144,12 +145,12 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
144145
* PKCS#7 message - but I can't be 100% sure of that. It's
145146
* possible this will need element-by-element comparison.
146147
*/
147-
if (!asymmetric_key_id_same(x509->id, sinfo->signing_cert_id))
148+
if (!asymmetric_key_id_same(x509->id, sinfo->sig->auth_ids[0]))
148149
continue;
149150
pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
150151
sinfo->index, certix);
151152

152-
if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) {
153+
if (x509->pub->pkey_algo != sinfo->sig->pkey_algo) {
153154
pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
154155
sinfo->index);
155156
continue;
@@ -164,7 +165,7 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
164165
*/
165166
pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n",
166167
sinfo->index,
167-
sinfo->signing_cert_id->len, sinfo->signing_cert_id->data);
168+
sinfo->sig->auth_ids[0]->len, sinfo->sig->auth_ids[0]->data);
168169
return 0;
169170
}
170171

@@ -334,7 +335,7 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
334335
}
335336

336337
/* Verify the PKCS#7 binary against the key */
337-
ret = public_key_verify_signature(sinfo->signer->pub, &sinfo->sig);
338+
ret = public_key_verify_signature(sinfo->signer->pub, sinfo->sig);
338339
if (ret < 0)
339340
return ret;
340341

0 commit comments

Comments
 (0)