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