18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLSv1 credentials 31b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "base64.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#include "crypto/sha1.h" 151b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#include "pkcs5.h" 161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#include "pkcs8.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "x509v3.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_cred.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tlsv1_credentials * tlsv1_cred_alloc(void) 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tlsv1_credentials *cred; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred = os_zalloc(sizeof(*cred)); 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return cred; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tlsv1_cred_free(struct tlsv1_credentials *cred) 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cred == NULL) 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_chain_free(cred->trusted_certs); 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_chain_free(cred->cert); 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_private_key_free(cred->key); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cred->dh_p); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cred->dh_g); 39d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt os_free(cred->ocsp_stapling_response); 40d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt os_free(cred->ocsp_stapling_response_multi); 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cred); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tlsv1_add_cert_der(struct x509_certificate **chain, 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct x509_certificate *cert, *p; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char name[128]; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert = x509_certificate_parse(buf, len); 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert == NULL) { 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: %s - failed to parse certificate", 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__); 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt p = *chain; 591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (p && p->next) 601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt p = p->next; 611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (p && x509_name_compare(&cert->subject, &p->issuer) == 0) { 621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * The new certificate is the issuer of the last certificate in 641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * the chain - add the new certificate to the end. 651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt p->next = cert; 671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Add to the beginning of the chain */ 691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt cert->next = *chain; 701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *chain = cert; 711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_name_string(&cert->subject, name, sizeof(name)); 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Added certificate: %s", name); 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----"; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_cert_end = "-----END CERTIFICATE-----"; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_key_begin = "-----BEGIN RSA PRIVATE KEY-----"; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_key_end = "-----END RSA PRIVATE KEY-----"; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_key2_begin = "-----BEGIN PRIVATE KEY-----"; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_key2_end = "-----END PRIVATE KEY-----"; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_key_enc_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_key_enc_end = "-----END ENCRYPTED PRIVATE KEY-----"; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * search_tag(const char *tag, const u8 *buf, size_t len) 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i, plen; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = os_strlen(tag); 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < plen) 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < len - plen; i++) { 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(buf + i, tag, plen) == 0) 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf + i; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tlsv1_add_cert(struct x509_certificate **chain, 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char *der; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t der_len; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = search_tag(pem_cert_begin, buf, len); 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pos) { 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: No PEM certificate tag found - " 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assume DER format"); 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tlsv1_add_cert_der(chain, buf, len); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format certificate into " 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "DER format"); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos) { 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += os_strlen(pem_cert_begin); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = search_tag(pem_cert_end, pos, buf + len - pos); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end == NULL) { 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Could not find PEM " 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "certificate end tag (%s)", pem_cert_end); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt der = base64_decode(pos, end - pos, &der_len); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (der == NULL) { 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM " 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "certificate"); 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_add_cert_der(chain, der, der_len) < 0) { 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM " 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "certificate after DER conversion"); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(der); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(der); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end += os_strlen(pem_cert_end); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = search_tag(pem_cert_begin, end, buf + len - end); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tlsv1_set_cert_chain(struct x509_certificate **chain, 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *cert, const u8 *cert_blob, 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t cert_blob_len) 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert_blob) 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tlsv1_add_cert(chain, cert_blob, cert_blob_len); 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert) { 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = (u8 *) os_readfile(cert, &len); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert); 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = tlsv1_add_cert(chain, buf, len); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_set_ca_cert - Set trusted CA certificate(s) 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cred: TLSv1 credentials from tlsv1_cred_alloc() 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert: File or reference name for X.509 certificate in PEM or DER format 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert_blob: cert as inlined data or %NULL if not used 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert_blob_len: ca_cert_blob length 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @path: Path to CA certificates (not yet supported) 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert, 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *cert_blob, size_t cert_blob_len, 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *path) 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 198d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (cert && os_strncmp(cert, "hash://", 7) == 0) { 199d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt const char *pos = cert + 7; 200d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (os_strncmp(pos, "server/sha256/", 14) != 0) { 201d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, 202d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "TLSv1: Unsupported ca_cert hash value '%s'", 203d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt cert); 204d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 205d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 206d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt pos += 14; 207d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (os_strlen(pos) != 32 * 2) { 208d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, 209d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "TLSv1: Unexpected SHA256 hash length in ca_cert '%s'", 210d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt cert); 211d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 212d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 213d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (hexstr2bin(pos, cred->srv_cert_hash, 32) < 0) { 214d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, 215d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "TLSv1: Invalid SHA256 hash value in ca_cert '%s'", 216d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt cert); 217d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 218d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 219d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt cred->server_cert_only = 1; 220d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt cred->ca_cert_verify = 0; 221d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, 222d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "TLSv1: Checking only server certificate match"); 223d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return 0; 224d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 225d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 226d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (cert && os_strncmp(cert, "probe://", 8) == 0) { 227d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt cred->cert_probe = 1; 228d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt cred->ca_cert_verify = 0; 229d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Only probe server certificate"); 230d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return 0; 231d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 232d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 233d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt cred->ca_cert_verify = cert || cert_blob || path; 234d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_set_cert_chain(&cred->trusted_certs, cert, 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert_blob, cert_blob_len) < 0) 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (path) { 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add support for reading number of certificate files */ 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Use of CA certificate directory " 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not yet supported"); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_set_cert - Set certificate 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cred: TLSv1 credentials from tlsv1_cred_alloc() 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert: File or reference name for X.509 certificate in PEM or DER format 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert_blob: cert as inlined data or %NULL if not used 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert_blob_len: cert_blob length 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert, 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *cert_blob, size_t cert_blob_len) 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tlsv1_set_cert_chain(&cred->cert, cert, 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert_blob, cert_blob_len); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct crypto_private_key * tlsv1_set_key_pem(const u8 *key, size_t len) 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char *der; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t der_len; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct crypto_private_key *pkey; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = search_tag(pem_key_begin, key, len); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pos) { 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = search_tag(pem_key2_begin, key, len); 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pos) 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += os_strlen(pem_key2_begin); 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = search_tag(pem_key2_end, pos, key + len - pos); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!end) 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos2; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += os_strlen(pem_key_begin); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = search_tag(pem_key_end, pos, key + len - pos); 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!end) 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos2 = search_tag("Proc-Type: 4,ENCRYPTED", pos, end - pos); 2891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos2) { 2901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Unsupported private key " 2911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "format (Proc-Type/DEK-Info)"); 2921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 2931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt der = base64_decode(pos, end - pos, &der_len); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!der) 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pkey = crypto_private_key_import(der, der_len, NULL); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(der); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pkey; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct crypto_private_key * tlsv1_set_key_enc_pem(const u8 *key, 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *passwd) 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char *der; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t der_len; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct crypto_private_key *pkey; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (passwd == NULL) 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = search_tag(pem_key_enc_begin, key, len); 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pos) 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += os_strlen(pem_key_enc_begin); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = search_tag(pem_key_enc_end, pos, key + len - pos); 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!end) 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt der = base64_decode(pos, end - pos, &der_len); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!der) 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pkey = crypto_private_key_import(der, der_len, passwd); 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(der); 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pkey; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#ifdef PKCS12_FUNCS 3341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3351b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int oid_is_rsadsi(struct asn1_oid *oid) 3361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 3371b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return oid->len >= 4 && 3381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[0] == 1 /* iso */ && 3391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[1] == 2 /* member-body */ && 3401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[2] == 840 /* us */ && 3411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[3] == 113549 /* rsadsi */; 3421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 3431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_is_bagtype_oid(struct asn1_oid *oid, unsigned long type) 3461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 3471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return oid->len == 9 && 3481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid_is_rsadsi(oid) && 3491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[4] == 1 /* pkcs */ && 3501b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[5] == 12 /* pkcs-12 */ && 3511b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[6] == 10 && 3521b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[7] == 1 /* bagtypes */ && 3531b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[8] == type; 3541b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 3551b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3561b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3571b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int is_oid_pkcs7(struct asn1_oid *oid) 3581b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 3591b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return oid->len == 7 && 3601b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[0] == 1 /* iso */ && 3611b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[1] == 2 /* member-body */ && 3621b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[2] == 840 /* us */ && 3631b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[3] == 113549 /* rsadsi */ && 3641b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[4] == 1 /* pkcs */ && 3651b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[5] == 7 /* pkcs-7 */; 3661b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 3671b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3681b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3691b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int is_oid_pkcs7_data(struct asn1_oid *oid) 3701b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 3711b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return is_oid_pkcs7(oid) && oid->oid[6] == 1 /* data */; 3721b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 3731b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3741b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3751b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int is_oid_pkcs7_enc_data(struct asn1_oid *oid) 3761b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 3771b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return is_oid_pkcs7(oid) && oid->oid[6] == 6 /* encryptedData */; 3781b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 3791b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3801b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3811b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int is_oid_pkcs9(struct asn1_oid *oid) 3821b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 3831b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return oid->len >= 6 && 3841b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[0] == 1 /* iso */ && 3851b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[1] == 2 /* member-body */ && 3861b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[2] == 840 /* us */ && 3871b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[3] == 113549 /* rsadsi */ && 3881b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[4] == 1 /* pkcs */ && 3891b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[5] == 9 /* pkcs-9 */; 3901b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 3911b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3921b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3931b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int is_oid_pkcs9_friendly_name(struct asn1_oid *oid) 3941b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 3951b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return oid->len == 7 && is_oid_pkcs9(oid) && 3961b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[6] == 20; 3971b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 3981b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3991b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4001b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int is_oid_pkcs9_local_key_id(struct asn1_oid *oid) 4011b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 4021b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return oid->len == 7 && is_oid_pkcs9(oid) && 4031b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[6] == 21; 4041b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 4051b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4061b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4071b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int is_oid_pkcs9_x509_cert(struct asn1_oid *oid) 4081b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 4091b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return oid->len == 8 && is_oid_pkcs9(oid) && 4101b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[6] == 22 /* certTypes */ && 4111b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[7] == 1 /* x509Certificate */; 4121b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 4131b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4151b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_keybag(struct tlsv1_credentials *cred, 4161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *buf, size_t len) 4171b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 4181b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* TODO */ 4191b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 4201b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 4211b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4231b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_pkcs8_keybag(struct tlsv1_credentials *cred, 4241b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *buf, size_t len, 4251b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const char *passwd) 4261b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 4271b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct crypto_private_key *key; 4281b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4291b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* PKCS8ShroudedKeyBag ::= EncryptedPrivateKeyInfo */ 4301b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt key = pkcs8_enc_key_import(buf, len, passwd); 4311b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (!key) 4321b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 4331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 4351b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Successfully decrypted PKCS8ShroudedKeyBag"); 4361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt crypto_private_key_free(cred->key); 4371b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt cred->key = key; 4381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 4401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 4411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_certbag(struct tlsv1_credentials *cred, 4441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *buf, size_t len) 4451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 4461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_hdr hdr; 4471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_oid oid; 4481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt char obuf[80]; 4491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *pos, *end; 4501b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4511b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* 4521b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * CertBag ::= SEQUENCE { 4531b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * certId BAG-TYPE.&id ({CertTypes}), 4541b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) 4551b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * } 4561b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt */ 4571b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4581b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(buf, len, &hdr) < 0 || 4591b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 4601b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 4611b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 4621b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected SEQUENCE (CertBag) - found class %d tag 0x%x", 4631b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 4641b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 4651b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 4661b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4671b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 4681b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt end = hdr.payload + hdr.length; 4691b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4701b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_oid(pos, end - pos, &oid, &pos)) { 4711b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 4721b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Failed to parse OID (certId)"); 4731b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 4741b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 4751b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4761b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt asn1_oid_to_str(&oid, obuf, sizeof(obuf)); 4771b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: certId %s", obuf); 4781b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4791b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (!is_oid_pkcs9_x509_cert(&oid)) { 4801b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 4811b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Ignored unsupported certificate type (certId %s)", 4821b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt obuf); 4831b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 4841b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4851b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 4861b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || 4871b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != 0) { 4881b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 4891b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected [0] EXPLICIT (certValue) - found class %d tag 0x%x", 4901b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 4911b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 4921b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 4931b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4941b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 || 4951b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 4961b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_OCTETSTRING) { 4971b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 4981b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected OCTET STRING (x509Certificate) - found class %d tag 0x%x", 4991b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 5001b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 5011b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 5021b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5031b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump(MSG_DEBUG, "PKCS #12: x509Certificate", 5041b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.payload, hdr.length); 5051b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (cred->cert) { 5061b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct x509_certificate *cert; 5071b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5081b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: Ignore extra certificate"); 5091b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt cert = x509_certificate_parse(hdr.payload, hdr.length); 5101b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (!cert) { 5111b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 5121b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Failed to parse x509Certificate"); 5131b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 5141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 5151b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt x509_certificate_chain_free(cert); 5161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5171b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 5181b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 5191b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return tlsv1_set_cert(cred, NULL, hdr.payload, hdr.length); 5201b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 5211b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5231b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_parse_attr_friendly_name(const u8 *pos, const u8 *end) 5241b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 5251b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_hdr hdr; 5261b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5271b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* 5281b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * RFC 2985, 5.5.1: 5291b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * friendlyName ATTRIBUTE ::= { 5301b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * WITH SYNTAX BMPString (SIZE(1..pkcs-9-ub-friendlyName)) 5311b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * EQUALITY MATCHING RULE caseIgnoreMatch 5321b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * SINGLE VALUE TRUE 5331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * ID pkcs-9-at-friendlyName 5341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * } 5351b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt */ 5361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 5371b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 5381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_BMPSTRING) { 5391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 5401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected BMPSTRING (friendlyName) - found class %d tag 0x%x", 5411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 5421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 5431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 5441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "PKCS #12: friendlyName", 5451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.payload, hdr.length); 5461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 5471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 5481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5501b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_parse_attr_local_key_id(const u8 *pos, const u8 *end) 5511b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 5521b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_hdr hdr; 5531b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5541b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* 5551b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * RFC 2985, 5.5.2: 5561b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * localKeyId ATTRIBUTE ::= { 5571b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * WITH SYNTAX OCTET STRING 5581b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * EQUALITY MATCHING RULE octetStringMatch 5591b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * SINGLE VALUE TRUE 5601b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * ID pkcs-9-at-localKeyId 5611b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * } 5621b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt */ 5631b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 5641b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 5651b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_OCTETSTRING) { 5661b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 5671b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected OCTET STRING (localKeyID) - found class %d tag 0x%x", 5681b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 5691b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 5701b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 5711b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "PKCS #12: localKeyID", 5721b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.payload, hdr.length); 5731b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 5741b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 5751b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5761b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5771b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_parse_attr(const u8 *pos, size_t len) 5781b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 5791b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *end = pos + len; 5801b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_hdr hdr; 5811b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_oid a_oid; 5821b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt char obuf[80]; 5831b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5841b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* 5851b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * PKCS12Attribute ::= SEQUENCE { 5861b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * attrId ATTRIBUTE.&id ({PKCS12AttrSet}), 5871b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * attrValues SET OF ATTRIBUTE.&Type ({PKCS12AttrSet}{@attrId}) 5881b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * } 5891b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt */ 5901b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5911b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_oid(pos, end - pos, &a_oid, &pos)) { 5921b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: Failed to parse OID (attrId)"); 5931b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 5941b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 5951b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5961b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt asn1_oid_to_str(&a_oid, obuf, sizeof(obuf)); 5971b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: attrId %s", obuf); 5981b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5991b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 6001b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 6011b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SET) { 6021b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 6031b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected SET (attrValues) - found class %d tag 0x%x", 6041b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 6051b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 6061b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 6071b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: attrValues", 6081b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.payload, hdr.length); 6091b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 6101b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt end = hdr.payload + hdr.length; 6111b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 6121b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (is_oid_pkcs9_friendly_name(&a_oid)) 6131b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return pkcs12_parse_attr_friendly_name(pos, end); 6141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (is_oid_pkcs9_local_key_id(&a_oid)) 6151b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return pkcs12_parse_attr_local_key_id(pos, end); 6161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 6171b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: Ignore unknown attribute"); 6181b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 6191b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 6201b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 6211b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 6221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_safebag(struct tlsv1_credentials *cred, 6231b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *buf, size_t len, const char *passwd) 6241b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 6251b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_hdr hdr; 6261b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_oid oid; 6271b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt char obuf[80]; 6281b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *pos = buf, *end = buf + len; 6291b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *value; 6301b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt size_t value_len; 6311b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 6321b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: SafeBag", buf, len); 6331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 6341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* BAG-TYPE ::= TYPE-IDENTIFIER */ 6351b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_oid(pos, end - pos, &oid, &pos)) { 6361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 6371b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Failed to parse OID (BAG-TYPE)"); 6381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 6391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 6401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 6411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt asn1_oid_to_str(&oid, obuf, sizeof(obuf)); 6421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: BAG-TYPE %s", obuf); 6431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 6441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 6451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || 6461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != 0) { 6471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 6481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected [0] EXPLICIT (bagValue) - found class %d tag 0x%x", 6491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 6501b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 6511b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 6521b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt value = hdr.payload; 6531b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt value_len = hdr.length; 6541b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: bagValue", value, value_len); 6551b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload + hdr.length; 6561b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 6571b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (pos < end) { 6581b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* bagAttributes SET OF PKCS12Attribute OPTIONAL */ 6591b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 6601b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 6611b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SET) { 6621b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 6631b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected SET (bagAttributes) - found class %d tag 0x%x", 6641b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 6651b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 6661b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 6671b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: bagAttributes", 6681b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.payload, hdr.length); 6691b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 6701b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 6711b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt end = hdr.payload + hdr.length; 6721b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt while (pos < end) { 6731b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* PKCS12Attribute ::= SEQUENCE */ 6741b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 6751b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 6761b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 6771b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 6781b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected SEQUENCE (PKCS12Attribute) - found class %d tag 0x%x", 6791b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 6801b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 6811b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 6821b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (pkcs12_parse_attr(hdr.payload, hdr.length) < 0) 6831b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 6841b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload + hdr.length; 6851b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 6861b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 6871b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 6881b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (pkcs12_is_bagtype_oid(&oid, 1)) 6891b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return pkcs12_keybag(cred, value, value_len); 6901b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (pkcs12_is_bagtype_oid(&oid, 2)) 6911b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return pkcs12_pkcs8_keybag(cred, value, value_len, passwd); 6921b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (pkcs12_is_bagtype_oid(&oid, 3)) 6931b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return pkcs12_certbag(cred, value, value_len); 6941b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 6951b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: Ignore unsupported BAG-TYPE"); 6961b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 6971b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 6981b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 6991b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 7001b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_safecontents(struct tlsv1_credentials *cred, 7011b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *buf, size_t len, 7021b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const char *passwd) 7031b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 7041b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_hdr hdr; 7051b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *pos, *end; 7061b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 7071b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* SafeContents ::= SEQUENCE OF SafeBag */ 7081b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(buf, len, &hdr) < 0 || 7091b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 7101b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 7111b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 7121b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected SEQUENCE (SafeContents) - found class %d tag 0x%x", 7131b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 7141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 7151b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 7161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 7171b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt end = hdr.payload + hdr.length; 7181b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 7191b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* 7201b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * SafeBag ::= SEQUENCE { 7211b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * bagId BAG-TYPE.&id ({PKCS12BagSet}) 7221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}), 7231b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * bagAttributes SET OF PKCS12Attribute OPTIONAL 7241b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * } 7251b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt */ 7261b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 7271b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt while (pos < end) { 7281b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 7291b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 7301b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 7311b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 7321b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected SEQUENCE (SafeBag) - found class %d tag 0x%x", 7331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 7341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 7351b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 7361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (pkcs12_safebag(cred, hdr.payload, hdr.length, passwd) < 0) 7371b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 7381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload + hdr.length; 7391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 7401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 7411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 7421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 7431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 7441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 7451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_parse_content_data(struct tlsv1_credentials *cred, 7461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *pos, const u8 *end, 7471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const char *passwd) 7481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 7491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_hdr hdr; 7501b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 7511b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* Data ::= OCTET STRING */ 7521b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 7531b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 7541b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_OCTETSTRING) { 7551b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 7561b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected OCTET STRING (Data) - found class %d tag 0x%x", 7571b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 7581b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 7591b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 7601b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 7611b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "PKCS #12: Data", hdr.payload, hdr.length); 7621b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 7631b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return pkcs12_safecontents(cred, hdr.payload, hdr.length, passwd); 7641b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 7651b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 7661b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 7671b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_parse_content_enc_data(struct tlsv1_credentials *cred, 7681b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *pos, const u8 *end, 7691b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const char *passwd) 7701b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 7711b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_hdr hdr; 7721b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_oid oid; 7731b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt char buf[80]; 7741b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *enc_alg; 7751b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt u8 *data; 7761b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt size_t enc_alg_len, data_len; 7771b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt int res = -1; 7781b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 7791b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* 7801b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * EncryptedData ::= SEQUENCE { 7811b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * version Version, 7821b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * encryptedContentInfo EncryptedContentInfo } 7831b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt */ 7841b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 7851b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 7861b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 7871b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 7881b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected SEQUENCE (EncryptedData) - found class %d tag 0x%x", 7891b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 7901b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 7911b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 7921b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 7931b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 7941b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* Version ::= INTEGER */ 7951b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 7961b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { 7971b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 7981b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: No INTEGER tag found for version; class=%d tag=0x%x", 7991b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 8001b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 8011b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 8021b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (hdr.length != 1 || hdr.payload[0] != 0) { 8031b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: Unrecognized PKCS #7 version"); 8041b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 8051b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 8061b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload + hdr.length; 8071b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 8081b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "PKCS #12: EncryptedContentInfo", 8091b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos, end - pos); 8101b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 8111b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* 8121b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * EncryptedContentInfo ::= SEQUENCE { 8131b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * contentType ContentType, 8141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, 8151b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL } 8161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt */ 8171b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 8181b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 8191b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 8201b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 8211b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected SEQUENCE (EncryptedContentInfo) - found class %d tag 0x%x", 8221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 8231b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 8241b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 8251b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 8261b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 8271b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt end = pos + hdr.length; 8281b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 8291b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* ContentType ::= OBJECT IDENTIFIER */ 8301b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_oid(pos, end - pos, &oid, &pos)) { 8311b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 8321b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Could not find OBJECT IDENTIFIER (contentType)"); 8331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 8341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 8351b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt asn1_oid_to_str(&oid, buf, sizeof(buf)); 8361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: EncryptedContentInfo::contentType %s", 8371b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt buf); 8381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 8391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (!is_oid_pkcs7_data(&oid)) { 8401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 8411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Unsupported EncryptedContentInfo::contentType %s", 8421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt buf); 8431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 8441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 8451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 8461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */ 8471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 8481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 8491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 8501b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: Expected SEQUENCE (ContentEncryptionAlgorithmIdentifier) - found class %d tag 0x%x", 8511b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 8521b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 8531b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 8541b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt enc_alg = hdr.payload; 8551b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt enc_alg_len = hdr.length; 8561b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload + hdr.length; 8571b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 8581b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 8591b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || 8601b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != 0) { 8611b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 8621b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected [0] IMPLICIT (encryptedContent) - found class %d tag 0x%x", 8631b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 8641b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 8651b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 8661b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 8671b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* EncryptedContent ::= OCTET STRING */ 8681b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length, 8691b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt passwd, &data_len); 8701b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (data) { 8711b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, 8721b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Decrypted encryptedContent", 8731b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt data, data_len); 8741b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt res = pkcs12_safecontents(cred, data, data_len, passwd); 8751b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt os_free(data); 8761b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 8771b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 8781b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return res; 8791b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 8801b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 8811b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 8821b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_parse_content(struct tlsv1_credentials *cred, 8831b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *buf, size_t len, 8841b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const char *passwd) 8851b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 8861b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *pos = buf; 8871b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *end = buf + len; 8881b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_oid oid; 8891b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt char txt[80]; 8901b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_hdr hdr; 8911b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 8921b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "PKCS #12: ContentInfo", buf, len); 8931b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 8941b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_oid(pos, end - pos, &oid, &pos)) { 8951b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 8961b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Could not find OBJECT IDENTIFIER (contentType)"); 8971b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 8981b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 8991b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9001b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt asn1_oid_to_str(&oid, txt, sizeof(txt)); 9011b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: contentType %s", txt); 9021b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9031b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 9041b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || 9051b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != 0) { 9061b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 9071b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected [0] EXPLICIT (content) - found class %d tag 0x%x", 9081b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 9091b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 9101b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 9111b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 9121b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9131b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (is_oid_pkcs7_data(&oid)) 9141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return pkcs12_parse_content_data(cred, pos, end, passwd); 9151b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (is_oid_pkcs7_enc_data(&oid)) 9161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return pkcs12_parse_content_enc_data(cred, pos, end, passwd); 9171b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9181b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: Ignored unsupported contentType %s", 9191b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt txt); 9201b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9211b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 9221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 9231b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9241b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9251b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_parse(struct tlsv1_credentials *cred, 9261b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *key, size_t len, const char *passwd) 9271b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 9281b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_hdr hdr; 9291b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *pos, *end; 9301b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_oid oid; 9311b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt char buf[80]; 9321b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* 9341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * PFX ::= SEQUENCE { 9351b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * version INTEGER {v3(3)}(v3,...), 9361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * authSafe ContentInfo, 9371b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * macData MacData OPTIONAL 9381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * } 9391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt */ 9401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(key, len, &hdr) < 0 || 9421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 9431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 9441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 9451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected SEQUENCE (PFX) - found class %d tag 0x%x; assume PKCS #12 not used", 9461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 9471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 9481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 9491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9501b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 9511b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt end = pos + hdr.length; 9521b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9531b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 9541b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { 9551b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 9561b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: No INTEGER tag found for version; class=%d tag=0x%x", 9571b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 9581b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 9591b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 9601b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (hdr.length != 1 || hdr.payload[0] != 3) { 9611b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: Unrecognized version"); 9621b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 9631b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 9641b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload + hdr.length; 9651b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9661b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* 9671b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * ContentInfo ::= SEQUENCE { 9681b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * contentType ContentType, 9691b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } 9701b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt */ 9711b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9721b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 9731b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 9741b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 9751b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 9761b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected SEQUENCE (authSafe) - found class %d tag 0x%x; assume PKCS #12 not used", 9771b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 9781b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 9791b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 9801b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9811b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 9821b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt end = pos + hdr.length; 9831b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9841b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* ContentType ::= OBJECT IDENTIFIER */ 9851b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_oid(pos, end - pos, &oid, &pos)) { 9861b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 9871b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Could not find OBJECT IDENTIFIER (contentType); assume PKCS #12 not used"); 9881b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 9891b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 9901b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt asn1_oid_to_str(&oid, buf, sizeof(buf)); 9911b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: contentType %s", buf); 9921b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (!is_oid_pkcs7_data(&oid)) { 9931b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #12: Unsupported contentType %s", 9941b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt buf); 9951b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 9961b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 9971b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 9981b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 9991b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || 10001b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != 0) { 10011b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 10021b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected [0] EXPLICIT (content) - found class %d tag 0x%x; assume PKCS #12 not used", 10031b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 10041b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 10051b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 10061b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 10071b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 10081b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 10091b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* Data ::= OCTET STRING */ 10101b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 10111b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 10121b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_OCTETSTRING) { 10131b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 10141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected OCTET STRING (Data) - found class %d tag 0x%x; assume PKCS #12 not used", 10151b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 10161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 10171b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 10181b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 10191b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* 10201b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * AuthenticatedSafe ::= SEQUENCE OF ContentInfo 10211b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * -- Data if unencrypted 10221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * -- EncryptedData if password-encrypted 10231b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * -- EnvelopedData if public key-encrypted 10241b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt */ 10251b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "PKCS #12: Data content", 10261b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.payload, hdr.length); 10271b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 10281b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 || 10291b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 10301b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 10311b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 10321b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected SEQUENCE within Data content - found class %d tag 0x%x; assume PKCS #12 not used", 10331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 10341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 10351b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 10361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 10371b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 10381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt end = pos + hdr.length; 10391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 10401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt while (end > pos) { 10411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 10421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 10431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 10441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 10451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #12: Expected SEQUENCE (ContentInfo) - found class %d tag 0x%x; assume PKCS #12 not used", 10461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 10471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 10481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 10491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (pkcs12_parse_content(cred, hdr.payload, hdr.length, 10501b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt passwd) < 0) 10511b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 10521b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 10531b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload + hdr.length; 10541b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 10551b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 10561b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 10571b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 10581b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 10591b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#endif /* PKCS12_FUNCS */ 10601b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 10611b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tlsv1_set_key(struct tlsv1_credentials *cred, 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key, size_t len, const char *passwd) 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->key = crypto_private_key_import(key, len, passwd); 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cred->key == NULL) 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->key = tlsv1_set_key_pem(key, len); 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cred->key == NULL) 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->key = tlsv1_set_key_enc_pem(key, len, passwd); 10701b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#ifdef PKCS12_FUNCS 10711b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (!cred->key) 10721b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pkcs12_parse(cred, key, len, passwd); 10731b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#endif /* PKCS12_FUNCS */ 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cred->key == NULL) { 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key"); 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_set_private_key - Set private key 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cred: TLSv1 credentials from tlsv1_cred_alloc() 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @private_key: File or reference name for the key in PEM or DER format 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @private_key_passwd: Passphrase for decrypted private key, %NULL if no 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * passphrase is used. 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @private_key_blob: private_key as inlined data or %NULL if not used 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @private_key_blob_len: private_key_blob length 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_set_private_key(struct tlsv1_credentials *cred, 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *private_key, 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *private_key_passwd, 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *private_key_blob, 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t private_key_blob_len) 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_private_key_free(cred->key); 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->key = NULL; 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (private_key_blob) 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tlsv1_set_key(cred, private_key_blob, 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private_key_blob_len, 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private_key_passwd); 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (private_key) { 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = (u8 *) os_readfile(private_key, &len); 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private_key); 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = tlsv1_set_key(cred, buf, len, private_key_passwd); 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tlsv1_set_dhparams_der(struct tlsv1_credentials *cred, 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *dh, size_t len) 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = dh; 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = dh + len; 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * DHParameter ::= SEQUENCE { 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * prime INTEGER, -- p 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * base INTEGER, -- g 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * privateValueLength INTEGER OPTIONAL } 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* DHParamer ::= SEQUENCE */ 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "DH: DH parameters did not start with a " 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "valid SEQUENCE - found class %d tag 0x%x", 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* prime INTEGER */ 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0) 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.class != ASN1_CLASS_UNIVERSAL || 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_INTEGER) { 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for p; " 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "class=%d tag=0x%x", hdr.class, hdr.tag); 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "DH: prime (p)", hdr.payload, hdr.length); 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length == 0) 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cred->dh_p); 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->dh_p = os_malloc(hdr.length); 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cred->dh_p == NULL) 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(cred->dh_p, hdr.payload, hdr.length); 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->dh_p_len = hdr.length; 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload + hdr.length; 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* base INTEGER */ 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0) 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.class != ASN1_CLASS_UNIVERSAL || 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_INTEGER) { 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for g; " 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "class=%d tag=0x%x", hdr.class, hdr.tag); 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "DH: base (g)", hdr.payload, hdr.length); 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length == 0) 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cred->dh_g); 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->dh_g = os_malloc(hdr.length); 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cred->dh_g == NULL) 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(cred->dh_g, hdr.payload, hdr.length); 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->dh_g_len = hdr.length; 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_dhparams_begin = "-----BEGIN DH PARAMETERS-----"; 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_dhparams_end = "-----END DH PARAMETERS-----"; 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred, 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char *der; 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t der_len; 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = search_tag(pem_dhparams_begin, buf, len); 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pos) { 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: No PEM dhparams tag found - " 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assume DER format"); 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tlsv1_set_dhparams_der(cred, buf, len); 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format dhparams into DER " 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "format"); 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += os_strlen(pem_dhparams_begin); 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = search_tag(pem_dhparams_end, pos, buf + len - pos); 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end == NULL) { 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Could not find PEM dhparams end " 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "tag (%s)", pem_dhparams_end); 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt der = base64_decode(pos, end - pos, &der_len); 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (der == NULL) { 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams"); 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_set_dhparams_der(cred, der, der_len) < 0) { 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM dhparams " 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "DER conversion"); 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(der); 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(der); 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_set_dhparams - Set Diffie-Hellman parameters 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cred: TLSv1 credentials from tlsv1_cred_alloc() 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dh_file: File or reference name for the DH params in PEM or DER format 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dh_blob: DH params as inlined data or %NULL if not used 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dh_blob_len: dh_blob length 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file, 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *dh_blob, size_t dh_blob_len) 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dh_blob) 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tlsv1_set_dhparams_blob(cred, dh_blob, dh_blob_len); 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dh_file) { 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = (u8 *) os_readfile(dh_file, &len); 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh_file); 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = tlsv1_set_dhparams_blob(cred, buf, len); 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1282