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