0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) "PKCS7: "fmt
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/export.h>
0012 #include <linux/slab.h>
0013 #include <linux/err.h>
0014 #include <linux/oid_registry.h>
0015 #include <crypto/public_key.h>
0016 #include "pkcs7_parser.h"
0017 #include "pkcs7.asn1.h"
0018
0019 MODULE_DESCRIPTION("PKCS#7 parser");
0020 MODULE_AUTHOR("Red Hat, Inc.");
0021 MODULE_LICENSE("GPL");
0022
0023 struct pkcs7_parse_context {
0024 struct pkcs7_message *msg;
0025 struct pkcs7_signed_info *sinfo;
0026 struct pkcs7_signed_info **ppsinfo;
0027 struct x509_certificate *certs;
0028 struct x509_certificate **ppcerts;
0029 unsigned long data;
0030 enum OID last_oid;
0031 unsigned x509_index;
0032 unsigned sinfo_index;
0033 const void *raw_serial;
0034 unsigned raw_serial_size;
0035 unsigned raw_issuer_size;
0036 const void *raw_issuer;
0037 const void *raw_skid;
0038 unsigned raw_skid_size;
0039 bool expect_skid;
0040 };
0041
0042
0043
0044
0045 static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
0046 {
0047 if (sinfo) {
0048 public_key_signature_free(sinfo->sig);
0049 kfree(sinfo);
0050 }
0051 }
0052
0053
0054
0055
0056
0057 void pkcs7_free_message(struct pkcs7_message *pkcs7)
0058 {
0059 struct x509_certificate *cert;
0060 struct pkcs7_signed_info *sinfo;
0061
0062 if (pkcs7) {
0063 while (pkcs7->certs) {
0064 cert = pkcs7->certs;
0065 pkcs7->certs = cert->next;
0066 x509_free_certificate(cert);
0067 }
0068 while (pkcs7->crl) {
0069 cert = pkcs7->crl;
0070 pkcs7->crl = cert->next;
0071 x509_free_certificate(cert);
0072 }
0073 while (pkcs7->signed_infos) {
0074 sinfo = pkcs7->signed_infos;
0075 pkcs7->signed_infos = sinfo->next;
0076 pkcs7_free_signed_info(sinfo);
0077 }
0078 kfree(pkcs7);
0079 }
0080 }
0081 EXPORT_SYMBOL_GPL(pkcs7_free_message);
0082
0083
0084
0085
0086 static int pkcs7_check_authattrs(struct pkcs7_message *msg)
0087 {
0088 struct pkcs7_signed_info *sinfo;
0089 bool want = false;
0090
0091 sinfo = msg->signed_infos;
0092 if (!sinfo)
0093 goto inconsistent;
0094
0095 if (sinfo->authattrs) {
0096 want = true;
0097 msg->have_authattrs = true;
0098 }
0099
0100 for (sinfo = sinfo->next; sinfo; sinfo = sinfo->next)
0101 if (!!sinfo->authattrs != want)
0102 goto inconsistent;
0103 return 0;
0104
0105 inconsistent:
0106 pr_warn("Inconsistently supplied authAttrs\n");
0107 return -EINVAL;
0108 }
0109
0110
0111
0112
0113
0114
0115 struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
0116 {
0117 struct pkcs7_parse_context *ctx;
0118 struct pkcs7_message *msg = ERR_PTR(-ENOMEM);
0119 int ret;
0120
0121 ctx = kzalloc(sizeof(struct pkcs7_parse_context), GFP_KERNEL);
0122 if (!ctx)
0123 goto out_no_ctx;
0124 ctx->msg = kzalloc(sizeof(struct pkcs7_message), GFP_KERNEL);
0125 if (!ctx->msg)
0126 goto out_no_msg;
0127 ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
0128 if (!ctx->sinfo)
0129 goto out_no_sinfo;
0130 ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature),
0131 GFP_KERNEL);
0132 if (!ctx->sinfo->sig)
0133 goto out_no_sig;
0134
0135 ctx->data = (unsigned long)data;
0136 ctx->ppcerts = &ctx->certs;
0137 ctx->ppsinfo = &ctx->msg->signed_infos;
0138
0139
0140 ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen);
0141 if (ret < 0) {
0142 msg = ERR_PTR(ret);
0143 goto out;
0144 }
0145
0146 ret = pkcs7_check_authattrs(ctx->msg);
0147 if (ret < 0) {
0148 msg = ERR_PTR(ret);
0149 goto out;
0150 }
0151
0152 msg = ctx->msg;
0153 ctx->msg = NULL;
0154
0155 out:
0156 while (ctx->certs) {
0157 struct x509_certificate *cert = ctx->certs;
0158 ctx->certs = cert->next;
0159 x509_free_certificate(cert);
0160 }
0161 out_no_sig:
0162 pkcs7_free_signed_info(ctx->sinfo);
0163 out_no_sinfo:
0164 pkcs7_free_message(ctx->msg);
0165 out_no_msg:
0166 kfree(ctx);
0167 out_no_ctx:
0168 return msg;
0169 }
0170 EXPORT_SYMBOL_GPL(pkcs7_parse_message);
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185 int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
0186 const void **_data, size_t *_data_len,
0187 size_t *_headerlen)
0188 {
0189 if (!pkcs7->data)
0190 return -ENODATA;
0191
0192 *_data = pkcs7->data;
0193 *_data_len = pkcs7->data_len;
0194 if (_headerlen)
0195 *_headerlen = pkcs7->data_hdrlen;
0196 return 0;
0197 }
0198 EXPORT_SYMBOL_GPL(pkcs7_get_content_data);
0199
0200
0201
0202
0203
0204 int pkcs7_note_OID(void *context, size_t hdrlen,
0205 unsigned char tag,
0206 const void *value, size_t vlen)
0207 {
0208 struct pkcs7_parse_context *ctx = context;
0209
0210 ctx->last_oid = look_up_OID(value, vlen);
0211 if (ctx->last_oid == OID__NR) {
0212 char buffer[50];
0213 sprint_oid(value, vlen, buffer, sizeof(buffer));
0214 printk("PKCS7: Unknown OID: [%lu] %s\n",
0215 (unsigned long)value - ctx->data, buffer);
0216 }
0217 return 0;
0218 }
0219
0220
0221
0222
0223 int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
0224 unsigned char tag,
0225 const void *value, size_t vlen)
0226 {
0227 struct pkcs7_parse_context *ctx = context;
0228
0229 switch (ctx->last_oid) {
0230 case OID_md4:
0231 ctx->sinfo->sig->hash_algo = "md4";
0232 break;
0233 case OID_md5:
0234 ctx->sinfo->sig->hash_algo = "md5";
0235 break;
0236 case OID_sha1:
0237 ctx->sinfo->sig->hash_algo = "sha1";
0238 break;
0239 case OID_sha256:
0240 ctx->sinfo->sig->hash_algo = "sha256";
0241 break;
0242 case OID_sha384:
0243 ctx->sinfo->sig->hash_algo = "sha384";
0244 break;
0245 case OID_sha512:
0246 ctx->sinfo->sig->hash_algo = "sha512";
0247 break;
0248 case OID_sha224:
0249 ctx->sinfo->sig->hash_algo = "sha224";
0250 break;
0251 case OID_sm3:
0252 ctx->sinfo->sig->hash_algo = "sm3";
0253 break;
0254 case OID_gost2012Digest256:
0255 ctx->sinfo->sig->hash_algo = "streebog256";
0256 break;
0257 case OID_gost2012Digest512:
0258 ctx->sinfo->sig->hash_algo = "streebog512";
0259 break;
0260 default:
0261 printk("Unsupported digest algo: %u\n", ctx->last_oid);
0262 return -ENOPKG;
0263 }
0264 return 0;
0265 }
0266
0267
0268
0269
0270 int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
0271 unsigned char tag,
0272 const void *value, size_t vlen)
0273 {
0274 struct pkcs7_parse_context *ctx = context;
0275
0276 switch (ctx->last_oid) {
0277 case OID_rsaEncryption:
0278 ctx->sinfo->sig->pkey_algo = "rsa";
0279 ctx->sinfo->sig->encoding = "pkcs1";
0280 break;
0281 case OID_id_ecdsa_with_sha1:
0282 case OID_id_ecdsa_with_sha224:
0283 case OID_id_ecdsa_with_sha256:
0284 case OID_id_ecdsa_with_sha384:
0285 case OID_id_ecdsa_with_sha512:
0286 ctx->sinfo->sig->pkey_algo = "ecdsa";
0287 ctx->sinfo->sig->encoding = "x962";
0288 break;
0289 case OID_SM2_with_SM3:
0290 ctx->sinfo->sig->pkey_algo = "sm2";
0291 ctx->sinfo->sig->encoding = "raw";
0292 break;
0293 case OID_gost2012PKey256:
0294 case OID_gost2012PKey512:
0295 ctx->sinfo->sig->pkey_algo = "ecrdsa";
0296 ctx->sinfo->sig->encoding = "raw";
0297 break;
0298 default:
0299 printk("Unsupported pkey algo: %u\n", ctx->last_oid);
0300 return -ENOPKG;
0301 }
0302 return 0;
0303 }
0304
0305
0306
0307
0308 int pkcs7_check_content_type(void *context, size_t hdrlen,
0309 unsigned char tag,
0310 const void *value, size_t vlen)
0311 {
0312 struct pkcs7_parse_context *ctx = context;
0313
0314 if (ctx->last_oid != OID_signed_data) {
0315 pr_warn("Only support pkcs7_signedData type\n");
0316 return -EINVAL;
0317 }
0318
0319 return 0;
0320 }
0321
0322
0323
0324
0325 int pkcs7_note_signeddata_version(void *context, size_t hdrlen,
0326 unsigned char tag,
0327 const void *value, size_t vlen)
0328 {
0329 struct pkcs7_parse_context *ctx = context;
0330 unsigned version;
0331
0332 if (vlen != 1)
0333 goto unsupported;
0334
0335 ctx->msg->version = version = *(const u8 *)value;
0336 switch (version) {
0337 case 1:
0338
0339
0340
0341 break;
0342 case 3:
0343
0344 break;
0345 default:
0346 goto unsupported;
0347 }
0348
0349 return 0;
0350
0351 unsupported:
0352 pr_warn("Unsupported SignedData version\n");
0353 return -EINVAL;
0354 }
0355
0356
0357
0358
0359 int pkcs7_note_signerinfo_version(void *context, size_t hdrlen,
0360 unsigned char tag,
0361 const void *value, size_t vlen)
0362 {
0363 struct pkcs7_parse_context *ctx = context;
0364 unsigned version;
0365
0366 if (vlen != 1)
0367 goto unsupported;
0368
0369 version = *(const u8 *)value;
0370 switch (version) {
0371 case 1:
0372
0373
0374
0375 if (ctx->msg->version != 1)
0376 goto version_mismatch;
0377 ctx->expect_skid = false;
0378 break;
0379 case 3:
0380
0381 if (ctx->msg->version == 1)
0382 goto version_mismatch;
0383 ctx->expect_skid = true;
0384 break;
0385 default:
0386 goto unsupported;
0387 }
0388
0389 return 0;
0390
0391 unsupported:
0392 pr_warn("Unsupported SignerInfo version\n");
0393 return -EINVAL;
0394 version_mismatch:
0395 pr_warn("SignedData-SignerInfo version mismatch\n");
0396 return -EBADMSG;
0397 }
0398
0399
0400
0401
0402 int pkcs7_extract_cert(void *context, size_t hdrlen,
0403 unsigned char tag,
0404 const void *value, size_t vlen)
0405 {
0406 struct pkcs7_parse_context *ctx = context;
0407 struct x509_certificate *x509;
0408
0409 if (tag != ((ASN1_UNIV << 6) | ASN1_CONS_BIT | ASN1_SEQ)) {
0410 pr_debug("Cert began with tag %02x at %lu\n",
0411 tag, (unsigned long)ctx - ctx->data);
0412 return -EBADMSG;
0413 }
0414
0415
0416
0417
0418
0419
0420 value -= hdrlen;
0421 vlen += hdrlen;
0422
0423 if (((u8*)value)[1] == 0x80)
0424 vlen += 2;
0425
0426 x509 = x509_cert_parse(value, vlen);
0427 if (IS_ERR(x509))
0428 return PTR_ERR(x509);
0429
0430 x509->index = ++ctx->x509_index;
0431 pr_debug("Got cert %u for %s\n", x509->index, x509->subject);
0432 pr_debug("- fingerprint %*phN\n", x509->id->len, x509->id->data);
0433
0434 *ctx->ppcerts = x509;
0435 ctx->ppcerts = &x509->next;
0436 return 0;
0437 }
0438
0439
0440
0441
0442 int pkcs7_note_certificate_list(void *context, size_t hdrlen,
0443 unsigned char tag,
0444 const void *value, size_t vlen)
0445 {
0446 struct pkcs7_parse_context *ctx = context;
0447
0448 pr_devel("Got cert list (%02x)\n", tag);
0449
0450 *ctx->ppcerts = ctx->msg->certs;
0451 ctx->msg->certs = ctx->certs;
0452 ctx->certs = NULL;
0453 ctx->ppcerts = &ctx->certs;
0454 return 0;
0455 }
0456
0457
0458
0459
0460 int pkcs7_note_content(void *context, size_t hdrlen,
0461 unsigned char tag,
0462 const void *value, size_t vlen)
0463 {
0464 struct pkcs7_parse_context *ctx = context;
0465
0466 if (ctx->last_oid != OID_data &&
0467 ctx->last_oid != OID_msIndirectData) {
0468 pr_warn("Unsupported data type %d\n", ctx->last_oid);
0469 return -EINVAL;
0470 }
0471
0472 ctx->msg->data_type = ctx->last_oid;
0473 return 0;
0474 }
0475
0476
0477
0478
0479
0480 int pkcs7_note_data(void *context, size_t hdrlen,
0481 unsigned char tag,
0482 const void *value, size_t vlen)
0483 {
0484 struct pkcs7_parse_context *ctx = context;
0485
0486 pr_debug("Got data\n");
0487
0488 ctx->msg->data = value;
0489 ctx->msg->data_len = vlen;
0490 ctx->msg->data_hdrlen = hdrlen;
0491 return 0;
0492 }
0493
0494
0495
0496
0497 int pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen,
0498 unsigned char tag,
0499 const void *value, size_t vlen)
0500 {
0501 struct pkcs7_parse_context *ctx = context;
0502 struct pkcs7_signed_info *sinfo = ctx->sinfo;
0503 enum OID content_type;
0504
0505 pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value);
0506
0507 switch (ctx->last_oid) {
0508 case OID_contentType:
0509 if (__test_and_set_bit(sinfo_has_content_type, &sinfo->aa_set))
0510 goto repeated;
0511 content_type = look_up_OID(value, vlen);
0512 if (content_type != ctx->msg->data_type) {
0513 pr_warn("Mismatch between global data type (%d) and sinfo %u (%d)\n",
0514 ctx->msg->data_type, sinfo->index,
0515 content_type);
0516 return -EBADMSG;
0517 }
0518 return 0;
0519
0520 case OID_signingTime:
0521 if (__test_and_set_bit(sinfo_has_signing_time, &sinfo->aa_set))
0522 goto repeated;
0523
0524
0525
0526 return x509_decode_time(&sinfo->signing_time,
0527 hdrlen, tag, value, vlen);
0528
0529 case OID_messageDigest:
0530 if (__test_and_set_bit(sinfo_has_message_digest, &sinfo->aa_set))
0531 goto repeated;
0532 if (tag != ASN1_OTS)
0533 return -EBADMSG;
0534 sinfo->msgdigest = value;
0535 sinfo->msgdigest_len = vlen;
0536 return 0;
0537
0538 case OID_smimeCapabilites:
0539 if (__test_and_set_bit(sinfo_has_smime_caps, &sinfo->aa_set))
0540 goto repeated;
0541 if (ctx->msg->data_type != OID_msIndirectData) {
0542 pr_warn("S/MIME Caps only allowed with Authenticode\n");
0543 return -EKEYREJECTED;
0544 }
0545 return 0;
0546
0547
0548
0549
0550
0551
0552
0553 case OID_msSpOpusInfo:
0554 if (__test_and_set_bit(sinfo_has_ms_opus_info, &sinfo->aa_set))
0555 goto repeated;
0556 goto authenticode_check;
0557 case OID_msStatementType:
0558 if (__test_and_set_bit(sinfo_has_ms_statement_type, &sinfo->aa_set))
0559 goto repeated;
0560 authenticode_check:
0561 if (ctx->msg->data_type != OID_msIndirectData) {
0562 pr_warn("Authenticode AuthAttrs only allowed with Authenticode\n");
0563 return -EKEYREJECTED;
0564 }
0565
0566 return 0;
0567 default:
0568 return 0;
0569 }
0570
0571 repeated:
0572
0573 pr_warn("Repeated/multivalue AuthAttrs not permitted\n");
0574 return -EKEYREJECTED;
0575 }
0576
0577
0578
0579
0580 int pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen,
0581 unsigned char tag,
0582 const void *value, size_t vlen)
0583 {
0584 struct pkcs7_parse_context *ctx = context;
0585 struct pkcs7_signed_info *sinfo = ctx->sinfo;
0586
0587 if (!test_bit(sinfo_has_content_type, &sinfo->aa_set) ||
0588 !test_bit(sinfo_has_message_digest, &sinfo->aa_set)) {
0589 pr_warn("Missing required AuthAttr\n");
0590 return -EBADMSG;
0591 }
0592
0593 if (ctx->msg->data_type != OID_msIndirectData &&
0594 test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set)) {
0595 pr_warn("Unexpected Authenticode AuthAttr\n");
0596 return -EBADMSG;
0597 }
0598
0599
0600 sinfo->authattrs = value - (hdrlen - 1);
0601 sinfo->authattrs_len = vlen + (hdrlen - 1);
0602 return 0;
0603 }
0604
0605
0606
0607
0608 int pkcs7_sig_note_serial(void *context, size_t hdrlen,
0609 unsigned char tag,
0610 const void *value, size_t vlen)
0611 {
0612 struct pkcs7_parse_context *ctx = context;
0613 ctx->raw_serial = value;
0614 ctx->raw_serial_size = vlen;
0615 return 0;
0616 }
0617
0618
0619
0620
0621 int pkcs7_sig_note_issuer(void *context, size_t hdrlen,
0622 unsigned char tag,
0623 const void *value, size_t vlen)
0624 {
0625 struct pkcs7_parse_context *ctx = context;
0626 ctx->raw_issuer = value;
0627 ctx->raw_issuer_size = vlen;
0628 return 0;
0629 }
0630
0631
0632
0633
0634 int pkcs7_sig_note_skid(void *context, size_t hdrlen,
0635 unsigned char tag,
0636 const void *value, size_t vlen)
0637 {
0638 struct pkcs7_parse_context *ctx = context;
0639
0640 pr_devel("SKID: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value);
0641
0642 ctx->raw_skid = value;
0643 ctx->raw_skid_size = vlen;
0644 return 0;
0645 }
0646
0647
0648
0649
0650 int pkcs7_sig_note_signature(void *context, size_t hdrlen,
0651 unsigned char tag,
0652 const void *value, size_t vlen)
0653 {
0654 struct pkcs7_parse_context *ctx = context;
0655
0656 ctx->sinfo->sig->s = kmemdup(value, vlen, GFP_KERNEL);
0657 if (!ctx->sinfo->sig->s)
0658 return -ENOMEM;
0659
0660 ctx->sinfo->sig->s_size = vlen;
0661 return 0;
0662 }
0663
0664
0665
0666
0667 int pkcs7_note_signed_info(void *context, size_t hdrlen,
0668 unsigned char tag,
0669 const void *value, size_t vlen)
0670 {
0671 struct pkcs7_parse_context *ctx = context;
0672 struct pkcs7_signed_info *sinfo = ctx->sinfo;
0673 struct asymmetric_key_id *kid;
0674
0675 if (ctx->msg->data_type == OID_msIndirectData && !sinfo->authattrs) {
0676 pr_warn("Authenticode requires AuthAttrs\n");
0677 return -EBADMSG;
0678 }
0679
0680
0681 if (!ctx->expect_skid) {
0682 kid = asymmetric_key_generate_id(ctx->raw_serial,
0683 ctx->raw_serial_size,
0684 ctx->raw_issuer,
0685 ctx->raw_issuer_size);
0686 } else {
0687 kid = asymmetric_key_generate_id(ctx->raw_skid,
0688 ctx->raw_skid_size,
0689 "", 0);
0690 }
0691 if (IS_ERR(kid))
0692 return PTR_ERR(kid);
0693
0694 pr_devel("SINFO KID: %u [%*phN]\n", kid->len, kid->len, kid->data);
0695
0696 sinfo->sig->auth_ids[0] = kid;
0697 sinfo->index = ++ctx->sinfo_index;
0698 *ctx->ppsinfo = sinfo;
0699 ctx->ppsinfo = &sinfo->next;
0700 ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
0701 if (!ctx->sinfo)
0702 return -ENOMEM;
0703 ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature),
0704 GFP_KERNEL);
0705 if (!ctx->sinfo->sig)
0706 return -ENOMEM;
0707 return 0;
0708 }