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