diff options
author | David Howells <dhowells@redhat.com> | 2015-07-20 16:16:33 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2015-08-12 12:01:01 -0400 |
commit | 60d65cacd7c2d84a6dcad69bcb57bbf0220c8643 (patch) | |
tree | 636bda3cc9024a04edf1ae5780266fde743e7b1e /crypto | |
parent | a4c6e57f4f5fa65cbdb8cc1c14ff5ca7c56766c3 (diff) |
PKCS#7: Support CMS messages also [RFC5652]
Since CMS is an evolution of PKCS#7, with much of the ASN.1 being
compatible, add support for CMS signed-data messages also [RFC5652 sec 5].
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-By: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/asymmetric_keys/pkcs7.asn1 | 10 | ||||
-rw-r--r-- | crypto/asymmetric_keys/pkcs7_parser.c | 62 | ||||
-rw-r--r-- | crypto/asymmetric_keys/pkcs7_parser.h | 5 |
3 files changed, 68 insertions, 9 deletions
diff --git a/crypto/asymmetric_keys/pkcs7.asn1 b/crypto/asymmetric_keys/pkcs7.asn1 index 05504431e1c1..6bf8ff4f7414 100644 --- a/crypto/asymmetric_keys/pkcs7.asn1 +++ b/crypto/asymmetric_keys/pkcs7.asn1 | |||
@@ -69,7 +69,7 @@ SignerInfos ::= CHOICE { | |||
69 | 69 | ||
70 | SignerInfo ::= SEQUENCE { | 70 | SignerInfo ::= SEQUENCE { |
71 | version INTEGER ({ pkcs7_note_signerinfo_version }), | 71 | version INTEGER ({ pkcs7_note_signerinfo_version }), |
72 | issuerAndSerialNumber IssuerAndSerialNumber, | 72 | sid SignerIdentifier, -- CMS variant, not PKCS#7 |
73 | digestAlgorithm DigestAlgorithmIdentifier ({ pkcs7_sig_note_digest_algo }), | 73 | digestAlgorithm DigestAlgorithmIdentifier ({ pkcs7_sig_note_digest_algo }), |
74 | authenticatedAttributes CHOICE { | 74 | authenticatedAttributes CHOICE { |
75 | aaSet [0] IMPLICIT SetOfAuthenticatedAttribute | 75 | aaSet [0] IMPLICIT SetOfAuthenticatedAttribute |
@@ -88,6 +88,12 @@ SignerInfo ::= SEQUENCE { | |||
88 | } OPTIONAL | 88 | } OPTIONAL |
89 | } ({ pkcs7_note_signed_info }) | 89 | } ({ pkcs7_note_signed_info }) |
90 | 90 | ||
91 | SignerIdentifier ::= CHOICE { | ||
92 | -- RFC5652 sec 5.3 | ||
93 | issuerAndSerialNumber IssuerAndSerialNumber, | ||
94 | subjectKeyIdentifier [0] IMPLICIT SubjectKeyIdentifier | ||
95 | } | ||
96 | |||
91 | IssuerAndSerialNumber ::= SEQUENCE { | 97 | IssuerAndSerialNumber ::= SEQUENCE { |
92 | issuer Name ({ pkcs7_sig_note_issuer }), | 98 | issuer Name ({ pkcs7_sig_note_issuer }), |
93 | serialNumber CertificateSerialNumber ({ pkcs7_sig_note_serial }) | 99 | serialNumber CertificateSerialNumber ({ pkcs7_sig_note_serial }) |
@@ -95,6 +101,8 @@ IssuerAndSerialNumber ::= SEQUENCE { | |||
95 | 101 | ||
96 | CertificateSerialNumber ::= INTEGER | 102 | CertificateSerialNumber ::= INTEGER |
97 | 103 | ||
104 | SubjectKeyIdentifier ::= OCTET STRING ({ pkcs7_sig_note_skid }) | ||
105 | |||
98 | SetOfAuthenticatedAttribute ::= SET OF AuthenticatedAttribute | 106 | SetOfAuthenticatedAttribute ::= SET OF AuthenticatedAttribute |
99 | 107 | ||
100 | AuthenticatedAttribute ::= SEQUENCE { | 108 | AuthenticatedAttribute ::= SEQUENCE { |
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index ab427f04b299..826e2f3f507b 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c | |||
@@ -33,6 +33,9 @@ struct pkcs7_parse_context { | |||
33 | unsigned raw_serial_size; | 33 | unsigned raw_serial_size; |
34 | unsigned raw_issuer_size; | 34 | unsigned raw_issuer_size; |
35 | const void *raw_issuer; | 35 | const void *raw_issuer; |
36 | const void *raw_skid; | ||
37 | unsigned raw_skid_size; | ||
38 | bool expect_skid; | ||
36 | }; | 39 | }; |
37 | 40 | ||
38 | /* | 41 | /* |
@@ -249,15 +252,21 @@ int pkcs7_note_signeddata_version(void *context, size_t hdrlen, | |||
249 | unsigned char tag, | 252 | unsigned char tag, |
250 | const void *value, size_t vlen) | 253 | const void *value, size_t vlen) |
251 | { | 254 | { |
255 | struct pkcs7_parse_context *ctx = context; | ||
252 | unsigned version; | 256 | unsigned version; |
253 | 257 | ||
254 | if (vlen != 1) | 258 | if (vlen != 1) |
255 | goto unsupported; | 259 | goto unsupported; |
256 | 260 | ||
257 | version = *(const u8 *)value; | 261 | ctx->msg->version = version = *(const u8 *)value; |
258 | switch (version) { | 262 | switch (version) { |
259 | case 1: | 263 | case 1: |
260 | /* PKCS#7 SignedData [RFC2315 sec 9.1] */ | 264 | /* PKCS#7 SignedData [RFC2315 sec 9.1] |
265 | * CMS ver 1 SignedData [RFC5652 sec 5.1] | ||
266 | */ | ||
267 | break; | ||
268 | case 3: | ||
269 | /* CMS ver 3 SignedData [RFC2315 sec 5.1] */ | ||
261 | break; | 270 | break; |
262 | default: | 271 | default: |
263 | goto unsupported; | 272 | goto unsupported; |
@@ -277,6 +286,7 @@ int pkcs7_note_signerinfo_version(void *context, size_t hdrlen, | |||
277 | unsigned char tag, | 286 | unsigned char tag, |
278 | const void *value, size_t vlen) | 287 | const void *value, size_t vlen) |
279 | { | 288 | { |
289 | struct pkcs7_parse_context *ctx = context; | ||
280 | unsigned version; | 290 | unsigned version; |
281 | 291 | ||
282 | if (vlen != 1) | 292 | if (vlen != 1) |
@@ -285,7 +295,18 @@ int pkcs7_note_signerinfo_version(void *context, size_t hdrlen, | |||
285 | version = *(const u8 *)value; | 295 | version = *(const u8 *)value; |
286 | switch (version) { | 296 | switch (version) { |
287 | case 1: | 297 | case 1: |
288 | /* PKCS#7 SignerInfo [RFC2315 sec 9.2] */ | 298 | /* PKCS#7 SignerInfo [RFC2315 sec 9.2] |
299 | * CMS ver 1 SignerInfo [RFC5652 sec 5.3] | ||
300 | */ | ||
301 | if (ctx->msg->version != 1) | ||
302 | goto version_mismatch; | ||
303 | ctx->expect_skid = false; | ||
304 | break; | ||
305 | case 3: | ||
306 | /* CMS ver 3 SignerInfo [RFC2315 sec 5.3] */ | ||
307 | if (ctx->msg->version == 1) | ||
308 | goto version_mismatch; | ||
309 | ctx->expect_skid = true; | ||
289 | break; | 310 | break; |
290 | default: | 311 | default: |
291 | goto unsupported; | 312 | goto unsupported; |
@@ -296,6 +317,9 @@ int pkcs7_note_signerinfo_version(void *context, size_t hdrlen, | |||
296 | unsupported: | 317 | unsupported: |
297 | pr_warn("Unsupported SignerInfo version\n"); | 318 | pr_warn("Unsupported SignerInfo version\n"); |
298 | return -EINVAL; | 319 | return -EINVAL; |
320 | version_mismatch: | ||
321 | pr_warn("SignedData-SignerInfo version mismatch\n"); | ||
322 | return -EBADMSG; | ||
299 | } | 323 | } |
300 | 324 | ||
301 | /* | 325 | /* |
@@ -440,6 +464,22 @@ int pkcs7_sig_note_issuer(void *context, size_t hdrlen, | |||
440 | } | 464 | } |
441 | 465 | ||
442 | /* | 466 | /* |
467 | * Note the issuing cert's subjectKeyIdentifier | ||
468 | */ | ||
469 | int pkcs7_sig_note_skid(void *context, size_t hdrlen, | ||
470 | unsigned char tag, | ||
471 | const void *value, size_t vlen) | ||
472 | { | ||
473 | struct pkcs7_parse_context *ctx = context; | ||
474 | |||
475 | pr_devel("SKID: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value); | ||
476 | |||
477 | ctx->raw_skid = value; | ||
478 | ctx->raw_skid_size = vlen; | ||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | /* | ||
443 | * Note the signature data | 483 | * Note the signature data |
444 | */ | 484 | */ |
445 | int pkcs7_sig_note_signature(void *context, size_t hdrlen, | 485 | int pkcs7_sig_note_signature(void *context, size_t hdrlen, |
@@ -472,13 +512,21 @@ int pkcs7_note_signed_info(void *context, size_t hdrlen, | |||
472 | struct asymmetric_key_id *kid; | 512 | struct asymmetric_key_id *kid; |
473 | 513 | ||
474 | /* Generate cert issuer + serial number key ID */ | 514 | /* Generate cert issuer + serial number key ID */ |
475 | kid = asymmetric_key_generate_id(ctx->raw_serial, | 515 | if (!ctx->expect_skid) { |
476 | ctx->raw_serial_size, | 516 | kid = asymmetric_key_generate_id(ctx->raw_serial, |
477 | ctx->raw_issuer, | 517 | ctx->raw_serial_size, |
478 | ctx->raw_issuer_size); | 518 | ctx->raw_issuer, |
519 | ctx->raw_issuer_size); | ||
520 | } else { | ||
521 | kid = asymmetric_key_generate_id(ctx->raw_skid, | ||
522 | ctx->raw_skid_size, | ||
523 | "", 0); | ||
524 | } | ||
479 | if (IS_ERR(kid)) | 525 | if (IS_ERR(kid)) |
480 | return PTR_ERR(kid); | 526 | return PTR_ERR(kid); |
481 | 527 | ||
528 | pr_devel("SINFO KID: %u [%*phN]\n", kid->len, kid->len, kid->data); | ||
529 | |||
482 | sinfo->signing_cert_id = kid; | 530 | sinfo->signing_cert_id = kid; |
483 | sinfo->index = ++ctx->sinfo_index; | 531 | sinfo->index = ++ctx->sinfo_index; |
484 | *ctx->ppsinfo = sinfo; | 532 | *ctx->ppsinfo = sinfo; |
diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h index efc7dc9b8f9c..790dd7cec82c 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.h +++ b/crypto/asymmetric_keys/pkcs7_parser.h | |||
@@ -33,7 +33,9 @@ struct pkcs7_signed_info { | |||
33 | unsigned authattrs_len; | 33 | unsigned authattrs_len; |
34 | const void *authattrs; | 34 | const void *authattrs; |
35 | 35 | ||
36 | /* Issuing cert serial number and issuer's name */ | 36 | /* Issuing cert serial number and issuer's name [PKCS#7 or CMS ver 1] |
37 | * or issuing cert's SKID [CMS ver 3]. | ||
38 | */ | ||
37 | struct asymmetric_key_id *signing_cert_id; | 39 | struct asymmetric_key_id *signing_cert_id; |
38 | 40 | ||
39 | /* Message signature. | 41 | /* Message signature. |
@@ -50,6 +52,7 @@ struct pkcs7_message { | |||
50 | struct x509_certificate *certs; /* Certificate list */ | 52 | struct x509_certificate *certs; /* Certificate list */ |
51 | struct x509_certificate *crl; /* Revocation list */ | 53 | struct x509_certificate *crl; /* Revocation list */ |
52 | struct pkcs7_signed_info *signed_infos; | 54 | struct pkcs7_signed_info *signed_infos; |
55 | u8 version; /* Version of cert (1 -> PKCS#7 or CMS; 3 -> CMS) */ | ||
53 | 56 | ||
54 | /* Content Data (or NULL) */ | 57 | /* Content Data (or NULL) */ |
55 | enum OID data_type; /* Type of Data */ | 58 | enum OID data_type; /* Type of Data */ |