18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SSL/TLS interface functions for NSS 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nspr/prtypes.h> 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nspr/plarenas.h> 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nspr/plhash.h> 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nspr/prio.h> 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nspr/prclist.h> 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nspr/prlock.h> 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nspr/prinit.h> 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nspr/prerror.h> 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nspr/prmem.h> 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nss/nss.h> 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nss/nssilckt.h> 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nss/ssl.h> 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nss/pk11func.h> 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nss/secerr.h> 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tls.h" 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_nss_ref_count = 0; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic PRDescIdentity nss_layer_id; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_connection { 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PRFileDesc *fd; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int established; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int verify_peer; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *push_buf, *pull_buf, *pull_buf_offset; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t push_buf_len, pull_buf_len; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic PRStatus nss_io_close(PRFileDesc *fd) 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: I/O close"); 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return PR_SUCCESS; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic PRInt32 nss_io_read(PRFileDesc *fd, void *buf, PRInt32 amount) 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: I/O read(%d)", amount); 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return PR_FAILURE; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic PRInt32 nss_io_write(PRFileDesc *fd, const void *buf, PRInt32 amount) 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: I/O write(%d)", amount); 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return PR_FAILURE; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic PRInt32 nss_io_writev(PRFileDesc *fd, const PRIOVec *iov, 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PRInt32 iov_size, PRIntervalTime timeout) 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: I/O writev(%d)", iov_size); 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return PR_FAILURE; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic PRInt32 nss_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount, 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PRIntn flags, PRIntervalTime timeout) 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn = (struct tls_connection *) fd->secret; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *end; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: I/O recv(%d)", amount); 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf == NULL) { 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: No data available to be read yet"); 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return PR_FAILURE; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = conn->pull_buf + conn->pull_buf_len; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - conn->pull_buf_offset < amount) 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt amount = end - conn->pull_buf_offset; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, conn->pull_buf_offset, amount); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf_offset += amount; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf_offset == end) { 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->pull_buf); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf = conn->pull_buf_offset = NULL; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf_len = 0; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) (end - conn->pull_buf_offset)); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return amount; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic PRInt32 nss_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount, 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PRIntn flags, PRIntervalTime timeout) 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn = (struct tls_connection *) fd->secret; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *nbuf; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "NSS: I/O send data", buf, amount); 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nbuf = os_realloc(conn->push_buf, conn->push_buf_len + amount); 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nbuf == NULL) { 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "NSS: Failed to allocate memory for the " 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data to be sent"); 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return PR_FAILURE; 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(nbuf + conn->push_buf_len, buf, amount); 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf = nbuf; 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf_len += amount; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return amount; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic PRInt32 nss_io_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount, 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PRIntn flags, PRNetAddr *addr, 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PRIntervalTime timeout) 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return PR_FAILURE; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic PRInt32 nss_io_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount, 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PRIntn flags, const PRNetAddr *addr, 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PRIntervalTime timeout) 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return PR_FAILURE; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic PRStatus nss_io_getpeername(PRFileDesc *fd, PRNetAddr *addr) 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: I/O getpeername"); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * It Looks like NSS only supports IPv4 and IPv6 TCP sockets. Provide a 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * fake IPv4 address to work around this even though we are not really 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * using TCP. 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(addr, 0, sizeof(*addr)); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr->inet.family = PR_AF_INET; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return PR_SUCCESS; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic PRStatus nss_io_getsocketoption(PRFileDesc *fd, 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PRSocketOptionData *data) 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->option) { 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PR_SockOpt_Nonblocking: 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(Nonblocking)"); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->value.non_blocking = PR_TRUE; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return PR_SUCCESS; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(%d)", 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->option); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return PR_FAILURE; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const PRIOMethods nss_io = { 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PR_DESC_LAYERED, 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nss_io_close, 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nss_io_read, 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nss_io_write, 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* available */, 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* available64 */, 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* fsync */, 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* fseek */, 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* fseek64 */, 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* fileinfo */, 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* fileinfo64 */, 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nss_io_writev, 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* connect */, 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* accept */, 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* bind */, 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* listen */, 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* shutdown */, 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nss_io_recv, 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nss_io_send, 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nss_io_recvfrom, 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nss_io_sendto, 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* poll */, 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* acceptread */, 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* transmitfile */, 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* getsockname */, 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nss_io_getpeername, 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* reserved_fn_6 */, 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* reserved_fn_5 */, 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nss_io_getsocketoption, 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* setsocketoption */, 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* sendfile */, 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* connectcontinue */, 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* reserved_fn_3 */, 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* reserved_fn_2 */, 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* reserved_fn_1 */, 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL /* reserved_fn_0 */ 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * nss_password_cb(PK11SlotInfo *slot, PRBool retry, void *arg) 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * tls_init(const struct tls_config *conf) 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *dir; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_nss_ref_count++; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_nss_ref_count > 1) 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (void *) 1; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nss_layer_id = PR_GetUniqueIdentity("wpa_supplicant"); 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PK11_SetPasswordFunc(nss_password_cb); 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dir = getenv("SSL_DIR"); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dir) { 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (NSS_Init(dir) != SECSuccess) { 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "NSS: NSS_Init(cert_dir=%s) " 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed", dir); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (NSS_NoDB_Init(NULL) != SECSuccess) { 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "NSS: NSS_NoDB_Init(NULL) " 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed"); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, PR_FALSE) != 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SECSuccess || 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_FALSE) != SECSuccess || 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess || 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE) != SECSuccess) { 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "NSS: SSL_OptionSetDefault failed"); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (NSS_SetDomesticPolicy() != SECSuccess) { 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "NSS: NSS_SetDomesticPolicy() failed"); 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (void *) 1; 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_deinit(void *ssl_ctx) 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_nss_ref_count--; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_nss_ref_count == 0) { 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (NSS_Shutdown() != SECSuccess) 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "NSS: NSS_Shutdown() failed"); 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_get_errors(void *tls_ctx) 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic SECStatus nss_bad_cert_cb(void *arg, PRFileDesc *fd) 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn = arg; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SECStatus res = SECSuccess; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PRErrorCode err; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CERTCertificate *cert; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *subject, *issuer; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = PR_GetError(); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (IS_SEC_ERROR(err)) 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (sec err " 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d)", err - SEC_ERROR_BASE); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (err %d)", 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert = SSL_PeerCertificate(fd); 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subject = CERT_NameToAscii(&cert->subject); 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt issuer = CERT_NameToAscii(&cert->issuer); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: Peer certificate subject='%s' issuer='%s'", 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subject, issuer); 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CERT_DestroyCertificate(cert); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PR_Free(subject); 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PR_Free(issuer); 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->verify_peer) 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = SECFailure; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nss_handshake_cb(PRFileDesc *fd, void *client_data) 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn = client_data; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: Handshake completed"); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->established = 1; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_connection * tls_connection_init(void *tls_ctx) 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn = os_zalloc(sizeof(*conn)); 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->fd = PR_CreateIOLayerStub(nss_layer_id, &nss_io); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->fd == NULL) { 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->fd->secret = (void *) conn; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->fd = SSL_ImportFD(NULL, conn->fd); 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->fd == NULL) { 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (SSL_OptionSet(conn->fd, SSL_SECURITY, PR_TRUE) != SECSuccess || 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SECSuccess || 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SECSuccess || 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SSL_OptionSet(conn->fd, SSL_ENABLE_TLS, PR_TRUE) != SECSuccess || 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SSL_BadCertHook(conn->fd, nss_bad_cert_cb, conn) != SECSuccess || 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SSL_HandshakeCallback(conn->fd, nss_handshake_cb, conn) != 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SECSuccess) { 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "NSS: Failed to set options"); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PR_Close(conn->fd); 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn); 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SSL_ResetHandshake(conn->fd, PR_FALSE); 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return conn; 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PR_Close(conn->fd); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->push_buf); 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->pull_buf); 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn); 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_established(void *tls_ctx, struct tls_connection *conn) 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return conn->established; 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct tls_connection_params *params) 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__); 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_global_set_params(void *tls_ctx, 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct tls_connection_params *params) 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_global_set_verify(void *tls_ctx, int check_crl) 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int verify_peer) 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->verify_peer = verify_peer; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_keys *keys) 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* NSS does not export master secret or client/server random. */ 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_prf(void *tls_ctx, struct tls_connection *conn, 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *label, int server_random_first, 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *out, size_t out_len) 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL || server_random_first) { 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "NSS: Unsupported PRF request " 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(server_random_first=%d)", 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt server_random_first); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (SSL_ExportKeyingMaterial(conn->fd, label, NULL, 0, out, out_len) != 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SECSuccess) { 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "NSS: Failed to use TLS extractor " 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(label='%s' out_len=%d", label, (int) out_len); 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_handshake(void *tls_ctx, 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data, 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **appl_data) 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *out_data; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u", 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_data ? (unsigned int) wpabuf_len(in_data) : 0); 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (appl_data) 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *appl_data = NULL; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_data && wpabuf_len(in_data) > 0) { 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf) { 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pull_buf", __func__, 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) conn->pull_buf_len); 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->pull_buf); 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf = os_malloc(wpabuf_len(in_data)); 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf == NULL) 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(conn->pull_buf, wpabuf_head(in_data), 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(in_data)); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf_offset = conn->pull_buf; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf_len = wpabuf_len(in_data); 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SSL_ForceHandshake(conn->fd); 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->established && conn->push_buf == NULL) { 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Need to return something to get final TLS ACK. */ 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf = os_malloc(1); 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->push_buf == NULL) 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len); 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (out_data == NULL) 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->push_buf); 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf = NULL; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf_len = 0; 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return out_data; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_server_handshake(void *tls_ctx, 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data, 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **appl_data) 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_encrypt(void *tls_ctx, 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data) 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PRInt32 res; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes", 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) wpabuf_len(in_data)); 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0, 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0); 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "NSS: Encryption failed"); 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->push_buf == NULL) 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len); 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->push_buf); 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf = NULL; 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf_len = 0; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_decrypt(void *tls_ctx, 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data) 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PRInt32 res; 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *out; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes", 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) wpabuf_len(in_data)); 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf) { 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pull_buf", __func__, 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) conn->pull_buf_len); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->pull_buf); 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf = os_malloc(wpabuf_len(in_data)); 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf == NULL) 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data)); 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf_offset = conn->pull_buf; 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf_len = wpabuf_len(in_data); 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Even though we try to disable TLS compression, it is possible that 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this cannot be done with all TLS libraries. Add extra buffer space 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to handle the possibility of the decrypted data being longer than 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * input data. 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (out == NULL) 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = PR_Recv(conn->fd, wpabuf_mhead(out), wpabuf_size(out), 0, 0); 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "NSS: PR_Recv: %d", res); 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(out); 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(out, res); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return out; 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *ciphers) 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_get_cipher(void *tls_ctx, struct tls_connection *conn, 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf, size_t buflen) 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_enable_workaround(void *tls_ctx, 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn) 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ext_type, const u8 *data, 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t data_len) 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_write_alerts(void *tls_ctx, 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn) 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_keyblock_size(void *tls_ctx, 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn) 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int tls_capabilities(void *tls_ctx) 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_session_ticket_cb(void *tls_ctx, 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_session_ticket_cb cb, 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx) 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 646