3
* Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 2 as
7
* published by the Free Software Foundation.
9
* Alternatively, this software may be distributed under the terms of BSD
12
* See README and COPYING for more details.
21
#include "tlsv1_cred.h"
24
struct tlsv1_credentials * tlsv1_cred_alloc(void)
26
struct tlsv1_credentials *cred;
27
cred = os_zalloc(sizeof(*cred));
32
void tlsv1_cred_free(struct tlsv1_credentials *cred)
37
x509_certificate_chain_free(cred->trusted_certs);
38
x509_certificate_chain_free(cred->cert);
39
crypto_private_key_free(cred->key);
46
static int tlsv1_add_cert_der(struct x509_certificate **chain,
47
const u8 *buf, size_t len)
49
struct x509_certificate *cert;
52
cert = x509_certificate_parse(buf, len);
54
wpa_printf(MSG_INFO, "TLSv1: %s - failed to parse certificate",
62
x509_name_string(&cert->subject, name, sizeof(name));
63
wpa_printf(MSG_DEBUG, "TLSv1: Added certificate: %s", name);
69
static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----";
70
static const char *pem_cert_end = "-----END CERTIFICATE-----";
73
static const u8 * search_tag(const char *tag, const u8 *buf, size_t len)
77
plen = os_strlen(tag);
81
for (i = 0; i < len - plen; i++) {
82
if (os_memcmp(buf + i, tag, plen) == 0)
90
static int tlsv1_add_cert(struct x509_certificate **chain,
91
const u8 *buf, size_t len)
97
pos = search_tag(pem_cert_begin, buf, len);
99
wpa_printf(MSG_DEBUG, "TLSv1: No PEM certificate tag found - "
100
"assume DER format");
101
return tlsv1_add_cert_der(chain, buf, len);
104
wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format certificate into "
108
pos += os_strlen(pem_cert_begin);
109
end = search_tag(pem_cert_end, pos, buf + len - pos);
111
wpa_printf(MSG_INFO, "TLSv1: Could not find PEM "
112
"certificate end tag (%s)", pem_cert_end);
116
der = base64_decode(pos, end - pos, &der_len);
118
wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM "
123
if (tlsv1_add_cert_der(chain, der, der_len) < 0) {
124
wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM "
125
"certificate after DER conversion");
132
end += os_strlen(pem_cert_end);
133
pos = search_tag(pem_cert_begin, end, buf + len - end);
140
static int tlsv1_set_cert_chain(struct x509_certificate **chain,
141
const char *cert, const u8 *cert_blob,
142
size_t cert_blob_len)
145
return tlsv1_add_cert(chain, cert_blob, cert_blob_len);
152
buf = (u8 *) os_readfile(cert, &len);
154
wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'",
159
ret = tlsv1_add_cert(chain, buf, len);
169
* tlsv1_set_ca_cert - Set trusted CA certificate(s)
170
* @cred: TLSv1 credentials from tlsv1_cred_alloc()
171
* @cert: File or reference name for X.509 certificate in PEM or DER format
172
* @cert_blob: cert as inlined data or %NULL if not used
173
* @cert_blob_len: ca_cert_blob length
174
* @path: Path to CA certificates (not yet supported)
175
* Returns: 0 on success, -1 on failure
177
int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert,
178
const u8 *cert_blob, size_t cert_blob_len,
181
if (tlsv1_set_cert_chain(&cred->trusted_certs, cert,
182
cert_blob, cert_blob_len) < 0)
186
/* TODO: add support for reading number of certificate files */
187
wpa_printf(MSG_INFO, "TLSv1: Use of CA certificate directory "
188
"not yet supported");
197
* tlsv1_set_cert - Set certificate
198
* @cred: TLSv1 credentials from tlsv1_cred_alloc()
199
* @cert: File or reference name for X.509 certificate in PEM or DER format
200
* @cert_blob: cert as inlined data or %NULL if not used
201
* @cert_blob_len: cert_blob length
202
* Returns: 0 on success, -1 on failure
204
int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert,
205
const u8 *cert_blob, size_t cert_blob_len)
207
return tlsv1_set_cert_chain(&cred->cert, cert,
208
cert_blob, cert_blob_len);
212
static int tlsv1_set_key(struct tlsv1_credentials *cred,
213
const u8 *key, size_t len)
215
cred->key = crypto_private_key_import(key, len);
216
if (cred->key == NULL) {
217
wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key");
225
* tlsv1_set_private_key - Set private key
226
* @cred: TLSv1 credentials from tlsv1_cred_alloc()
227
* @private_key: File or reference name for the key in PEM or DER format
228
* @private_key_passwd: Passphrase for decrypted private key, %NULL if no
229
* passphrase is used.
230
* @private_key_blob: private_key as inlined data or %NULL if not used
231
* @private_key_blob_len: private_key_blob length
232
* Returns: 0 on success, -1 on failure
234
int tlsv1_set_private_key(struct tlsv1_credentials *cred,
235
const char *private_key,
236
const char *private_key_passwd,
237
const u8 *private_key_blob,
238
size_t private_key_blob_len)
240
crypto_private_key_free(cred->key);
243
if (private_key_blob)
244
return tlsv1_set_key(cred, private_key_blob,
245
private_key_blob_len);
252
buf = (u8 *) os_readfile(private_key, &len);
254
wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'",
259
ret = tlsv1_set_key(cred, buf, len);
268
static int tlsv1_set_dhparams_der(struct tlsv1_credentials *cred,
269
const u8 *dh, size_t len)
278
* DHParameter ::= SEQUENCE {
279
* prime INTEGER, -- p
281
* privateValueLength INTEGER OPTIONAL }
284
/* DHParamer ::= SEQUENCE */
285
if (asn1_get_next(pos, len, &hdr) < 0 ||
286
hdr.class != ASN1_CLASS_UNIVERSAL ||
287
hdr.tag != ASN1_TAG_SEQUENCE) {
288
wpa_printf(MSG_DEBUG, "DH: DH parameters did not start with a "
289
"valid SEQUENCE - found class %d tag 0x%x",
296
if (asn1_get_next(pos, end - pos, &hdr) < 0)
299
if (hdr.class != ASN1_CLASS_UNIVERSAL ||
300
hdr.tag != ASN1_TAG_INTEGER) {
301
wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for p; "
302
"class=%d tag=0x%x", hdr.class, hdr.tag);
306
wpa_hexdump(MSG_MSGDUMP, "DH: prime (p)", hdr.payload, hdr.length);
310
cred->dh_p = os_malloc(hdr.length);
311
if (cred->dh_p == NULL)
313
os_memcpy(cred->dh_p, hdr.payload, hdr.length);
314
cred->dh_p_len = hdr.length;
315
pos = hdr.payload + hdr.length;
318
if (asn1_get_next(pos, end - pos, &hdr) < 0)
321
if (hdr.class != ASN1_CLASS_UNIVERSAL ||
322
hdr.tag != ASN1_TAG_INTEGER) {
323
wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for g; "
324
"class=%d tag=0x%x", hdr.class, hdr.tag);
328
wpa_hexdump(MSG_MSGDUMP, "DH: base (g)", hdr.payload, hdr.length);
332
cred->dh_g = os_malloc(hdr.length);
333
if (cred->dh_g == NULL)
335
os_memcpy(cred->dh_g, hdr.payload, hdr.length);
336
cred->dh_g_len = hdr.length;
342
static const char *pem_dhparams_begin = "-----BEGIN DH PARAMETERS-----";
343
static const char *pem_dhparams_end = "-----END DH PARAMETERS-----";
346
static int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred,
347
const u8 *buf, size_t len)
353
pos = search_tag(pem_dhparams_begin, buf, len);
355
wpa_printf(MSG_DEBUG, "TLSv1: No PEM dhparams tag found - "
356
"assume DER format");
357
return tlsv1_set_dhparams_der(cred, buf, len);
360
wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format dhparams into DER "
363
pos += os_strlen(pem_dhparams_begin);
364
end = search_tag(pem_dhparams_end, pos, buf + len - pos);
366
wpa_printf(MSG_INFO, "TLSv1: Could not find PEM dhparams end "
367
"tag (%s)", pem_dhparams_end);
371
der = base64_decode(pos, end - pos, &der_len);
373
wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams");
377
if (tlsv1_set_dhparams_der(cred, der, der_len) < 0) {
378
wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM dhparams "
391
* tlsv1_set_dhparams - Set Diffie-Hellman parameters
392
* @cred: TLSv1 credentials from tlsv1_cred_alloc()
393
* @dh_file: File or reference name for the DH params in PEM or DER format
394
* @dh_blob: DH params as inlined data or %NULL if not used
395
* @dh_blob_len: dh_blob length
396
* Returns: 0 on success, -1 on failure
398
int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file,
399
const u8 *dh_blob, size_t dh_blob_len)
402
return tlsv1_set_dhparams_blob(cred, dh_blob, dh_blob_len);
409
buf = (u8 *) os_readfile(dh_file, &len);
411
wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'",
416
ret = tlsv1_set_dhparams_blob(cred, buf, len);