1 /* PKCS#7 parser 2 * 3 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public Licence 8 * as published by the Free Software Foundation; either version 9 * 2 of the Licence, or (at your option) any later version. 10 */ 11 12 #define pr_fmt(fmt) "PKCS7: "fmt 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/export.h> 16 #include <linux/slab.h> 17 #include <linux/err.h> 18 #include <linux/oid_registry.h> 19 #include <crypto/public_key.h> 20 #include "pkcs7_parser.h" 21 #include "pkcs7.asn1.h" 22 23 MODULE_DESCRIPTION("PKCS#7 parser"); 24 MODULE_AUTHOR("Red Hat, Inc."); 25 MODULE_LICENSE("GPL"); 26 27 struct pkcs7_parse_context { 28 struct pkcs7_message *msg; /* Message being constructed */ 29 struct pkcs7_signed_info *sinfo; /* SignedInfo being constructed */ 30 struct pkcs7_signed_info **ppsinfo; 31 struct x509_certificate *certs; /* Certificate cache */ 32 struct x509_certificate **ppcerts; 33 unsigned long data; /* Start of data */ 34 enum OID last_oid; /* Last OID encountered */ 35 unsigned x509_index; 36 unsigned sinfo_index; 37 const void *raw_serial; 38 unsigned raw_serial_size; 39 unsigned raw_issuer_size; 40 const void *raw_issuer; 41 const void *raw_skid; 42 unsigned raw_skid_size; 43 bool expect_skid; 44 }; 45 46 /* 47 * Free a signed information block. 48 */ 49 static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo) 50 { 51 if (sinfo) { 52 public_key_signature_free(sinfo->sig); 53 kfree(sinfo); 54 } 55 } 56 57 /** 58 * pkcs7_free_message - Free a PKCS#7 message 59 * @pkcs7: The PKCS#7 message to free 60 */ 61 void pkcs7_free_message(struct pkcs7_message *pkcs7) 62 { 63 struct x509_certificate *cert; 64 struct pkcs7_signed_info *sinfo; 65 66 if (pkcs7) { 67 while (pkcs7->certs) { 68 cert = pkcs7->certs; 69 pkcs7->certs = cert->next; 70 x509_free_certificate(cert); 71 } 72 while (pkcs7->crl) { 73 cert = pkcs7->crl; 74 pkcs7->crl = cert->next; 75 x509_free_certificate(cert); 76 } 77 while (pkcs7->signed_infos) { 78 sinfo = pkcs7->signed_infos; 79 pkcs7->signed_infos = sinfo->next; 80 pkcs7_free_signed_info(sinfo); 81 } 82 kfree(pkcs7); 83 } 84 } 85 EXPORT_SYMBOL_GPL(pkcs7_free_message); 86 87 /* 88 * Check authenticatedAttributes are provided or not provided consistently. 89 */ 90 static int pkcs7_check_authattrs(struct pkcs7_message *msg) 91 { 92 struct pkcs7_signed_info *sinfo; 93 bool want = false; 94 95 sinfo = msg->signed_infos; 96 if (!sinfo) 97 goto inconsistent; 98 99 if (sinfo->authattrs) { 100 want = true; 101 msg->have_authattrs = true; 102 } 103 104 for (sinfo = sinfo->next; sinfo; sinfo = sinfo->next) 105 if (!!sinfo->authattrs != want) 106 goto inconsistent; 107 return 0; 108 109 inconsistent: 110 pr_warn("Inconsistently supplied authAttrs\n"); 111 return -EINVAL; 112 } 113 114 /** 115 * pkcs7_parse_message - Parse a PKCS#7 message 116 * @data: The raw binary ASN.1 encoded message to be parsed 117 * @datalen: The size of the encoded message 118 */ 119 struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen) 120 { 121 struct pkcs7_parse_context *ctx; 122 struct pkcs7_message *msg = ERR_PTR(-ENOMEM); 123 int ret; 124 125 ctx = kzalloc(sizeof(struct pkcs7_parse_context), GFP_KERNEL); 126 if (!ctx) 127 goto out_no_ctx; 128 ctx->msg = kzalloc(sizeof(struct pkcs7_message), GFP_KERNEL); 129 if (!ctx->msg) 130 goto out_no_msg; 131 ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL); 132 if (!ctx->sinfo) 133 goto out_no_sinfo; 134 ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature), 135 GFP_KERNEL); 136 if (!ctx->sinfo->sig) 137 goto out_no_sig; 138 139 ctx->data = (unsigned long)data; 140 ctx->ppcerts = &ctx->certs; 141 ctx->ppsinfo = &ctx->msg->signed_infos; 142 143 /* Attempt to decode the signature */ 144 ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen); 145 if (ret < 0) { 146 msg = ERR_PTR(ret); 147 goto out; 148 } 149 150 ret = pkcs7_check_authattrs(ctx->msg); 151 if (ret < 0) { 152 msg = ERR_PTR(ret); 153 goto out; 154 } 155 156 msg = ctx->msg; 157 ctx->msg = NULL; 158 159 out: 160 while (ctx->certs) { 161 struct x509_certificate *cert = ctx->certs; 162 ctx->certs = cert->next; 163 x509_free_certificate(cert); 164 } 165 out_no_sig: 166 pkcs7_free_signed_info(ctx->sinfo); 167 out_no_sinfo: 168 pkcs7_free_message(ctx->msg); 169 out_no_msg: 170 kfree(ctx); 171 out_no_ctx: 172 return msg; 173 } 174 EXPORT_SYMBOL_GPL(pkcs7_parse_message); 175 176 /** 177 * pkcs7_get_content_data - Get access to the PKCS#7 content 178 * @pkcs7: The preparsed PKCS#7 message to access 179 * @_data: Place to return a pointer to the data 180 * @_data_len: Place to return the data length 181 * @_headerlen: Size of ASN.1 header not included in _data 182 * 183 * Get access to the data content of the PKCS#7 message. The size of the 184 * header of the ASN.1 object that contains it is also provided and can be used 185 * to adjust *_data and *_data_len to get the entire object. 186 * 187 * Returns -ENODATA if the data object was missing from the message. 188 */ 189 int pkcs7_get_content_data(const struct pkcs7_message *pkcs7, 190 const void **_data, size_t *_data_len, 191 size_t *_headerlen) 192 { 193 if (!pkcs7->data) 194 return -ENODATA; 195 196 *_data = pkcs7->data; 197 *_data_len = pkcs7->data_len; 198 if (_headerlen) 199 *_headerlen = pkcs7->data_hdrlen; 200 return 0; 201 } 202 EXPORT_SYMBOL_GPL(pkcs7_get_content_data); 203 204 /* 205 * Note an OID when we find one for later processing when we know how 206 * to interpret it. 207 */ 208 int pkcs7_note_OID(void *context, size_t hdrlen, 209 unsigned char tag, 210 const void *value, size_t vlen) 211 { 212 struct pkcs7_parse_context *ctx = context; 213 214 ctx->last_oid = look_up_OID(value, vlen); 215 if (ctx->last_oid == OID__NR) { 216 char buffer[50]; 217 sprint_oid(value, vlen, buffer, sizeof(buffer)); 218 printk("PKCS7: Unknown OID: [%lu] %s\n", 219 (unsigned long)value - ctx->data, buffer); 220 } 221 return 0; 222 } 223 224 /* 225 * Note the digest algorithm for the signature. 226 */ 227 int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen, 228 unsigned char tag, 229 const void *value, size_t vlen) 230 { 231 struct pkcs7_parse_context *ctx = context; 232 233 switch (ctx->last_oid) { 234 case OID_md4: 235 ctx->sinfo->sig->hash_algo = "md4"; 236 break; 237 case OID_md5: 238 ctx->sinfo->sig->hash_algo = "md5"; 239 break; 240 case OID_sha1: 241 ctx->sinfo->sig->hash_algo = "sha1"; 242 break; 243 case OID_sha256: 244 ctx->sinfo->sig->hash_algo = "sha256"; 245 break; 246 case OID_sha384: 247 ctx->sinfo->sig->hash_algo = "sha384"; 248 break; 249 case OID_sha512: 250 ctx->sinfo->sig->hash_algo = "sha512"; 251 break; 252 case OID_sha224: 253 ctx->sinfo->sig->hash_algo = "sha224"; 254 break; 255 default: 256 printk("Unsupported digest algo: %u\n", ctx->last_oid); 257 return -ENOPKG; 258 } 259 return 0; 260 } 261 262 /* 263 * Note the public key algorithm for the signature. 264 */ 265 int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen, 266 unsigned char tag, 267 const void *value, size_t vlen) 268 { 269 struct pkcs7_parse_context *ctx = context; 270 271 switch (ctx->last_oid) { 272 case OID_rsaEncryption: 273 ctx->sinfo->sig->pkey_algo = "rsa"; 274 ctx->sinfo->sig->encoding = "pkcs1"; 275 break; 276 default: 277 printk("Unsupported pkey algo: %u\n", ctx->last_oid); 278 return -ENOPKG; 279 } 280 return 0; 281 } 282 283 /* 284 * We only support signed data [RFC2315 sec 9]. 285 */ 286 int pkcs7_check_content_type(void *context, size_t hdrlen, 287 unsigned char tag, 288 const void *value, size_t vlen) 289 { 290 struct pkcs7_parse_context *ctx = context; 291 292 if (ctx->last_oid != OID_signed_data) { 293 pr_warn("Only support pkcs7_signedData type\n"); 294 return -EINVAL; 295 } 296 297 return 0; 298 } 299 300 /* 301 * Note the SignedData version 302 */ 303 int pkcs7_note_signeddata_version(void *context, size_t hdrlen, 304 unsigned char tag, 305 const void *value, size_t vlen) 306 { 307 struct pkcs7_parse_context *ctx = context; 308 unsigned version; 309 310 if (vlen != 1) 311 goto unsupported; 312 313 ctx->msg->version = version = *(const u8 *)value; 314 switch (version) { 315 case 1: 316 /* PKCS#7 SignedData [RFC2315 sec 9.1] 317 * CMS ver 1 SignedData [RFC5652 sec 5.1] 318 */ 319 break; 320 case 3: 321 /* CMS ver 3 SignedData [RFC2315 sec 5.1] */ 322 break; 323 default: 324 goto unsupported; 325 } 326 327 return 0; 328 329 unsupported: 330 pr_warn("Unsupported SignedData version\n"); 331 return -EINVAL; 332 } 333 334 /* 335 * Note the SignerInfo version 336 */ 337 int pkcs7_note_signerinfo_version(void *context, size_t hdrlen, 338 unsigned char tag, 339 const void *value, size_t vlen) 340 { 341 struct pkcs7_parse_context *ctx = context; 342 unsigned version; 343 344 if (vlen != 1) 345 goto unsupported; 346 347 version = *(const u8 *)value; 348 switch (version) { 349 case 1: 350 /* PKCS#7 SignerInfo [RFC2315 sec 9.2] 351 * CMS ver 1 SignerInfo [RFC5652 sec 5.3] 352 */ 353 if (ctx->msg->version != 1) 354 goto version_mismatch; 355 ctx->expect_skid = false; 356 break; 357 case 3: 358 /* CMS ver 3 SignerInfo [RFC2315 sec 5.3] */ 359 if (ctx->msg->version == 1) 360 goto version_mismatch; 361 ctx->expect_skid = true; 362 break; 363 default: 364 goto unsupported; 365 } 366 367 return 0; 368 369 unsupported: 370 pr_warn("Unsupported SignerInfo version\n"); 371 return -EINVAL; 372 version_mismatch: 373 pr_warn("SignedData-SignerInfo version mismatch\n"); 374 return -EBADMSG; 375 } 376 377 /* 378 * Extract a certificate and store it in the context. 379 */ 380 int pkcs7_extract_cert(void *context, size_t hdrlen, 381 unsigned char tag, 382 const void *value, size_t vlen) 383 { 384 struct pkcs7_parse_context *ctx = context; 385 struct x509_certificate *x509; 386 387 if (tag != ((ASN1_UNIV << 6) | ASN1_CONS_BIT | ASN1_SEQ)) { 388 pr_debug("Cert began with tag %02x at %lu\n", 389 tag, (unsigned long)ctx - ctx->data); 390 return -EBADMSG; 391 } 392 393 /* We have to correct for the header so that the X.509 parser can start 394 * from the beginning. Note that since X.509 stipulates DER, there 395 * probably shouldn't be an EOC trailer - but it is in PKCS#7 (which 396 * stipulates BER). 397 */ 398 value -= hdrlen; 399 vlen += hdrlen; 400 401 if (((u8*)value)[1] == 0x80) 402 vlen += 2; /* Indefinite length - there should be an EOC */ 403 404 x509 = x509_cert_parse(value, vlen); 405 if (IS_ERR(x509)) 406 return PTR_ERR(x509); 407 408 x509->index = ++ctx->x509_index; 409 pr_debug("Got cert %u for %s\n", x509->index, x509->subject); 410 pr_debug("- fingerprint %*phN\n", x509->id->len, x509->id->data); 411 412 *ctx->ppcerts = x509; 413 ctx->ppcerts = &x509->next; 414 return 0; 415 } 416 417 /* 418 * Save the certificate list 419 */ 420 int pkcs7_note_certificate_list(void *context, size_t hdrlen, 421 unsigned char tag, 422 const void *value, size_t vlen) 423 { 424 struct pkcs7_parse_context *ctx = context; 425 426 pr_devel("Got cert list (%02x)\n", tag); 427 428 *ctx->ppcerts = ctx->msg->certs; 429 ctx->msg->certs = ctx->certs; 430 ctx->certs = NULL; 431 ctx->ppcerts = &ctx->certs; 432 return 0; 433 } 434 435 /* 436 * Note the content type. 437 */ 438 int pkcs7_note_content(void *context, size_t hdrlen, 439 unsigned char tag, 440 const void *value, size_t vlen) 441 { 442 struct pkcs7_parse_context *ctx = context; 443 444 if (ctx->last_oid != OID_data && 445 ctx->last_oid != OID_msIndirectData) { 446 pr_warn("Unsupported data type %d\n", ctx->last_oid); 447 return -EINVAL; 448 } 449 450 ctx->msg->data_type = ctx->last_oid; 451 return 0; 452 } 453 454 /* 455 * Extract the data from the message and store that and its content type OID in 456 * the context. 457 */ 458 int pkcs7_note_data(void *context, size_t hdrlen, 459 unsigned char tag, 460 const void *value, size_t vlen) 461 { 462 struct pkcs7_parse_context *ctx = context; 463 464 pr_debug("Got data\n"); 465 466 ctx->msg->data = value; 467 ctx->msg->data_len = vlen; 468 ctx->msg->data_hdrlen = hdrlen; 469 return 0; 470 } 471 472 /* 473 * Parse authenticated attributes. 474 */ 475 int pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen, 476 unsigned char tag, 477 const void *value, size_t vlen) 478 { 479 struct pkcs7_parse_context *ctx = context; 480 struct pkcs7_signed_info *sinfo = ctx->sinfo; 481 enum OID content_type; 482 483 pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value); 484 485 switch (ctx->last_oid) { 486 case OID_contentType: 487 if (__test_and_set_bit(sinfo_has_content_type, &sinfo->aa_set)) 488 goto repeated; 489 content_type = look_up_OID(value, vlen); 490 if (content_type != ctx->msg->data_type) { 491 pr_warn("Mismatch between global data type (%d) and sinfo %u (%d)\n", 492 ctx->msg->data_type, sinfo->index, 493 content_type); 494 return -EBADMSG; 495 } 496 return 0; 497 498 case OID_signingTime: 499 if (__test_and_set_bit(sinfo_has_signing_time, &sinfo->aa_set)) 500 goto repeated; 501 /* Should we check that the signing time is consistent 502 * with the signer's X.509 cert? 503 */ 504 return x509_decode_time(&sinfo->signing_time, 505 hdrlen, tag, value, vlen); 506 507 case OID_messageDigest: 508 if (__test_and_set_bit(sinfo_has_message_digest, &sinfo->aa_set)) 509 goto repeated; 510 if (tag != ASN1_OTS) 511 return -EBADMSG; 512 sinfo->msgdigest = value; 513 sinfo->msgdigest_len = vlen; 514 return 0; 515 516 case OID_smimeCapabilites: 517 if (__test_and_set_bit(sinfo_has_smime_caps, &sinfo->aa_set)) 518 goto repeated; 519 if (ctx->msg->data_type != OID_msIndirectData) { 520 pr_warn("S/MIME Caps only allowed with Authenticode\n"); 521 return -EKEYREJECTED; 522 } 523 return 0; 524 525 /* Microsoft SpOpusInfo seems to be contain cont[0] 16-bit BE 526 * char URLs and cont[1] 8-bit char URLs. 527 * 528 * Microsoft StatementType seems to contain a list of OIDs that 529 * are also used as extendedKeyUsage types in X.509 certs. 530 */ 531 case OID_msSpOpusInfo: 532 if (__test_and_set_bit(sinfo_has_ms_opus_info, &sinfo->aa_set)) 533 goto repeated; 534 goto authenticode_check; 535 case OID_msStatementType: 536 if (__test_and_set_bit(sinfo_has_ms_statement_type, &sinfo->aa_set)) 537 goto repeated; 538 authenticode_check: 539 if (ctx->msg->data_type != OID_msIndirectData) { 540 pr_warn("Authenticode AuthAttrs only allowed with Authenticode\n"); 541 return -EKEYREJECTED; 542 } 543 /* I'm not sure how to validate these */ 544 return 0; 545 default: 546 return 0; 547 } 548 549 repeated: 550 /* We permit max one item per AuthenticatedAttribute and no repeats */ 551 pr_warn("Repeated/multivalue AuthAttrs not permitted\n"); 552 return -EKEYREJECTED; 553 } 554 555 /* 556 * Note the set of auth attributes for digestion purposes [RFC2315 sec 9.3] 557 */ 558 int pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen, 559 unsigned char tag, 560 const void *value, size_t vlen) 561 { 562 struct pkcs7_parse_context *ctx = context; 563 struct pkcs7_signed_info *sinfo = ctx->sinfo; 564 565 if (!test_bit(sinfo_has_content_type, &sinfo->aa_set) || 566 !test_bit(sinfo_has_message_digest, &sinfo->aa_set)) { 567 pr_warn("Missing required AuthAttr\n"); 568 return -EBADMSG; 569 } 570 571 if (ctx->msg->data_type != OID_msIndirectData && 572 test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set)) { 573 pr_warn("Unexpected Authenticode AuthAttr\n"); 574 return -EBADMSG; 575 } 576 577 /* We need to switch the 'CONT 0' to a 'SET OF' when we digest */ 578 sinfo->authattrs = value - (hdrlen - 1); 579 sinfo->authattrs_len = vlen + (hdrlen - 1); 580 return 0; 581 } 582 583 /* 584 * Note the issuing certificate serial number 585 */ 586 int pkcs7_sig_note_serial(void *context, size_t hdrlen, 587 unsigned char tag, 588 const void *value, size_t vlen) 589 { 590 struct pkcs7_parse_context *ctx = context; 591 ctx->raw_serial = value; 592 ctx->raw_serial_size = vlen; 593 return 0; 594 } 595 596 /* 597 * Note the issuer's name 598 */ 599 int pkcs7_sig_note_issuer(void *context, size_t hdrlen, 600 unsigned char tag, 601 const void *value, size_t vlen) 602 { 603 struct pkcs7_parse_context *ctx = context; 604 ctx->raw_issuer = value; 605 ctx->raw_issuer_size = vlen; 606 return 0; 607 } 608 609 /* 610 * Note the issuing cert's subjectKeyIdentifier 611 */ 612 int pkcs7_sig_note_skid(void *context, size_t hdrlen, 613 unsigned char tag, 614 const void *value, size_t vlen) 615 { 616 struct pkcs7_parse_context *ctx = context; 617 618 pr_devel("SKID: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value); 619 620 ctx->raw_skid = value; 621 ctx->raw_skid_size = vlen; 622 return 0; 623 } 624 625 /* 626 * Note the signature data 627 */ 628 int pkcs7_sig_note_signature(void *context, size_t hdrlen, 629 unsigned char tag, 630 const void *value, size_t vlen) 631 { 632 struct pkcs7_parse_context *ctx = context; 633 634 ctx->sinfo->sig->s = kmemdup(value, vlen, GFP_KERNEL); 635 if (!ctx->sinfo->sig->s) 636 return -ENOMEM; 637 638 ctx->sinfo->sig->s_size = vlen; 639 return 0; 640 } 641 642 /* 643 * Note a signature information block 644 */ 645 int pkcs7_note_signed_info(void *context, size_t hdrlen, 646 unsigned char tag, 647 const void *value, size_t vlen) 648 { 649 struct pkcs7_parse_context *ctx = context; 650 struct pkcs7_signed_info *sinfo = ctx->sinfo; 651 struct asymmetric_key_id *kid; 652 653 if (ctx->msg->data_type == OID_msIndirectData && !sinfo->authattrs) { 654 pr_warn("Authenticode requires AuthAttrs\n"); 655 return -EBADMSG; 656 } 657 658 /* Generate cert issuer + serial number key ID */ 659 if (!ctx->expect_skid) { 660 kid = asymmetric_key_generate_id(ctx->raw_serial, 661 ctx->raw_serial_size, 662 ctx->raw_issuer, 663 ctx->raw_issuer_size); 664 } else { 665 kid = asymmetric_key_generate_id(ctx->raw_skid, 666 ctx->raw_skid_size, 667 "", 0); 668 } 669 if (IS_ERR(kid)) 670 return PTR_ERR(kid); 671 672 pr_devel("SINFO KID: %u [%*phN]\n", kid->len, kid->len, kid->data); 673 674 sinfo->sig->auth_ids[0] = kid; 675 sinfo->index = ++ctx->sinfo_index; 676 *ctx->ppsinfo = sinfo; 677 ctx->ppsinfo = &sinfo->next; 678 ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL); 679 if (!ctx->sinfo) 680 return -ENOMEM; 681 ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature), 682 GFP_KERNEL); 683 if (!ctx->sinfo->sig) 684 return -ENOMEM; 685 return 0; 686 } 687