18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLSv1 credentials 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2006-2009, 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" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "x509v3.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_cred.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tlsv1_credentials * tlsv1_cred_alloc(void) 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tlsv1_credentials *cred; 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred = os_zalloc(sizeof(*cred)); 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return cred; 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tlsv1_cred_free(struct tlsv1_credentials *cred) 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cred == NULL) 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_chain_free(cred->trusted_certs); 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_chain_free(cred->cert); 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_private_key_free(cred->key); 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cred->dh_p); 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cred->dh_g); 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cred); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tlsv1_add_cert_der(struct x509_certificate **chain, 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct x509_certificate *cert, *p; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char name[128]; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert = x509_certificate_parse(buf, len); 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert == NULL) { 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: %s - failed to parse certificate", 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__); 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt p = *chain; 541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (p && p->next) 551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt p = p->next; 561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (p && x509_name_compare(&cert->subject, &p->issuer) == 0) { 571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * The new certificate is the issuer of the last certificate in 591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * the chain - add the new certificate to the end. 601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt p->next = cert; 621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Add to the beginning of the chain */ 641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt cert->next = *chain; 651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *chain = cert; 661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_name_string(&cert->subject, name, sizeof(name)); 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Added certificate: %s", name); 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----"; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_cert_end = "-----END CERTIFICATE-----"; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_key_begin = "-----BEGIN RSA PRIVATE KEY-----"; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_key_end = "-----END RSA PRIVATE KEY-----"; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_key2_begin = "-----BEGIN PRIVATE KEY-----"; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_key2_end = "-----END PRIVATE KEY-----"; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_key_enc_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_key_enc_end = "-----END ENCRYPTED PRIVATE KEY-----"; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * search_tag(const char *tag, const u8 *buf, size_t len) 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i, plen; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = os_strlen(tag); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < plen) 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < len - plen; i++) { 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(buf + i, tag, plen) == 0) 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf + i; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tlsv1_add_cert(struct x509_certificate **chain, 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char *der; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t der_len; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = search_tag(pem_cert_begin, buf, len); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pos) { 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: No PEM certificate tag found - " 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assume DER format"); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tlsv1_add_cert_der(chain, buf, len); 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format certificate into " 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "DER format"); 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos) { 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += os_strlen(pem_cert_begin); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = search_tag(pem_cert_end, pos, buf + len - pos); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end == NULL) { 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Could not find PEM " 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "certificate end tag (%s)", pem_cert_end); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt der = base64_decode(pos, end - pos, &der_len); 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (der == NULL) { 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM " 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "certificate"); 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_add_cert_der(chain, der, der_len) < 0) { 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM " 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "certificate after DER conversion"); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(der); 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(der); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end += os_strlen(pem_cert_end); 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = search_tag(pem_cert_begin, end, buf + len - end); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tlsv1_set_cert_chain(struct x509_certificate **chain, 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *cert, const u8 *cert_blob, 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t cert_blob_len) 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert_blob) 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tlsv1_add_cert(chain, cert_blob, cert_blob_len); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert) { 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = (u8 *) os_readfile(cert, &len); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = tlsv1_add_cert(chain, buf, len); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_set_ca_cert - Set trusted CA certificate(s) 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cred: TLSv1 credentials from tlsv1_cred_alloc() 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert: File or reference name for X.509 certificate in PEM or DER format 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert_blob: cert as inlined data or %NULL if not used 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert_blob_len: ca_cert_blob length 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @path: Path to CA certificates (not yet supported) 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert, 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *cert_blob, size_t cert_blob_len, 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *path) 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_set_cert_chain(&cred->trusted_certs, cert, 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert_blob, cert_blob_len) < 0) 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (path) { 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add support for reading number of certificate files */ 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Use of CA certificate directory " 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not yet supported"); 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_set_cert - Set certificate 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cred: TLSv1 credentials from tlsv1_cred_alloc() 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert: File or reference name for X.509 certificate in PEM or DER format 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert_blob: cert as inlined data or %NULL if not used 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert_blob_len: cert_blob length 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert, 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *cert_blob, size_t cert_blob_len) 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tlsv1_set_cert_chain(&cred->cert, cert, 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert_blob, cert_blob_len); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct crypto_private_key * tlsv1_set_key_pem(const u8 *key, size_t len) 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char *der; 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t der_len; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct crypto_private_key *pkey; 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = search_tag(pem_key_begin, key, len); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pos) { 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = search_tag(pem_key2_begin, key, len); 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pos) 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += os_strlen(pem_key2_begin); 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = search_tag(pem_key2_end, pos, key + len - pos); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!end) 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos2; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += os_strlen(pem_key_begin); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = search_tag(pem_key_end, pos, key + len - pos); 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!end) 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos2 = search_tag("Proc-Type: 4,ENCRYPTED", pos, end - pos); 2471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos2) { 2481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Unsupported private key " 2491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "format (Proc-Type/DEK-Info)"); 2501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 2511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt der = base64_decode(pos, end - pos, &der_len); 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!der) 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pkey = crypto_private_key_import(der, der_len, NULL); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(der); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pkey; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct crypto_private_key * tlsv1_set_key_enc_pem(const u8 *key, 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *passwd) 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char *der; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t der_len; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct crypto_private_key *pkey; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (passwd == NULL) 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = search_tag(pem_key_enc_begin, key, len); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pos) 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += os_strlen(pem_key_enc_begin); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = search_tag(pem_key_enc_end, pos, key + len - pos); 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!end) 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt der = base64_decode(pos, end - pos, &der_len); 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!der) 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pkey = crypto_private_key_import(der, der_len, passwd); 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(der); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pkey; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tlsv1_set_key(struct tlsv1_credentials *cred, 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key, size_t len, const char *passwd) 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->key = crypto_private_key_import(key, len, passwd); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cred->key == NULL) 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->key = tlsv1_set_key_pem(key, len); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cred->key == NULL) 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->key = tlsv1_set_key_enc_pem(key, len, passwd); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cred->key == NULL) { 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key"); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_set_private_key - Set private key 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cred: TLSv1 credentials from tlsv1_cred_alloc() 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @private_key: File or reference name for the key in PEM or DER format 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @private_key_passwd: Passphrase for decrypted private key, %NULL if no 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * passphrase is used. 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @private_key_blob: private_key as inlined data or %NULL if not used 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @private_key_blob_len: private_key_blob length 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_set_private_key(struct tlsv1_credentials *cred, 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *private_key, 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *private_key_passwd, 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *private_key_blob, 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t private_key_blob_len) 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_private_key_free(cred->key); 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->key = NULL; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (private_key_blob) 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tlsv1_set_key(cred, private_key_blob, 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private_key_blob_len, 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private_key_passwd); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (private_key) { 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = (u8 *) os_readfile(private_key, &len); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private_key); 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = tlsv1_set_key(cred, buf, len, private_key_passwd); 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tlsv1_set_dhparams_der(struct tlsv1_credentials *cred, 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *dh, size_t len) 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = dh; 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = dh + len; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * DHParameter ::= SEQUENCE { 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * prime INTEGER, -- p 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * base INTEGER, -- g 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * privateValueLength INTEGER OPTIONAL } 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* DHParamer ::= SEQUENCE */ 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "DH: DH parameters did not start with a " 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "valid SEQUENCE - found class %d tag 0x%x", 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* prime INTEGER */ 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0) 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.class != ASN1_CLASS_UNIVERSAL || 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_INTEGER) { 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for p; " 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "class=%d tag=0x%x", hdr.class, hdr.tag); 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "DH: prime (p)", hdr.payload, hdr.length); 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length == 0) 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cred->dh_p); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->dh_p = os_malloc(hdr.length); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cred->dh_p == NULL) 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(cred->dh_p, hdr.payload, hdr.length); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->dh_p_len = hdr.length; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload + hdr.length; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* base INTEGER */ 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0) 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.class != ASN1_CLASS_UNIVERSAL || 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_INTEGER) { 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for g; " 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "class=%d tag=0x%x", hdr.class, hdr.tag); 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "DH: base (g)", hdr.payload, hdr.length); 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length == 0) 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cred->dh_g); 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->dh_g = os_malloc(hdr.length); 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cred->dh_g == NULL) 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(cred->dh_g, hdr.payload, hdr.length); 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->dh_g_len = hdr.length; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_dhparams_begin = "-----BEGIN DH PARAMETERS-----"; 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pem_dhparams_end = "-----END DH PARAMETERS-----"; 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred, 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char *der; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t der_len; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = search_tag(pem_dhparams_begin, buf, len); 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pos) { 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: No PEM dhparams tag found - " 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assume DER format"); 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tlsv1_set_dhparams_der(cred, buf, len); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format dhparams into DER " 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "format"); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += os_strlen(pem_dhparams_begin); 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = search_tag(pem_dhparams_end, pos, buf + len - pos); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end == NULL) { 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Could not find PEM dhparams end " 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "tag (%s)", pem_dhparams_end); 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt der = base64_decode(pos, end - pos, &der_len); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (der == NULL) { 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams"); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_set_dhparams_der(cred, der, der_len) < 0) { 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM dhparams " 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "DER conversion"); 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(der); 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(der); 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_set_dhparams - Set Diffie-Hellman parameters 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cred: TLSv1 credentials from tlsv1_cred_alloc() 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dh_file: File or reference name for the DH params in PEM or DER format 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dh_blob: DH params as inlined data or %NULL if not used 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dh_blob_len: dh_blob length 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file, 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *dh_blob, size_t dh_blob_len) 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dh_blob) 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tlsv1_set_dhparams_blob(cred, dh_blob, dh_blob_len); 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dh_file) { 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = (u8 *) os_readfile(dh_file, &len); 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh_file); 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = tlsv1_set_dhparams_blob(cred, buf, len); 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 507