tlsv1_cred.c revision 1b46775bb44f06b3cc285481ff5f7a673559ed7d
1/* 2 * TLSv1 credentials 3 * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9#include "includes.h" 10 11#include "common.h" 12#include "base64.h" 13#include "crypto/crypto.h" 14#include "crypto/sha1.h" 15#include "pkcs5.h" 16#include "pkcs8.h" 17#include "x509v3.h" 18#include "tlsv1_cred.h" 19 20 21struct tlsv1_credentials * tlsv1_cred_alloc(void) 22{ 23 struct tlsv1_credentials *cred; 24 cred = os_zalloc(sizeof(*cred)); 25 return cred; 26} 27 28 29void tlsv1_cred_free(struct tlsv1_credentials *cred) 30{ 31 if (cred == NULL) 32 return; 33 34 x509_certificate_chain_free(cred->trusted_certs); 35 x509_certificate_chain_free(cred->cert); 36 crypto_private_key_free(cred->key); 37 os_free(cred->dh_p); 38 os_free(cred->dh_g); 39 os_free(cred); 40} 41 42 43static int tlsv1_add_cert_der(struct x509_certificate **chain, 44 const u8 *buf, size_t len) 45{ 46 struct x509_certificate *cert, *p; 47 char name[128]; 48 49 cert = x509_certificate_parse(buf, len); 50 if (cert == NULL) { 51 wpa_printf(MSG_INFO, "TLSv1: %s - failed to parse certificate", 52 __func__); 53 return -1; 54 } 55 56 p = *chain; 57 while (p && p->next) 58 p = p->next; 59 if (p && x509_name_compare(&cert->subject, &p->issuer) == 0) { 60 /* 61 * The new certificate is the issuer of the last certificate in 62 * the chain - add the new certificate to the end. 63 */ 64 p->next = cert; 65 } else { 66 /* Add to the beginning of the chain */ 67 cert->next = *chain; 68 *chain = cert; 69 } 70 71 x509_name_string(&cert->subject, name, sizeof(name)); 72 wpa_printf(MSG_DEBUG, "TLSv1: Added certificate: %s", name); 73 74 return 0; 75} 76 77 78static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----"; 79static const char *pem_cert_end = "-----END CERTIFICATE-----"; 80static const char *pem_key_begin = "-----BEGIN RSA PRIVATE KEY-----"; 81static const char *pem_key_end = "-----END RSA PRIVATE KEY-----"; 82static const char *pem_key2_begin = "-----BEGIN PRIVATE KEY-----"; 83static const char *pem_key2_end = "-----END PRIVATE KEY-----"; 84static const char *pem_key_enc_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; 85static const char *pem_key_enc_end = "-----END ENCRYPTED PRIVATE KEY-----"; 86 87 88static const u8 * search_tag(const char *tag, const u8 *buf, size_t len) 89{ 90 size_t i, plen; 91 92 plen = os_strlen(tag); 93 if (len < plen) 94 return NULL; 95 96 for (i = 0; i < len - plen; i++) { 97 if (os_memcmp(buf + i, tag, plen) == 0) 98 return buf + i; 99 } 100 101 return NULL; 102} 103 104 105static int tlsv1_add_cert(struct x509_certificate **chain, 106 const u8 *buf, size_t len) 107{ 108 const u8 *pos, *end; 109 unsigned char *der; 110 size_t der_len; 111 112 pos = search_tag(pem_cert_begin, buf, len); 113 if (!pos) { 114 wpa_printf(MSG_DEBUG, "TLSv1: No PEM certificate tag found - " 115 "assume DER format"); 116 return tlsv1_add_cert_der(chain, buf, len); 117 } 118 119 wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format certificate into " 120 "DER format"); 121 122 while (pos) { 123 pos += os_strlen(pem_cert_begin); 124 end = search_tag(pem_cert_end, pos, buf + len - pos); 125 if (end == NULL) { 126 wpa_printf(MSG_INFO, "TLSv1: Could not find PEM " 127 "certificate end tag (%s)", pem_cert_end); 128 return -1; 129 } 130 131 der = base64_decode(pos, end - pos, &der_len); 132 if (der == NULL) { 133 wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM " 134 "certificate"); 135 return -1; 136 } 137 138 if (tlsv1_add_cert_der(chain, der, der_len) < 0) { 139 wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM " 140 "certificate after DER conversion"); 141 os_free(der); 142 return -1; 143 } 144 145 os_free(der); 146 147 end += os_strlen(pem_cert_end); 148 pos = search_tag(pem_cert_begin, end, buf + len - end); 149 } 150 151 return 0; 152} 153 154 155static int tlsv1_set_cert_chain(struct x509_certificate **chain, 156 const char *cert, const u8 *cert_blob, 157 size_t cert_blob_len) 158{ 159 if (cert_blob) 160 return tlsv1_add_cert(chain, cert_blob, cert_blob_len); 161 162 if (cert) { 163 u8 *buf; 164 size_t len; 165 int ret; 166 167 buf = (u8 *) os_readfile(cert, &len); 168 if (buf == NULL) { 169 wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", 170 cert); 171 return -1; 172 } 173 174 ret = tlsv1_add_cert(chain, buf, len); 175 os_free(buf); 176 return ret; 177 } 178 179 return 0; 180} 181 182 183/** 184 * tlsv1_set_ca_cert - Set trusted CA certificate(s) 185 * @cred: TLSv1 credentials from tlsv1_cred_alloc() 186 * @cert: File or reference name for X.509 certificate in PEM or DER format 187 * @cert_blob: cert as inlined data or %NULL if not used 188 * @cert_blob_len: ca_cert_blob length 189 * @path: Path to CA certificates (not yet supported) 190 * Returns: 0 on success, -1 on failure 191 */ 192int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert, 193 const u8 *cert_blob, size_t cert_blob_len, 194 const char *path) 195{ 196 if (cert && os_strncmp(cert, "hash://", 7) == 0) { 197 const char *pos = cert + 7; 198 if (os_strncmp(pos, "server/sha256/", 14) != 0) { 199 wpa_printf(MSG_DEBUG, 200 "TLSv1: Unsupported ca_cert hash value '%s'", 201 cert); 202 return -1; 203 } 204 pos += 14; 205 if (os_strlen(pos) != 32 * 2) { 206 wpa_printf(MSG_DEBUG, 207 "TLSv1: Unexpected SHA256 hash length in ca_cert '%s'", 208 cert); 209 return -1; 210 } 211 if (hexstr2bin(pos, cred->srv_cert_hash, 32) < 0) { 212 wpa_printf(MSG_DEBUG, 213 "TLSv1: Invalid SHA256 hash value in ca_cert '%s'", 214 cert); 215 return -1; 216 } 217 cred->server_cert_only = 1; 218 cred->ca_cert_verify = 0; 219 wpa_printf(MSG_DEBUG, 220 "TLSv1: Checking only server certificate match"); 221 return 0; 222 } 223 224 if (cert && os_strncmp(cert, "probe://", 8) == 0) { 225 cred->cert_probe = 1; 226 cred->ca_cert_verify = 0; 227 wpa_printf(MSG_DEBUG, "TLSv1: Only probe server certificate"); 228 return 0; 229 } 230 231 cred->ca_cert_verify = cert || cert_blob || path; 232 233 if (tlsv1_set_cert_chain(&cred->trusted_certs, cert, 234 cert_blob, cert_blob_len) < 0) 235 return -1; 236 237 if (path) { 238 /* TODO: add support for reading number of certificate files */ 239 wpa_printf(MSG_INFO, "TLSv1: Use of CA certificate directory " 240 "not yet supported"); 241 return -1; 242 } 243 244 return 0; 245} 246 247 248/** 249 * tlsv1_set_cert - Set certificate 250 * @cred: TLSv1 credentials from tlsv1_cred_alloc() 251 * @cert: File or reference name for X.509 certificate in PEM or DER format 252 * @cert_blob: cert as inlined data or %NULL if not used 253 * @cert_blob_len: cert_blob length 254 * Returns: 0 on success, -1 on failure 255 */ 256int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert, 257 const u8 *cert_blob, size_t cert_blob_len) 258{ 259 return tlsv1_set_cert_chain(&cred->cert, cert, 260 cert_blob, cert_blob_len); 261} 262 263 264static struct crypto_private_key * tlsv1_set_key_pem(const u8 *key, size_t len) 265{ 266 const u8 *pos, *end; 267 unsigned char *der; 268 size_t der_len; 269 struct crypto_private_key *pkey; 270 271 pos = search_tag(pem_key_begin, key, len); 272 if (!pos) { 273 pos = search_tag(pem_key2_begin, key, len); 274 if (!pos) 275 return NULL; 276 pos += os_strlen(pem_key2_begin); 277 end = search_tag(pem_key2_end, pos, key + len - pos); 278 if (!end) 279 return NULL; 280 } else { 281 const u8 *pos2; 282 pos += os_strlen(pem_key_begin); 283 end = search_tag(pem_key_end, pos, key + len - pos); 284 if (!end) 285 return NULL; 286 pos2 = search_tag("Proc-Type: 4,ENCRYPTED", pos, end - pos); 287 if (pos2) { 288 wpa_printf(MSG_DEBUG, "TLSv1: Unsupported private key " 289 "format (Proc-Type/DEK-Info)"); 290 return NULL; 291 } 292 } 293 294 der = base64_decode(pos, end - pos, &der_len); 295 if (!der) 296 return NULL; 297 pkey = crypto_private_key_import(der, der_len, NULL); 298 os_free(der); 299 return pkey; 300} 301 302 303static struct crypto_private_key * tlsv1_set_key_enc_pem(const u8 *key, 304 size_t len, 305 const char *passwd) 306{ 307 const u8 *pos, *end; 308 unsigned char *der; 309 size_t der_len; 310 struct crypto_private_key *pkey; 311 312 if (passwd == NULL) 313 return NULL; 314 pos = search_tag(pem_key_enc_begin, key, len); 315 if (!pos) 316 return NULL; 317 pos += os_strlen(pem_key_enc_begin); 318 end = search_tag(pem_key_enc_end, pos, key + len - pos); 319 if (!end) 320 return NULL; 321 322 der = base64_decode(pos, end - pos, &der_len); 323 if (!der) 324 return NULL; 325 pkey = crypto_private_key_import(der, der_len, passwd); 326 os_free(der); 327 return pkey; 328} 329 330 331#ifdef PKCS12_FUNCS 332 333static int oid_is_rsadsi(struct asn1_oid *oid) 334{ 335 return oid->len >= 4 && 336 oid->oid[0] == 1 /* iso */ && 337 oid->oid[1] == 2 /* member-body */ && 338 oid->oid[2] == 840 /* us */ && 339 oid->oid[3] == 113549 /* rsadsi */; 340} 341 342 343static int pkcs12_is_bagtype_oid(struct asn1_oid *oid, unsigned long type) 344{ 345 return oid->len == 9 && 346 oid_is_rsadsi(oid) && 347 oid->oid[4] == 1 /* pkcs */ && 348 oid->oid[5] == 12 /* pkcs-12 */ && 349 oid->oid[6] == 10 && 350 oid->oid[7] == 1 /* bagtypes */ && 351 oid->oid[8] == type; 352} 353 354 355static int is_oid_pkcs7(struct asn1_oid *oid) 356{ 357 return oid->len == 7 && 358 oid->oid[0] == 1 /* iso */ && 359 oid->oid[1] == 2 /* member-body */ && 360 oid->oid[2] == 840 /* us */ && 361 oid->oid[3] == 113549 /* rsadsi */ && 362 oid->oid[4] == 1 /* pkcs */ && 363 oid->oid[5] == 7 /* pkcs-7 */; 364} 365 366 367static int is_oid_pkcs7_data(struct asn1_oid *oid) 368{ 369 return is_oid_pkcs7(oid) && oid->oid[6] == 1 /* data */; 370} 371 372 373static int is_oid_pkcs7_enc_data(struct asn1_oid *oid) 374{ 375 return is_oid_pkcs7(oid) && oid->oid[6] == 6 /* encryptedData */; 376} 377 378 379static int is_oid_pkcs9(struct asn1_oid *oid) 380{ 381 return oid->len >= 6 && 382 oid->oid[0] == 1 /* iso */ && 383 oid->oid[1] == 2 /* member-body */ && 384 oid->oid[2] == 840 /* us */ && 385 oid->oid[3] == 113549 /* rsadsi */ && 386 oid->oid[4] == 1 /* pkcs */ && 387 oid->oid[5] == 9 /* pkcs-9 */; 388} 389 390 391static int is_oid_pkcs9_friendly_name(struct asn1_oid *oid) 392{ 393 return oid->len == 7 && is_oid_pkcs9(oid) && 394 oid->oid[6] == 20; 395} 396 397 398static int is_oid_pkcs9_local_key_id(struct asn1_oid *oid) 399{ 400 return oid->len == 7 && is_oid_pkcs9(oid) && 401 oid->oid[6] == 21; 402} 403 404 405static int is_oid_pkcs9_x509_cert(struct asn1_oid *oid) 406{ 407 return oid->len == 8 && is_oid_pkcs9(oid) && 408 oid->oid[6] == 22 /* certTypes */ && 409 oid->oid[7] == 1 /* x509Certificate */; 410} 411 412 413static int pkcs12_keybag(struct tlsv1_credentials *cred, 414 const u8 *buf, size_t len) 415{ 416 /* TODO */ 417 return 0; 418} 419 420 421static int pkcs12_pkcs8_keybag(struct tlsv1_credentials *cred, 422 const u8 *buf, size_t len, 423 const char *passwd) 424{ 425 struct crypto_private_key *key; 426 427 /* PKCS8ShroudedKeyBag ::= EncryptedPrivateKeyInfo */ 428 key = pkcs8_enc_key_import(buf, len, passwd); 429 if (!key) 430 return -1; 431 432 wpa_printf(MSG_DEBUG, 433 "PKCS #12: Successfully decrypted PKCS8ShroudedKeyBag"); 434 crypto_private_key_free(cred->key); 435 cred->key = key; 436 437 return 0; 438} 439 440 441static int pkcs12_certbag(struct tlsv1_credentials *cred, 442 const u8 *buf, size_t len) 443{ 444 struct asn1_hdr hdr; 445 struct asn1_oid oid; 446 char obuf[80]; 447 const u8 *pos, *end; 448 449 /* 450 * CertBag ::= SEQUENCE { 451 * certId BAG-TYPE.&id ({CertTypes}), 452 * certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) 453 * } 454 */ 455 456 if (asn1_get_next(buf, len, &hdr) < 0 || 457 hdr.class != ASN1_CLASS_UNIVERSAL || 458 hdr.tag != ASN1_TAG_SEQUENCE) { 459 wpa_printf(MSG_DEBUG, 460 "PKCS #12: Expected SEQUENCE (CertBag) - found class %d tag 0x%x", 461 hdr.class, hdr.tag); 462 return -1; 463 } 464 465 pos = hdr.payload; 466 end = hdr.payload + hdr.length; 467 468 if (asn1_get_oid(pos, end - pos, &oid, &pos)) { 469 wpa_printf(MSG_DEBUG, 470 "PKCS #12: Failed to parse OID (certId)"); 471 return -1; 472 } 473 474 asn1_oid_to_str(&oid, obuf, sizeof(obuf)); 475 wpa_printf(MSG_DEBUG, "PKCS #12: certId %s", obuf); 476 477 if (!is_oid_pkcs9_x509_cert(&oid)) { 478 wpa_printf(MSG_DEBUG, 479 "PKCS #12: Ignored unsupported certificate type (certId %s)", 480 obuf); 481 } 482 483 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 484 hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || 485 hdr.tag != 0) { 486 wpa_printf(MSG_DEBUG, 487 "PKCS #12: Expected [0] EXPLICIT (certValue) - found class %d tag 0x%x", 488 hdr.class, hdr.tag); 489 return -1; 490 } 491 492 if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 || 493 hdr.class != ASN1_CLASS_UNIVERSAL || 494 hdr.tag != ASN1_TAG_OCTETSTRING) { 495 wpa_printf(MSG_DEBUG, 496 "PKCS #12: Expected OCTET STRING (x509Certificate) - found class %d tag 0x%x", 497 hdr.class, hdr.tag); 498 return -1; 499 } 500 501 wpa_hexdump(MSG_DEBUG, "PKCS #12: x509Certificate", 502 hdr.payload, hdr.length); 503 if (cred->cert) { 504 struct x509_certificate *cert; 505 506 wpa_printf(MSG_DEBUG, "PKCS #12: Ignore extra certificate"); 507 cert = x509_certificate_parse(hdr.payload, hdr.length); 508 if (!cert) { 509 wpa_printf(MSG_DEBUG, 510 "PKCS #12: Failed to parse x509Certificate"); 511 return 0; 512 } 513 x509_certificate_chain_free(cert); 514 515 return 0; 516 } 517 return tlsv1_set_cert(cred, NULL, hdr.payload, hdr.length); 518} 519 520 521static int pkcs12_parse_attr_friendly_name(const u8 *pos, const u8 *end) 522{ 523 struct asn1_hdr hdr; 524 525 /* 526 * RFC 2985, 5.5.1: 527 * friendlyName ATTRIBUTE ::= { 528 * WITH SYNTAX BMPString (SIZE(1..pkcs-9-ub-friendlyName)) 529 * EQUALITY MATCHING RULE caseIgnoreMatch 530 * SINGLE VALUE TRUE 531 * ID pkcs-9-at-friendlyName 532 * } 533 */ 534 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 535 hdr.class != ASN1_CLASS_UNIVERSAL || 536 hdr.tag != ASN1_TAG_BMPSTRING) { 537 wpa_printf(MSG_DEBUG, 538 "PKCS #12: Expected BMPSTRING (friendlyName) - found class %d tag 0x%x", 539 hdr.class, hdr.tag); 540 return 0; 541 } 542 wpa_hexdump_ascii(MSG_DEBUG, "PKCS #12: friendlyName", 543 hdr.payload, hdr.length); 544 return 0; 545} 546 547 548static int pkcs12_parse_attr_local_key_id(const u8 *pos, const u8 *end) 549{ 550 struct asn1_hdr hdr; 551 552 /* 553 * RFC 2985, 5.5.2: 554 * localKeyId ATTRIBUTE ::= { 555 * WITH SYNTAX OCTET STRING 556 * EQUALITY MATCHING RULE octetStringMatch 557 * SINGLE VALUE TRUE 558 * ID pkcs-9-at-localKeyId 559 * } 560 */ 561 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 562 hdr.class != ASN1_CLASS_UNIVERSAL || 563 hdr.tag != ASN1_TAG_OCTETSTRING) { 564 wpa_printf(MSG_DEBUG, 565 "PKCS #12: Expected OCTET STRING (localKeyID) - found class %d tag 0x%x", 566 hdr.class, hdr.tag); 567 return -1; 568 } 569 wpa_hexdump_key(MSG_DEBUG, "PKCS #12: localKeyID", 570 hdr.payload, hdr.length); 571 return 0; 572} 573 574 575static int pkcs12_parse_attr(const u8 *pos, size_t len) 576{ 577 const u8 *end = pos + len; 578 struct asn1_hdr hdr; 579 struct asn1_oid a_oid; 580 char obuf[80]; 581 582 /* 583 * PKCS12Attribute ::= SEQUENCE { 584 * attrId ATTRIBUTE.&id ({PKCS12AttrSet}), 585 * attrValues SET OF ATTRIBUTE.&Type ({PKCS12AttrSet}{@attrId}) 586 * } 587 */ 588 589 if (asn1_get_oid(pos, end - pos, &a_oid, &pos)) { 590 wpa_printf(MSG_DEBUG, "PKCS #12: Failed to parse OID (attrId)"); 591 return -1; 592 } 593 594 asn1_oid_to_str(&a_oid, obuf, sizeof(obuf)); 595 wpa_printf(MSG_DEBUG, "PKCS #12: attrId %s", obuf); 596 597 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 598 hdr.class != ASN1_CLASS_UNIVERSAL || 599 hdr.tag != ASN1_TAG_SET) { 600 wpa_printf(MSG_DEBUG, 601 "PKCS #12: Expected SET (attrValues) - found class %d tag 0x%x", 602 hdr.class, hdr.tag); 603 return -1; 604 } 605 wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: attrValues", 606 hdr.payload, hdr.length); 607 pos = hdr.payload; 608 end = hdr.payload + hdr.length; 609 610 if (is_oid_pkcs9_friendly_name(&a_oid)) 611 return pkcs12_parse_attr_friendly_name(pos, end); 612 if (is_oid_pkcs9_local_key_id(&a_oid)) 613 return pkcs12_parse_attr_local_key_id(pos, end); 614 615 wpa_printf(MSG_DEBUG, "PKCS #12: Ignore unknown attribute"); 616 return 0; 617} 618 619 620static int pkcs12_safebag(struct tlsv1_credentials *cred, 621 const u8 *buf, size_t len, const char *passwd) 622{ 623 struct asn1_hdr hdr; 624 struct asn1_oid oid; 625 char obuf[80]; 626 const u8 *pos = buf, *end = buf + len; 627 const u8 *value; 628 size_t value_len; 629 630 wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: SafeBag", buf, len); 631 632 /* BAG-TYPE ::= TYPE-IDENTIFIER */ 633 if (asn1_get_oid(pos, end - pos, &oid, &pos)) { 634 wpa_printf(MSG_DEBUG, 635 "PKCS #12: Failed to parse OID (BAG-TYPE)"); 636 return -1; 637 } 638 639 asn1_oid_to_str(&oid, obuf, sizeof(obuf)); 640 wpa_printf(MSG_DEBUG, "PKCS #12: BAG-TYPE %s", obuf); 641 642 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 643 hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || 644 hdr.tag != 0) { 645 wpa_printf(MSG_DEBUG, 646 "PKCS #12: Expected [0] EXPLICIT (bagValue) - found class %d tag 0x%x", 647 hdr.class, hdr.tag); 648 return 0; 649 } 650 value = hdr.payload; 651 value_len = hdr.length; 652 wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: bagValue", value, value_len); 653 pos = hdr.payload + hdr.length; 654 655 if (pos < end) { 656 /* bagAttributes SET OF PKCS12Attribute OPTIONAL */ 657 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 658 hdr.class != ASN1_CLASS_UNIVERSAL || 659 hdr.tag != ASN1_TAG_SET) { 660 wpa_printf(MSG_DEBUG, 661 "PKCS #12: Expected SET (bagAttributes) - found class %d tag 0x%x", 662 hdr.class, hdr.tag); 663 return -1; 664 } 665 wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: bagAttributes", 666 hdr.payload, hdr.length); 667 668 pos = hdr.payload; 669 end = hdr.payload + hdr.length; 670 while (pos < end) { 671 /* PKCS12Attribute ::= SEQUENCE */ 672 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 673 hdr.class != ASN1_CLASS_UNIVERSAL || 674 hdr.tag != ASN1_TAG_SEQUENCE) { 675 wpa_printf(MSG_DEBUG, 676 "PKCS #12: Expected SEQUENCE (PKCS12Attribute) - found class %d tag 0x%x", 677 hdr.class, hdr.tag); 678 return -1; 679 } 680 if (pkcs12_parse_attr(hdr.payload, hdr.length) < 0) 681 return -1; 682 pos = hdr.payload + hdr.length; 683 } 684 } 685 686 if (pkcs12_is_bagtype_oid(&oid, 1)) 687 return pkcs12_keybag(cred, value, value_len); 688 if (pkcs12_is_bagtype_oid(&oid, 2)) 689 return pkcs12_pkcs8_keybag(cred, value, value_len, passwd); 690 if (pkcs12_is_bagtype_oid(&oid, 3)) 691 return pkcs12_certbag(cred, value, value_len); 692 693 wpa_printf(MSG_DEBUG, "PKCS #12: Ignore unsupported BAG-TYPE"); 694 return 0; 695} 696 697 698static int pkcs12_safecontents(struct tlsv1_credentials *cred, 699 const u8 *buf, size_t len, 700 const char *passwd) 701{ 702 struct asn1_hdr hdr; 703 const u8 *pos, *end; 704 705 /* SafeContents ::= SEQUENCE OF SafeBag */ 706 if (asn1_get_next(buf, len, &hdr) < 0 || 707 hdr.class != ASN1_CLASS_UNIVERSAL || 708 hdr.tag != ASN1_TAG_SEQUENCE) { 709 wpa_printf(MSG_DEBUG, 710 "PKCS #12: Expected SEQUENCE (SafeContents) - found class %d tag 0x%x", 711 hdr.class, hdr.tag); 712 return -1; 713 } 714 pos = hdr.payload; 715 end = hdr.payload + hdr.length; 716 717 /* 718 * SafeBag ::= SEQUENCE { 719 * bagId BAG-TYPE.&id ({PKCS12BagSet}) 720 * bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}), 721 * bagAttributes SET OF PKCS12Attribute OPTIONAL 722 * } 723 */ 724 725 while (pos < end) { 726 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 727 hdr.class != ASN1_CLASS_UNIVERSAL || 728 hdr.tag != ASN1_TAG_SEQUENCE) { 729 wpa_printf(MSG_DEBUG, 730 "PKCS #12: Expected SEQUENCE (SafeBag) - found class %d tag 0x%x", 731 hdr.class, hdr.tag); 732 return -1; 733 } 734 if (pkcs12_safebag(cred, hdr.payload, hdr.length, passwd) < 0) 735 return -1; 736 pos = hdr.payload + hdr.length; 737 } 738 739 return 0; 740} 741 742 743static int pkcs12_parse_content_data(struct tlsv1_credentials *cred, 744 const u8 *pos, const u8 *end, 745 const char *passwd) 746{ 747 struct asn1_hdr hdr; 748 749 /* Data ::= OCTET STRING */ 750 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 751 hdr.class != ASN1_CLASS_UNIVERSAL || 752 hdr.tag != ASN1_TAG_OCTETSTRING) { 753 wpa_printf(MSG_DEBUG, 754 "PKCS #12: Expected OCTET STRING (Data) - found class %d tag 0x%x", 755 hdr.class, hdr.tag); 756 return -1; 757 } 758 759 wpa_hexdump(MSG_MSGDUMP, "PKCS #12: Data", hdr.payload, hdr.length); 760 761 return pkcs12_safecontents(cred, hdr.payload, hdr.length, passwd); 762} 763 764 765static int pkcs12_parse_content_enc_data(struct tlsv1_credentials *cred, 766 const u8 *pos, const u8 *end, 767 const char *passwd) 768{ 769 struct asn1_hdr hdr; 770 struct asn1_oid oid; 771 char buf[80]; 772 const u8 *enc_alg; 773 u8 *data; 774 size_t enc_alg_len, data_len; 775 int res = -1; 776 777 /* 778 * EncryptedData ::= SEQUENCE { 779 * version Version, 780 * encryptedContentInfo EncryptedContentInfo } 781 */ 782 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 783 hdr.class != ASN1_CLASS_UNIVERSAL || 784 hdr.tag != ASN1_TAG_SEQUENCE) { 785 wpa_printf(MSG_DEBUG, 786 "PKCS #12: Expected SEQUENCE (EncryptedData) - found class %d tag 0x%x", 787 hdr.class, hdr.tag); 788 return 0; 789 } 790 pos = hdr.payload; 791 792 /* Version ::= INTEGER */ 793 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 794 hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { 795 wpa_printf(MSG_DEBUG, 796 "PKCS #12: No INTEGER tag found for version; class=%d tag=0x%x", 797 hdr.class, hdr.tag); 798 return -1; 799 } 800 if (hdr.length != 1 || hdr.payload[0] != 0) { 801 wpa_printf(MSG_DEBUG, "PKCS #12: Unrecognized PKCS #7 version"); 802 return -1; 803 } 804 pos = hdr.payload + hdr.length; 805 806 wpa_hexdump(MSG_MSGDUMP, "PKCS #12: EncryptedContentInfo", 807 pos, end - pos); 808 809 /* 810 * EncryptedContentInfo ::= SEQUENCE { 811 * contentType ContentType, 812 * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, 813 * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL } 814 */ 815 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 816 hdr.class != ASN1_CLASS_UNIVERSAL || 817 hdr.tag != ASN1_TAG_SEQUENCE) { 818 wpa_printf(MSG_DEBUG, 819 "PKCS #12: Expected SEQUENCE (EncryptedContentInfo) - found class %d tag 0x%x", 820 hdr.class, hdr.tag); 821 return -1; 822 } 823 824 pos = hdr.payload; 825 end = pos + hdr.length; 826 827 /* ContentType ::= OBJECT IDENTIFIER */ 828 if (asn1_get_oid(pos, end - pos, &oid, &pos)) { 829 wpa_printf(MSG_DEBUG, 830 "PKCS #12: Could not find OBJECT IDENTIFIER (contentType)"); 831 return -1; 832 } 833 asn1_oid_to_str(&oid, buf, sizeof(buf)); 834 wpa_printf(MSG_DEBUG, "PKCS #12: EncryptedContentInfo::contentType %s", 835 buf); 836 837 if (!is_oid_pkcs7_data(&oid)) { 838 wpa_printf(MSG_DEBUG, 839 "PKCS #12: Unsupported EncryptedContentInfo::contentType %s", 840 buf); 841 return 0; 842 } 843 844 /* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */ 845 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 846 hdr.class != ASN1_CLASS_UNIVERSAL || 847 hdr.tag != ASN1_TAG_SEQUENCE) { 848 wpa_printf(MSG_DEBUG, "PKCS #12: Expected SEQUENCE (ContentEncryptionAlgorithmIdentifier) - found class %d tag 0x%x", 849 hdr.class, hdr.tag); 850 return -1; 851 } 852 enc_alg = hdr.payload; 853 enc_alg_len = hdr.length; 854 pos = hdr.payload + hdr.length; 855 856 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 857 hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || 858 hdr.tag != 0) { 859 wpa_printf(MSG_DEBUG, 860 "PKCS #12: Expected [0] IMPLICIT (encryptedContent) - found class %d tag 0x%x", 861 hdr.class, hdr.tag); 862 return -1; 863 } 864 865 /* EncryptedContent ::= OCTET STRING */ 866 data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length, 867 passwd, &data_len); 868 if (data) { 869 wpa_hexdump_key(MSG_MSGDUMP, 870 "PKCS #12: Decrypted encryptedContent", 871 data, data_len); 872 res = pkcs12_safecontents(cred, data, data_len, passwd); 873 os_free(data); 874 } 875 876 return res; 877} 878 879 880static int pkcs12_parse_content(struct tlsv1_credentials *cred, 881 const u8 *buf, size_t len, 882 const char *passwd) 883{ 884 const u8 *pos = buf; 885 const u8 *end = buf + len; 886 struct asn1_oid oid; 887 char txt[80]; 888 struct asn1_hdr hdr; 889 890 wpa_hexdump(MSG_MSGDUMP, "PKCS #12: ContentInfo", buf, len); 891 892 if (asn1_get_oid(pos, end - pos, &oid, &pos)) { 893 wpa_printf(MSG_DEBUG, 894 "PKCS #12: Could not find OBJECT IDENTIFIER (contentType)"); 895 return 0; 896 } 897 898 asn1_oid_to_str(&oid, txt, sizeof(txt)); 899 wpa_printf(MSG_DEBUG, "PKCS #12: contentType %s", txt); 900 901 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 902 hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || 903 hdr.tag != 0) { 904 wpa_printf(MSG_DEBUG, 905 "PKCS #12: Expected [0] EXPLICIT (content) - found class %d tag 0x%x", 906 hdr.class, hdr.tag); 907 return 0; 908 } 909 pos = hdr.payload; 910 911 if (is_oid_pkcs7_data(&oid)) 912 return pkcs12_parse_content_data(cred, pos, end, passwd); 913 if (is_oid_pkcs7_enc_data(&oid)) 914 return pkcs12_parse_content_enc_data(cred, pos, end, passwd); 915 916 wpa_printf(MSG_DEBUG, "PKCS #12: Ignored unsupported contentType %s", 917 txt); 918 919 return 0; 920} 921 922 923static int pkcs12_parse(struct tlsv1_credentials *cred, 924 const u8 *key, size_t len, const char *passwd) 925{ 926 struct asn1_hdr hdr; 927 const u8 *pos, *end; 928 struct asn1_oid oid; 929 char buf[80]; 930 931 /* 932 * PFX ::= SEQUENCE { 933 * version INTEGER {v3(3)}(v3,...), 934 * authSafe ContentInfo, 935 * macData MacData OPTIONAL 936 * } 937 */ 938 939 if (asn1_get_next(key, len, &hdr) < 0 || 940 hdr.class != ASN1_CLASS_UNIVERSAL || 941 hdr.tag != ASN1_TAG_SEQUENCE) { 942 wpa_printf(MSG_DEBUG, 943 "PKCS #12: Expected SEQUENCE (PFX) - found class %d tag 0x%x; assume PKCS #12 not used", 944 hdr.class, hdr.tag); 945 return -1; 946 } 947 948 pos = hdr.payload; 949 end = pos + hdr.length; 950 951 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 952 hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { 953 wpa_printf(MSG_DEBUG, 954 "PKCS #12: No INTEGER tag found for version; class=%d tag=0x%x", 955 hdr.class, hdr.tag); 956 return -1; 957 } 958 if (hdr.length != 1 || hdr.payload[0] != 3) { 959 wpa_printf(MSG_DEBUG, "PKCS #12: Unrecognized version"); 960 return -1; 961 } 962 pos = hdr.payload + hdr.length; 963 964 /* 965 * ContentInfo ::= SEQUENCE { 966 * contentType ContentType, 967 * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } 968 */ 969 970 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 971 hdr.class != ASN1_CLASS_UNIVERSAL || 972 hdr.tag != ASN1_TAG_SEQUENCE) { 973 wpa_printf(MSG_DEBUG, 974 "PKCS #12: Expected SEQUENCE (authSafe) - found class %d tag 0x%x; assume PKCS #12 not used", 975 hdr.class, hdr.tag); 976 return -1; 977 } 978 979 pos = hdr.payload; 980 end = pos + hdr.length; 981 982 /* ContentType ::= OBJECT IDENTIFIER */ 983 if (asn1_get_oid(pos, end - pos, &oid, &pos)) { 984 wpa_printf(MSG_DEBUG, 985 "PKCS #12: Could not find OBJECT IDENTIFIER (contentType); assume PKCS #12 not used"); 986 return -1; 987 } 988 asn1_oid_to_str(&oid, buf, sizeof(buf)); 989 wpa_printf(MSG_DEBUG, "PKCS #12: contentType %s", buf); 990 if (!is_oid_pkcs7_data(&oid)) { 991 wpa_printf(MSG_DEBUG, "PKCS #12: Unsupported contentType %s", 992 buf); 993 return -1; 994 } 995 996 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 997 hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || 998 hdr.tag != 0) { 999 wpa_printf(MSG_DEBUG, 1000 "PKCS #12: Expected [0] EXPLICIT (content) - found class %d tag 0x%x; assume PKCS #12 not used", 1001 hdr.class, hdr.tag); 1002 return -1; 1003 } 1004 1005 pos = hdr.payload; 1006 1007 /* Data ::= OCTET STRING */ 1008 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1009 hdr.class != ASN1_CLASS_UNIVERSAL || 1010 hdr.tag != ASN1_TAG_OCTETSTRING) { 1011 wpa_printf(MSG_DEBUG, 1012 "PKCS #12: Expected OCTET STRING (Data) - found class %d tag 0x%x; assume PKCS #12 not used", 1013 hdr.class, hdr.tag); 1014 return -1; 1015 } 1016 1017 /* 1018 * AuthenticatedSafe ::= SEQUENCE OF ContentInfo 1019 * -- Data if unencrypted 1020 * -- EncryptedData if password-encrypted 1021 * -- EnvelopedData if public key-encrypted 1022 */ 1023 wpa_hexdump(MSG_MSGDUMP, "PKCS #12: Data content", 1024 hdr.payload, hdr.length); 1025 1026 if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 || 1027 hdr.class != ASN1_CLASS_UNIVERSAL || 1028 hdr.tag != ASN1_TAG_SEQUENCE) { 1029 wpa_printf(MSG_DEBUG, 1030 "PKCS #12: Expected SEQUENCE within Data content - found class %d tag 0x%x; assume PKCS #12 not used", 1031 hdr.class, hdr.tag); 1032 return -1; 1033 } 1034 1035 pos = hdr.payload; 1036 end = pos + hdr.length; 1037 1038 while (end > pos) { 1039 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1040 hdr.class != ASN1_CLASS_UNIVERSAL || 1041 hdr.tag != ASN1_TAG_SEQUENCE) { 1042 wpa_printf(MSG_DEBUG, 1043 "PKCS #12: Expected SEQUENCE (ContentInfo) - found class %d tag 0x%x; assume PKCS #12 not used", 1044 hdr.class, hdr.tag); 1045 return -1; 1046 } 1047 if (pkcs12_parse_content(cred, hdr.payload, hdr.length, 1048 passwd) < 0) 1049 return -1; 1050 1051 pos = hdr.payload + hdr.length; 1052 } 1053 1054 return 0; 1055} 1056 1057#endif /* PKCS12_FUNCS */ 1058 1059 1060static int tlsv1_set_key(struct tlsv1_credentials *cred, 1061 const u8 *key, size_t len, const char *passwd) 1062{ 1063 cred->key = crypto_private_key_import(key, len, passwd); 1064 if (cred->key == NULL) 1065 cred->key = tlsv1_set_key_pem(key, len); 1066 if (cred->key == NULL) 1067 cred->key = tlsv1_set_key_enc_pem(key, len, passwd); 1068#ifdef PKCS12_FUNCS 1069 if (!cred->key) 1070 pkcs12_parse(cred, key, len, passwd); 1071#endif /* PKCS12_FUNCS */ 1072 if (cred->key == NULL) { 1073 wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key"); 1074 return -1; 1075 } 1076 return 0; 1077} 1078 1079 1080/** 1081 * tlsv1_set_private_key - Set private key 1082 * @cred: TLSv1 credentials from tlsv1_cred_alloc() 1083 * @private_key: File or reference name for the key in PEM or DER format 1084 * @private_key_passwd: Passphrase for decrypted private key, %NULL if no 1085 * passphrase is used. 1086 * @private_key_blob: private_key as inlined data or %NULL if not used 1087 * @private_key_blob_len: private_key_blob length 1088 * Returns: 0 on success, -1 on failure 1089 */ 1090int tlsv1_set_private_key(struct tlsv1_credentials *cred, 1091 const char *private_key, 1092 const char *private_key_passwd, 1093 const u8 *private_key_blob, 1094 size_t private_key_blob_len) 1095{ 1096 crypto_private_key_free(cred->key); 1097 cred->key = NULL; 1098 1099 if (private_key_blob) 1100 return tlsv1_set_key(cred, private_key_blob, 1101 private_key_blob_len, 1102 private_key_passwd); 1103 1104 if (private_key) { 1105 u8 *buf; 1106 size_t len; 1107 int ret; 1108 1109 buf = (u8 *) os_readfile(private_key, &len); 1110 if (buf == NULL) { 1111 wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", 1112 private_key); 1113 return -1; 1114 } 1115 1116 ret = tlsv1_set_key(cred, buf, len, private_key_passwd); 1117 os_free(buf); 1118 return ret; 1119 } 1120 1121 return 0; 1122} 1123 1124 1125static int tlsv1_set_dhparams_der(struct tlsv1_credentials *cred, 1126 const u8 *dh, size_t len) 1127{ 1128 struct asn1_hdr hdr; 1129 const u8 *pos, *end; 1130 1131 pos = dh; 1132 end = dh + len; 1133 1134 /* 1135 * DHParameter ::= SEQUENCE { 1136 * prime INTEGER, -- p 1137 * base INTEGER, -- g 1138 * privateValueLength INTEGER OPTIONAL } 1139 */ 1140 1141 /* DHParamer ::= SEQUENCE */ 1142 if (asn1_get_next(pos, len, &hdr) < 0 || 1143 hdr.class != ASN1_CLASS_UNIVERSAL || 1144 hdr.tag != ASN1_TAG_SEQUENCE) { 1145 wpa_printf(MSG_DEBUG, "DH: DH parameters did not start with a " 1146 "valid SEQUENCE - found class %d tag 0x%x", 1147 hdr.class, hdr.tag); 1148 return -1; 1149 } 1150 pos = hdr.payload; 1151 1152 /* prime INTEGER */ 1153 if (asn1_get_next(pos, end - pos, &hdr) < 0) 1154 return -1; 1155 1156 if (hdr.class != ASN1_CLASS_UNIVERSAL || 1157 hdr.tag != ASN1_TAG_INTEGER) { 1158 wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for p; " 1159 "class=%d tag=0x%x", hdr.class, hdr.tag); 1160 return -1; 1161 } 1162 1163 wpa_hexdump(MSG_MSGDUMP, "DH: prime (p)", hdr.payload, hdr.length); 1164 if (hdr.length == 0) 1165 return -1; 1166 os_free(cred->dh_p); 1167 cred->dh_p = os_malloc(hdr.length); 1168 if (cred->dh_p == NULL) 1169 return -1; 1170 os_memcpy(cred->dh_p, hdr.payload, hdr.length); 1171 cred->dh_p_len = hdr.length; 1172 pos = hdr.payload + hdr.length; 1173 1174 /* base INTEGER */ 1175 if (asn1_get_next(pos, end - pos, &hdr) < 0) 1176 return -1; 1177 1178 if (hdr.class != ASN1_CLASS_UNIVERSAL || 1179 hdr.tag != ASN1_TAG_INTEGER) { 1180 wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for g; " 1181 "class=%d tag=0x%x", hdr.class, hdr.tag); 1182 return -1; 1183 } 1184 1185 wpa_hexdump(MSG_MSGDUMP, "DH: base (g)", hdr.payload, hdr.length); 1186 if (hdr.length == 0) 1187 return -1; 1188 os_free(cred->dh_g); 1189 cred->dh_g = os_malloc(hdr.length); 1190 if (cred->dh_g == NULL) 1191 return -1; 1192 os_memcpy(cred->dh_g, hdr.payload, hdr.length); 1193 cred->dh_g_len = hdr.length; 1194 1195 return 0; 1196} 1197 1198 1199static const char *pem_dhparams_begin = "-----BEGIN DH PARAMETERS-----"; 1200static const char *pem_dhparams_end = "-----END DH PARAMETERS-----"; 1201 1202 1203static int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred, 1204 const u8 *buf, size_t len) 1205{ 1206 const u8 *pos, *end; 1207 unsigned char *der; 1208 size_t der_len; 1209 1210 pos = search_tag(pem_dhparams_begin, buf, len); 1211 if (!pos) { 1212 wpa_printf(MSG_DEBUG, "TLSv1: No PEM dhparams tag found - " 1213 "assume DER format"); 1214 return tlsv1_set_dhparams_der(cred, buf, len); 1215 } 1216 1217 wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format dhparams into DER " 1218 "format"); 1219 1220 pos += os_strlen(pem_dhparams_begin); 1221 end = search_tag(pem_dhparams_end, pos, buf + len - pos); 1222 if (end == NULL) { 1223 wpa_printf(MSG_INFO, "TLSv1: Could not find PEM dhparams end " 1224 "tag (%s)", pem_dhparams_end); 1225 return -1; 1226 } 1227 1228 der = base64_decode(pos, end - pos, &der_len); 1229 if (der == NULL) { 1230 wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams"); 1231 return -1; 1232 } 1233 1234 if (tlsv1_set_dhparams_der(cred, der, der_len) < 0) { 1235 wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM dhparams " 1236 "DER conversion"); 1237 os_free(der); 1238 return -1; 1239 } 1240 1241 os_free(der); 1242 1243 return 0; 1244} 1245 1246 1247/** 1248 * tlsv1_set_dhparams - Set Diffie-Hellman parameters 1249 * @cred: TLSv1 credentials from tlsv1_cred_alloc() 1250 * @dh_file: File or reference name for the DH params in PEM or DER format 1251 * @dh_blob: DH params as inlined data or %NULL if not used 1252 * @dh_blob_len: dh_blob length 1253 * Returns: 0 on success, -1 on failure 1254 */ 1255int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file, 1256 const u8 *dh_blob, size_t dh_blob_len) 1257{ 1258 if (dh_blob) 1259 return tlsv1_set_dhparams_blob(cred, dh_blob, dh_blob_len); 1260 1261 if (dh_file) { 1262 u8 *buf; 1263 size_t len; 1264 int ret; 1265 1266 buf = (u8 *) os_readfile(dh_file, &len); 1267 if (buf == NULL) { 1268 wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", 1269 dh_file); 1270 return -1; 1271 } 1272 1273 ret = tlsv1_set_dhparams_blob(cred, buf, len); 1274 os_free(buf); 1275 return ret; 1276 } 1277 1278 return 0; 1279} 1280