2
* SSL/TLS interface functions for NSS
3
* Copyright (c) 2009, 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.
16
#include <nspr/prtypes.h>
17
#include <nspr/plarenas.h>
18
#include <nspr/plhash.h>
19
#include <nspr/prio.h>
20
#include <nspr/prclist.h>
21
#include <nspr/prlock.h>
22
#include <nspr/prinit.h>
23
#include <nspr/prerror.h>
24
#include <nspr/prmem.h>
26
#include <nss/nssilckt.h>
28
#include <nss/pk11func.h>
29
#include <nss/secerr.h>
34
static int tls_nss_ref_count = 0;
36
static PRDescIdentity nss_layer_id;
39
struct tls_connection {
44
u8 *push_buf, *pull_buf, *pull_buf_offset;
45
size_t push_buf_len, pull_buf_len;
49
static PRStatus nss_io_close(PRFileDesc *fd)
51
wpa_printf(MSG_DEBUG, "NSS: I/O close");
56
static PRInt32 nss_io_read(PRFileDesc *fd, void *buf, PRInt32 amount)
58
wpa_printf(MSG_DEBUG, "NSS: I/O read(%d)", amount);
63
static PRInt32 nss_io_write(PRFileDesc *fd, const void *buf, PRInt32 amount)
65
wpa_printf(MSG_DEBUG, "NSS: I/O write(%d)", amount);
70
static PRInt32 nss_io_writev(PRFileDesc *fd, const PRIOVec *iov,
71
PRInt32 iov_size, PRIntervalTime timeout)
73
wpa_printf(MSG_DEBUG, "NSS: I/O writev(%d)", iov_size);
78
static PRInt32 nss_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
79
PRIntn flags, PRIntervalTime timeout)
81
struct tls_connection *conn = (struct tls_connection *) fd->secret;
84
wpa_printf(MSG_DEBUG, "NSS: I/O recv(%d)", amount);
86
if (conn->pull_buf == NULL) {
87
wpa_printf(MSG_DEBUG, "NSS: No data available to be read yet");
91
end = conn->pull_buf + conn->pull_buf_len;
92
if (end - conn->pull_buf_offset < amount)
93
amount = end - conn->pull_buf_offset;
94
os_memcpy(buf, conn->pull_buf_offset, amount);
95
conn->pull_buf_offset += amount;
96
if (conn->pull_buf_offset == end) {
97
wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
98
os_free(conn->pull_buf);
99
conn->pull_buf = conn->pull_buf_offset = NULL;
100
conn->pull_buf_len = 0;
102
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
104
(unsigned long) (end - conn->pull_buf_offset));
110
static PRInt32 nss_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
111
PRIntn flags, PRIntervalTime timeout)
113
struct tls_connection *conn = (struct tls_connection *) fd->secret;
116
wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
117
wpa_hexdump(MSG_MSGDUMP, "NSS: I/O send data", buf, amount);
119
nbuf = os_realloc(conn->push_buf, conn->push_buf_len + amount);
121
wpa_printf(MSG_ERROR, "NSS: Failed to allocate memory for the "
125
os_memcpy(nbuf + conn->push_buf_len, buf, amount);
126
conn->push_buf = nbuf;
127
conn->push_buf_len += amount;
133
static PRInt32 nss_io_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount,
134
PRIntn flags, PRNetAddr *addr,
135
PRIntervalTime timeout)
137
wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
142
static PRInt32 nss_io_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount,
143
PRIntn flags, const PRNetAddr *addr,
144
PRIntervalTime timeout)
146
wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
151
static PRStatus nss_io_getpeername(PRFileDesc *fd, PRNetAddr *addr)
153
wpa_printf(MSG_DEBUG, "NSS: I/O getpeername");
156
* It Looks like NSS only supports IPv4 and IPv6 TCP sockets. Provide a
157
* fake IPv4 address to work around this even though we are not really
160
os_memset(addr, 0, sizeof(*addr));
161
addr->inet.family = PR_AF_INET;
167
static PRStatus nss_io_getsocketoption(PRFileDesc *fd,
168
PRSocketOptionData *data)
170
switch (data->option) {
171
case PR_SockOpt_Nonblocking:
172
wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(Nonblocking)");
173
data->value.non_blocking = PR_TRUE;
176
wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(%d)",
183
static const PRIOMethods nss_io = {
188
NULL /* available */,
189
NULL /* available64 */,
194
NULL /* fileinfo64 */,
206
NULL /* acceptread */,
207
NULL /* transmitfile */,
208
NULL /* getsockname */,
210
NULL /* reserved_fn_6 */,
211
NULL /* reserved_fn_5 */,
212
nss_io_getsocketoption,
213
NULL /* setsocketoption */,
215
NULL /* connectcontinue */,
216
NULL /* reserved_fn_3 */,
217
NULL /* reserved_fn_2 */,
218
NULL /* reserved_fn_1 */,
219
NULL /* reserved_fn_0 */
223
static char * nss_password_cb(PK11SlotInfo *slot, PRBool retry, void *arg)
225
wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__);
230
void * tls_init(const struct tls_config *conf)
235
if (tls_nss_ref_count > 1)
238
PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
240
nss_layer_id = PR_GetUniqueIdentity("wpa_supplicant");
242
PK11_SetPasswordFunc(nss_password_cb);
244
dir = getenv("SSL_DIR");
246
if (NSS_Init(dir) != SECSuccess) {
247
wpa_printf(MSG_ERROR, "NSS: NSS_Init(cert_dir=%s) "
252
if (NSS_NoDB_Init(NULL) != SECSuccess) {
253
wpa_printf(MSG_ERROR, "NSS: NSS_NoDB_Init(NULL) "
259
if (SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, PR_FALSE) !=
261
SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_FALSE) != SECSuccess ||
262
SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess ||
263
SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE) != SECSuccess) {
264
wpa_printf(MSG_ERROR, "NSS: SSL_OptionSetDefault failed");
268
if (NSS_SetDomesticPolicy() != SECSuccess) {
269
wpa_printf(MSG_ERROR, "NSS: NSS_SetDomesticPolicy() failed");
276
void tls_deinit(void *ssl_ctx)
279
if (tls_nss_ref_count == 0) {
280
if (NSS_Shutdown() != SECSuccess)
281
wpa_printf(MSG_ERROR, "NSS: NSS_Shutdown() failed");
286
int tls_get_errors(void *tls_ctx)
292
static SECStatus nss_bad_cert_cb(void *arg, PRFileDesc *fd)
294
struct tls_connection *conn = arg;
295
SECStatus res = SECSuccess;
297
CERTCertificate *cert;
298
char *subject, *issuer;
301
if (IS_SEC_ERROR(err))
302
wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (sec err "
303
"%d)", err - SEC_ERROR_BASE);
305
wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (err %d)",
307
cert = SSL_PeerCertificate(fd);
308
subject = CERT_NameToAscii(&cert->subject);
309
issuer = CERT_NameToAscii(&cert->issuer);
310
wpa_printf(MSG_DEBUG, "NSS: Peer certificate subject='%s' issuer='%s'",
312
CERT_DestroyCertificate(cert);
315
if (conn->verify_peer)
322
static void nss_handshake_cb(PRFileDesc *fd, void *client_data)
324
struct tls_connection *conn = client_data;
325
wpa_printf(MSG_DEBUG, "NSS: Handshake completed");
326
conn->established = 1;
330
struct tls_connection * tls_connection_init(void *tls_ctx)
332
struct tls_connection *conn;
334
conn = os_zalloc(sizeof(*conn));
338
conn->fd = PR_CreateIOLayerStub(nss_layer_id, &nss_io);
339
if (conn->fd == NULL) {
343
conn->fd->secret = (void *) conn;
345
conn->fd = SSL_ImportFD(NULL, conn->fd);
346
if (conn->fd == NULL) {
351
if (SSL_OptionSet(conn->fd, SSL_SECURITY, PR_TRUE) != SECSuccess ||
352
SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) !=
354
SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) !=
356
SSL_OptionSet(conn->fd, SSL_ENABLE_TLS, PR_TRUE) != SECSuccess ||
357
SSL_BadCertHook(conn->fd, nss_bad_cert_cb, conn) != SECSuccess ||
358
SSL_HandshakeCallback(conn->fd, nss_handshake_cb, conn) !=
360
wpa_printf(MSG_ERROR, "NSS: Failed to set options");
366
SSL_ResetHandshake(conn->fd, PR_FALSE);
372
void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
375
os_free(conn->push_buf);
376
os_free(conn->pull_buf);
381
int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
383
return conn->established;
387
int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
393
int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
394
const struct tls_connection_params *params)
396
wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__);
401
int tls_global_set_params(void *tls_ctx,
402
const struct tls_connection_params *params)
408
int tls_global_set_verify(void *tls_ctx, int check_crl)
414
int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
417
conn->verify_peer = verify_peer;
422
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
429
int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
430
struct tls_keys *keys)
432
/* NSS does not export master secret or client/server random. */
437
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
438
const char *label, int server_random_first,
439
u8 *out, size_t out_len)
441
if (conn == NULL || server_random_first) {
442
wpa_printf(MSG_INFO, "NSS: Unsupported PRF request "
443
"(server_random_first=%d)",
444
server_random_first);
448
if (SSL_ExportKeyingMaterial(conn->fd, label, NULL, 0, out, out_len) !=
450
wpa_printf(MSG_INFO, "NSS: Failed to use TLS extractor "
451
"(label='%s' out_len=%d", label, (int) out_len);
459
struct wpabuf * tls_connection_handshake(void *tls_ctx,
460
struct tls_connection *conn,
461
const struct wpabuf *in_data,
462
struct wpabuf **appl_data)
464
struct wpabuf *out_data;
466
wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u",
467
in_data ? (unsigned int) wpabuf_len(in_data) : 0);
472
if (in_data && wpabuf_len(in_data) > 0) {
473
if (conn->pull_buf) {
474
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
475
"pull_buf", __func__,
476
(unsigned long) conn->pull_buf_len);
477
os_free(conn->pull_buf);
479
conn->pull_buf = os_malloc(wpabuf_len(in_data));
480
if (conn->pull_buf == NULL)
482
os_memcpy(conn->pull_buf, wpabuf_head(in_data),
483
wpabuf_len(in_data));
484
conn->pull_buf_offset = conn->pull_buf;
485
conn->pull_buf_len = wpabuf_len(in_data);
488
SSL_ForceHandshake(conn->fd);
490
if (conn->established && conn->push_buf == NULL) {
491
/* Need to return something to get final TLS ACK. */
492
conn->push_buf = os_malloc(1);
495
if (conn->push_buf == NULL)
497
out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
498
if (out_data == NULL)
499
os_free(conn->push_buf);
500
conn->push_buf = NULL;
501
conn->push_buf_len = 0;
506
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
507
struct tls_connection *conn,
508
const struct wpabuf *in_data,
509
struct wpabuf **appl_data)
515
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
516
struct tls_connection *conn,
517
const struct wpabuf *in_data)
522
wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes",
523
(int) wpabuf_len(in_data));
524
res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0,
527
wpa_printf(MSG_ERROR, "NSS: Encryption failed");
530
if (conn->push_buf == NULL)
532
buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
534
os_free(conn->push_buf);
535
conn->push_buf = NULL;
536
conn->push_buf_len = 0;
541
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
542
struct tls_connection *conn,
543
const struct wpabuf *in_data)
548
wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes",
549
(int) wpabuf_len(in_data));
550
if (conn->pull_buf) {
551
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
552
"pull_buf", __func__,
553
(unsigned long) conn->pull_buf_len);
554
os_free(conn->pull_buf);
556
conn->pull_buf = os_malloc(wpabuf_len(in_data));
557
if (conn->pull_buf == NULL)
559
os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data));
560
conn->pull_buf_offset = conn->pull_buf;
561
conn->pull_buf_len = wpabuf_len(in_data);
564
* Even though we try to disable TLS compression, it is possible that
565
* this cannot be done with all TLS libraries. Add extra buffer space
566
* to handle the possibility of the decrypted data being longer than
569
out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
573
res = PR_Recv(conn->fd, wpabuf_mhead(out), wpabuf_size(out), 0, 0);
574
wpa_printf(MSG_DEBUG, "NSS: PR_Recv: %d", res);
579
wpabuf_put(out, res);
585
int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
591
int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
598
int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
599
char *buf, size_t buflen)
605
int tls_connection_enable_workaround(void *tls_ctx,
606
struct tls_connection *conn)
612
int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
613
int ext_type, const u8 *data,
620
int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
626
int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
632
int tls_connection_get_write_alerts(void *tls_ctx,
633
struct tls_connection *conn)
639
int tls_connection_get_keyblock_size(void *tls_ctx,
640
struct tls_connection *conn)
646
unsigned int tls_capabilities(void *tls_ctx)
652
struct wpabuf * tls_connection_ia_send_phase_finished(
653
void *tls_ctx, struct tls_connection *conn, int final)
659
int tls_connection_ia_final_phase_finished(void *tls_ctx,
660
struct tls_connection *conn)
666
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
667
struct tls_connection *conn,
668
const u8 *key, size_t key_len)
674
int tls_connection_set_session_ticket_cb(void *tls_ctx,
675
struct tls_connection *conn,
676
tls_session_ticket_cb cb,