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 goto out; 153 154 msg = ctx->msg; 155 ctx->msg = NULL; 156 157 out: 158 while (ctx->certs) { 159 struct x509_certificate *cert = ctx->certs; 160 ctx->certs = cert->next; 161 x509_free_certificate(cert); 162 } 163 out_no_sig: 164 pkcs7_free_signed_info(ctx->sinfo); 165 out_no_sinfo: 166 pkcs7_free_message(ctx->msg); 167 out_no_msg: 168 kfree(ctx); 169 out_no_ctx: 170 return msg; 171 } 172 EXPORT_SYMBOL_GPL(pkcs7_parse_message); 173 174 /** 175 * pkcs7_get_content_data - Get access to the PKCS#7 content 176 * @pkcs7: The preparsed PKCS#7 message to access 177 * @_data: Place to return a pointer to the data 178 * @_data_len: Place to return the data length 179 * @_headerlen: Size of ASN.1 header not included in _data 180 * 181 * Get access to the data content of the PKCS#7 message. The size of the 182 * header of the ASN.1 object that contains it is also provided and can be used 183 * to adjust *_data and *_data_len to get the entire object. 184 * 185 * Returns -ENODATA if the data object was missing from the message. 186 */ 187 int pkcs7_get_content_data(const struct pkcs7_message *pkcs7, 188 const void **_data, size_t *_data_len, 189 size_t *_headerlen) 190 { 191 if (!pkcs7->data) 192 return -ENODATA; 193 194 *_data = pkcs7->data; 195 *_data_len = pkcs7->data_len; 196 if (_headerlen) 197 *_headerlen = pkcs7->data_hdrlen; 198 return 0; 199 } 200 EXPORT_SYMBOL_GPL(pkcs7_get_content_data); 201 202 /* 203 * Note an OID when we find one for later processing when we know how 204 * to interpret it. 205 */ 206 int pkcs7_note_OID(void *context, size_t hdrlen, 207 unsigned char tag, 208 const void *value, size_t vlen) 209 { 210 struct pkcs7_parse_context *ctx = context; 211 212 ctx->last_oid = look_up_OID(value, vlen); 213 if (ctx->last_oid == OID__NR) { 214 char buffer[50]; 215 sprint_oid(value, vlen, buffer, sizeof(buffer)); 216 printk("PKCS7: Unknown OID: [%lu] %s\n", 217 (unsigned long)value - ctx->data, buffer); 218 } 219 return 0; 220 } 221 222 /* 223 * Note the digest algorithm for the signature. 224 */ 225 int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen, 226 unsigned char tag, 227 const void *value, size_t vlen) 228 { 229 struct pkcs7_parse_context *ctx = context; 230 231 switch (ctx->last_oid) { 232 case OID_md4: 233 ctx->sinfo->sig->hash_algo = "md4"; 234 break; 235 case OID_md5: 236 ctx->sinfo->sig->hash_algo = "md5"; 237 break; 238 case OID_sha1: 239 ctx->sinfo->sig->hash_algo = "sha1"; 240 break; 241 case OID_sha256: 242 ctx->sinfo->sig->hash_algo = "sha256"; 243 break; 244 case OID_sha384: 245 ctx->sinfo->sig->hash_algo = "sha384"; 246 break; 247 case OID_sha512: 248 ctx->sinfo->sig->hash_algo = "sha512"; 249 break; 250 case OID_sha224: 251 ctx->sinfo->sig->hash_algo = "sha224"; 252 break; 253 default: 254 printk("Unsupported digest algo: %u\n", ctx->last_oid); 255 return -ENOPKG; 256 } 257 return 0; 258 } 259 260 /* 261 * Note the public key algorithm for the signature. 262 */ 263 int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen, 264 unsigned char tag, 265 const void *value, size_t vlen) 266 { 267 struct pkcs7_parse_context *ctx = context; 268 269 switch (ctx->last_oid) { 270 case OID_rsaEncryption: 271 ctx->sinfo->sig->pkey_algo = "rsa"; 272 break; 273 default: 274 printk("Unsupported pkey algo: %u\n", ctx->last_oid); 275 return -ENOPKG; 276 } 277 return 0; 278 } 279 280 /* 281 * We only support signed data [RFC2315 sec 9]. 282 */ 283 int pkcs7_check_content_type(void *context, size_t hdrlen, 284 unsigned char tag, 285 const void *value, size_t vlen) 286 { 287 struct pkcs7_parse_context *ctx = context; 288 289 if (ctx->last_oid != OID_signed_data) { 290 pr_warn("Only support pkcs7_signedData type\n"); 291 return -EINVAL; 292 } 293 294 return 0; 295 } 296 297 /* 298 * Note the SignedData version 299 */ 300 int pkcs7_note_signeddata_version(void *context, size_t hdrlen, 301 unsigned char tag, 302 const void *value, size_t vlen) 303 { 304 struct pkcs7_parse_context *ctx = context; 305 unsigned version; 306 307 if (vlen != 1) 308 goto unsupported; 309 310 ctx->msg->version = version = *(const u8 *)value; 311 switch (version) { 312 case 1: 313 /* PKCS#7 SignedData [RFC2315 sec 9.1] 314 * CMS ver 1 SignedData [RFC5652 sec 5.1] 315 */ 316 break; 317 case 3: 318 /* CMS ver 3 SignedData [RFC2315 sec 5.1] */ 319 break; 320 default: 321 goto unsupported; 322 } 323 324 return 0; 325 326 unsupported: 327 pr_warn("Unsupported SignedData version\n"); 328 return -EINVAL; 329 } 330 331 /* 332 * Note the SignerInfo version 333 */ 334 int pkcs7_note_signerinfo_version(void *context, size_t hdrlen, 335 unsigned char tag, 336 const void *value, size_t vlen) 337 { 338 struct pkcs7_parse_context *ctx = context; 339 unsigned version; 340 341 if (vlen != 1) 342 goto unsupported; 343 344 version = *(const u8 *)value; 345 switch (version) { 346 case 1: 347 /* PKCS#7 SignerInfo [RFC2315 sec 9.2] 348 * CMS ver 1 SignerInfo [RFC5652 sec 5.3] 349 */ 350 if (ctx->msg->version != 1) 351 goto version_mismatch; 352 ctx->expect_skid = false; 353 break; 354 case 3: 355 /* CMS ver 3 SignerInfo [RFC2315 sec 5.3] */ 356 if (ctx->msg->version == 1) 357 goto version_mismatch; 358 ctx->expect_skid = true; 359 break; 360 default: 361 goto unsupported; 362 } 363 364 return 0; 365 366 unsupported: 367 pr_warn("Unsupported SignerInfo version\n"); 368 return -EINVAL; 369 version_mismatch: 370 pr_warn("SignedData-SignerInfo version mismatch\n"); 371 return -EBADMSG; 372 } 373 374 /* 375 * Extract a certificate and store it in the context. 376 */ 377 int pkcs7_extract_cert(void *context, size_t hdrlen, 378 unsigned char tag, 379 const void *value, size_t vlen) 380 { 381 struct pkcs7_parse_context *ctx = context; 382 struct x509_certificate *x509; 383 384 if (tag != ((ASN1_UNIV << 6) | ASN1_CONS_BIT | ASN1_SEQ)) { 385 pr_debug("Cert began with tag %02x at %lu\n", 386 tag, (unsigned long)ctx - ctx->data); 387 return -EBADMSG; 388 } 389 390 /* We have to correct for the header so that the X.509 parser can start 391 * from the beginning. Note that since X.509 stipulates DER, there 392 * probably shouldn't be an EOC trailer - but it is in PKCS#7 (which 393 * stipulates BER). 394 */ 395 value -= hdrlen; 396 vlen += hdrlen; 397 398 if (((u8*)value)[1] == 0x80) 399 vlen += 2; /* Indefinite length - there should be an EOC */ 400 401 x509 = x509_cert_parse(value, vlen); 402 if (IS_ERR(x509)) 403 return PTR_ERR(x509); 404 405 x509->index = ++ctx->x509_index; 406 pr_debug("Got cert %u for %s\n", x509->index, x509->subject); 407 pr_debug("- fingerprint %*phN\n", x509->id->len, x509->id->data); 408 409 *ctx->ppcerts = x509; 410 ctx->ppcerts = &x509->next; 411 return 0; 412 } 413 414 /* 415 * Save the certificate list 416 */ 417 int pkcs7_note_certificate_list(void *context, size_t hdrlen, 418 unsigned char tag, 419 const void *value, size_t vlen) 420 { 421 struct pkcs7_parse_context *ctx = context; 422 423 pr_devel("Got cert list (%02x)\n", tag); 424 425 *ctx->ppcerts = ctx->msg->certs; 426 ctx->msg->certs = ctx->certs; 427 ctx->certs = NULL; 428 ctx->ppcerts = &ctx->certs; 429 return 0; 430 } 431 432 /* 433 * Note the content type. 434 */ 435 int pkcs7_note_content(void *context, size_t hdrlen, 436 unsigned char tag, 437 const void *value, size_t vlen) 438 { 439 struct pkcs7_parse_context *ctx = context; 440 441 if (ctx->last_oid != OID_data && 442 ctx->last_oid != OID_msIndirectData) { 443 pr_warn("Unsupported data type %d\n", ctx->last_oid); 444 return -EINVAL; 445 } 446 447 ctx->msg->data_type = ctx->last_oid; 448 return 0; 449 } 450 451 /* 452 * Extract the data from the message and store that and its content type OID in 453 * the context. 454 */ 455 int pkcs7_note_data(void *context, size_t hdrlen, 456 unsigned char tag, 457 const void *value, size_t vlen) 458 { 459 struct pkcs7_parse_context *ctx = context; 460 461 pr_debug("Got data\n"); 462 463 ctx->msg->data = value; 464 ctx->msg->data_len = vlen; 465 ctx->msg->data_hdrlen = hdrlen; 466 return 0; 467 } 468 469 /* 470 * Parse authenticated attributes. 471 */ 472 int pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen, 473 unsigned char tag, 474 const void *value, size_t vlen) 475 { 476 struct pkcs7_parse_context *ctx = context; 477 struct pkcs7_signed_info *sinfo = ctx->sinfo; 478 enum OID content_type; 479 480 pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value); 481 482 switch (ctx->last_oid) { 483 case OID_contentType: 484 if (__test_and_set_bit(sinfo_has_content_type, &sinfo->aa_set)) 485 goto repeated; 486 content_type = look_up_OID(value, vlen); 487 if (content_type != ctx->msg->data_type) { 488 pr_warn("Mismatch between global data type (%d) and sinfo %u (%d)\n", 489 ctx->msg->data_type, sinfo->index, 490 content_type); 491 return -EBADMSG; 492 } 493 return 0; 494 495 case OID_signingTime: 496 if (__test_and_set_bit(sinfo_has_signing_time, &sinfo->aa_set)) 497 goto repeated; 498 /* Should we check that the signing time is consistent 499 * with the signer's X.509 cert? 500 */ 501 return x509_decode_time(&sinfo->signing_time, 502 hdrlen, tag, value, vlen); 503 504 case OID_messageDigest: 505 if (__test_and_set_bit(sinfo_has_message_digest, &sinfo->aa_set)) 506 goto repeated; 507 if (tag != ASN1_OTS) 508 return -EBADMSG; 509 sinfo->msgdigest = value; 510 sinfo->msgdigest_len = vlen; 511 return 0; 512 513 case OID_smimeCapabilites: 514 if (__test_and_set_bit(sinfo_has_smime_caps, &sinfo->aa_set)) 515 goto repeated; 516 if (ctx->msg->data_type != OID_msIndirectData) { 517 pr_warn("S/MIME Caps only allowed with Authenticode\n"); 518 return -EKEYREJECTED; 519 } 520 return 0; 521 522 /* Microsoft SpOpusInfo seems to be contain cont[0] 16-bit BE 523 * char URLs and cont[1] 8-bit char URLs. 524 * 525 * Microsoft StatementType seems to contain a list of OIDs that 526 * are also used as extendedKeyUsage types in X.509 certs. 527 */ 528 case OID_msSpOpusInfo: 529 if (__test_and_set_bit(sinfo_has_ms_opus_info, &sinfo->aa_set)) 530 goto repeated; 531 goto authenticode_check; 532 case OID_msStatementType: 533 if (__test_and_set_bit(sinfo_has_ms_statement_type, &sinfo->aa_set)) 534 goto repeated; 535 authenticode_check: 536 if (ctx->msg->data_type != OID_msIndirectData) { 537 pr_warn("Authenticode AuthAttrs only allowed with Authenticode\n"); 538 return -EKEYREJECTED; 539 } 540 /* I'm not sure how to validate these */ 541 return 0; 542 default: 543 return 0; 544 } 545 546 repeated: 547 /* We permit max one item per AuthenticatedAttribute and no repeats */ 548 pr_warn("Repeated/multivalue AuthAttrs not permitted\n"); 549 return -EKEYREJECTED; 550 } 551 552 /* 553 * Note the set of auth attributes for digestion purposes [RFC2315 sec 9.3] 554 */ 555 int pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen, 556 unsigned char tag, 557 const void *value, size_t vlen) 558 { 559 struct pkcs7_parse_context *ctx = context; 560 struct pkcs7_signed_info *sinfo = ctx->sinfo; 561 562 if (!test_bit(sinfo_has_content_type, &sinfo->aa_set) || 563 !test_bit(sinfo_has_message_digest, &sinfo->aa_set)) { 564 pr_warn("Missing required AuthAttr\n"); 565 return -EBADMSG; 566 } 567 568 if (ctx->msg->data_type != OID_msIndirectData && 569 test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set)) { 570 pr_warn("Unexpected Authenticode AuthAttr\n"); 571 return -EBADMSG; 572 } 573 574 /* We need to switch the 'CONT 0' to a 'SET OF' when we digest */ 575 sinfo->authattrs = value - (hdrlen - 1); 576 sinfo->authattrs_len = vlen + (hdrlen - 1); 577 return 0; 578 } 579 580 /* 581 * Note the issuing certificate serial number 582 */ 583 int pkcs7_sig_note_serial(void *context, size_t hdrlen, 584 unsigned char tag, 585 const void *value, size_t vlen) 586 { 587 struct pkcs7_parse_context *ctx = context; 588 ctx->raw_serial = value; 589 ctx->raw_serial_size = vlen; 590 return 0; 591 } 592 593 /* 594 * Note the issuer's name 595 */ 596 int pkcs7_sig_note_issuer(void *context, size_t hdrlen, 597 unsigned char tag, 598 const void *value, size_t vlen) 599 { 600 struct pkcs7_parse_context *ctx = context; 601 ctx->raw_issuer = value; 602 ctx->raw_issuer_size = vlen; 603 return 0; 604 } 605 606 /* 607 * Note the issuing cert's subjectKeyIdentifier 608 */ 609 int pkcs7_sig_note_skid(void *context, size_t hdrlen, 610 unsigned char tag, 611 const void *value, size_t vlen) 612 { 613 struct pkcs7_parse_context *ctx = context; 614 615 pr_devel("SKID: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value); 616 617 ctx->raw_skid = value; 618 ctx->raw_skid_size = vlen; 619 return 0; 620 } 621 622 /* 623 * Note the signature data 624 */ 625 int pkcs7_sig_note_signature(void *context, size_t hdrlen, 626 unsigned char tag, 627 const void *value, size_t vlen) 628 { 629 struct pkcs7_parse_context *ctx = context; 630 631 ctx->sinfo->sig->s = kmemdup(value, vlen, GFP_KERNEL); 632 if (!ctx->sinfo->sig->s) 633 return -ENOMEM; 634 635 ctx->sinfo->sig->s_size = vlen; 636 return 0; 637 } 638 639 /* 640 * Note a signature information block 641 */ 642 int pkcs7_note_signed_info(void *context, size_t hdrlen, 643 unsigned char tag, 644 const void *value, size_t vlen) 645 { 646 struct pkcs7_parse_context *ctx = context; 647 struct pkcs7_signed_info *sinfo = ctx->sinfo; 648 struct asymmetric_key_id *kid; 649 650 if (ctx->msg->data_type == OID_msIndirectData && !sinfo->authattrs) { 651 pr_warn("Authenticode requires AuthAttrs\n"); 652 return -EBADMSG; 653 } 654 655 /* Generate cert issuer + serial number key ID */ 656 if (!ctx->expect_skid) { 657 kid = asymmetric_key_generate_id(ctx->raw_serial, 658 ctx->raw_serial_size, 659 ctx->raw_issuer, 660 ctx->raw_issuer_size); 661 } else { 662 kid = asymmetric_key_generate_id(ctx->raw_skid, 663 ctx->raw_skid_size, 664 "", 0); 665 } 666 if (IS_ERR(kid)) 667 return PTR_ERR(kid); 668 669 pr_devel("SINFO KID: %u [%*phN]\n", kid->len, kid->len, kid->data); 670 671 sinfo->sig->auth_ids[0] = kid; 672 sinfo->index = ++ctx->sinfo_index; 673 *ctx->ppsinfo = sinfo; 674 ctx->ppsinfo = &sinfo->next; 675 ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL); 676 if (!ctx->sinfo) 677 return -ENOMEM; 678 ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature), 679 GFP_KERNEL); 680 if (!ctx->sinfo->sig) 681 return -ENOMEM; 682 return 0; 683 } 684