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