Add preliminary version of NSS TLS/crypto wrapper for wpa_supplicant
This brings in the first step in adding support for using NSS (Mozilla Network Security Services) as the crypto and TLS library with wpa_supplicant. This version is able to run through EAP-PEAP and EAP-TTLS authentication, but does not yet implement any certificate/private key configuration. In addition, this does not implement proper key fetching functions either, so the end result is not really of much use in real world yet.
This commit is contained in:
parent
f335c69e14
commit
289ffc2b61
4 changed files with 918 additions and 0 deletions
213
src/crypto/crypto_nss.c
Normal file
213
src/crypto/crypto_nss.c
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Crypto wrapper functions for NSS
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <nspr/prtypes.h>
|
||||
#include <nspr/plarenas.h>
|
||||
#include <nspr/plhash.h>
|
||||
#include <nspr/prtime.h>
|
||||
#include <nspr/prinrval.h>
|
||||
#include <nspr/prclist.h>
|
||||
#include <nspr/prlock.h>
|
||||
#include <nss/sechash.h>
|
||||
#include <nss/pk11pub.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
static int nss_hash(HASH_HashType type, unsigned int max_res_len,
|
||||
size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *mac)
|
||||
{
|
||||
HASHContext *ctx;
|
||||
size_t i;
|
||||
unsigned int reslen;
|
||||
|
||||
ctx = HASH_Create(type);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
|
||||
HASH_Begin(ctx);
|
||||
for (i = 0; i < num_elem; i++)
|
||||
HASH_Update(ctx, addr[i], len[i]);
|
||||
HASH_End(ctx, mac, &reslen, max_res_len);
|
||||
HASH_Destroy(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
|
||||
{
|
||||
PK11Context *ctx = NULL;
|
||||
PK11SlotInfo *slot;
|
||||
SECItem *param = NULL;
|
||||
PK11SymKey *symkey = NULL;
|
||||
SECItem item;
|
||||
int olen;
|
||||
u8 pkey[8], next, tmp;
|
||||
int i;
|
||||
|
||||
/* Add parity bits to the key */
|
||||
next = 0;
|
||||
for (i = 0; i < 7; i++) {
|
||||
tmp = key[i];
|
||||
pkey[i] = (tmp >> i) | next | 1;
|
||||
next = tmp << (7 - i);
|
||||
}
|
||||
pkey[i] = next | 1;
|
||||
|
||||
slot = PK11_GetBestSlot(CKM_DES_ECB, NULL);
|
||||
if (slot == NULL) {
|
||||
wpa_printf(MSG_ERROR, "NSS: PK11_GetBestSlot failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
item.type = siBuffer;
|
||||
item.data = pkey;
|
||||
item.len = 8;
|
||||
symkey = PK11_ImportSymKey(slot, CKM_DES_ECB, PK11_OriginDerive,
|
||||
CKA_ENCRYPT, &item, NULL);
|
||||
if (symkey == NULL) {
|
||||
wpa_printf(MSG_ERROR, "NSS: PK11_ImportSymKey failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
param = PK11_GenerateNewParam(CKM_DES_ECB, symkey);
|
||||
if (param == NULL) {
|
||||
wpa_printf(MSG_ERROR, "NSS: PK11_GenerateNewParam failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx = PK11_CreateContextBySymKey(CKM_DES_ECB, CKA_ENCRYPT,
|
||||
symkey, param);
|
||||
if (ctx == NULL) {
|
||||
wpa_printf(MSG_ERROR, "NSS: PK11_CreateContextBySymKey("
|
||||
"CKM_DES_ECB) failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (PK11_CipherOp(ctx, cypher, &olen, 8, (void *) clear, 8) !=
|
||||
SECSuccess) {
|
||||
wpa_printf(MSG_ERROR, "NSS: PK11_CipherOp failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (ctx)
|
||||
PK11_DestroyContext(ctx, PR_TRUE);
|
||||
if (symkey)
|
||||
PK11_FreeSymKey(symkey);
|
||||
if (param)
|
||||
SECITEM_FreeItem(param, PR_TRUE);
|
||||
}
|
||||
|
||||
|
||||
int rc4_skip(const u8 *key, size_t keylen, size_t skip,
|
||||
u8 *data, size_t data_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
return nss_hash(HASH_AlgMD5, 16, num_elem, addr, len, mac);
|
||||
}
|
||||
|
||||
|
||||
int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
return nss_hash(HASH_AlgSHA1, 20, num_elem, addr, len, mac);
|
||||
}
|
||||
|
||||
|
||||
int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *mac)
|
||||
{
|
||||
return nss_hash(HASH_AlgSHA256, 32, num_elem, addr, len, mac);
|
||||
}
|
||||
|
||||
|
||||
void * aes_encrypt_init(const u8 *key, size_t len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void aes_encrypt_deinit(void *ctx)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void * aes_decrypt_init(const u8 *key, size_t len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void aes_decrypt_deinit(void *ctx)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int crypto_mod_exp(const u8 *base, size_t base_len,
|
||||
const u8 *power, size_t power_len,
|
||||
const u8 *modulus, size_t modulus_len,
|
||||
u8 *result, size_t *result_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_cipher {
|
||||
};
|
||||
|
||||
|
||||
struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
|
||||
const u8 *iv, const u8 *key,
|
||||
size_t key_len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
|
||||
u8 *crypt, size_t len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
|
||||
u8 *plain, size_t len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void crypto_cipher_deinit(struct crypto_cipher *ctx)
|
||||
{
|
||||
}
|
25
src/crypto/fips_prf_nss.c
Normal file
25
src/crypto/fips_prf_nss.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* FIPS 186-2 PRF for NSS
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
|
||||
{
|
||||
return -1;
|
||||
}
|
662
src/crypto/tls_nss.c
Normal file
662
src/crypto/tls_nss.c
Normal file
|
@ -0,0 +1,662 @@
|
|||
/*
|
||||
* SSL/TLS interface functions for NSS
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <nspr/prtypes.h>
|
||||
#include <nspr/plarenas.h>
|
||||
#include <nspr/plhash.h>
|
||||
#include <nspr/prio.h>
|
||||
#include <nspr/prclist.h>
|
||||
#include <nspr/prlock.h>
|
||||
#include <nspr/prinit.h>
|
||||
#include <nspr/prerror.h>
|
||||
#include <nspr/prmem.h>
|
||||
#include <nss/nss.h>
|
||||
#include <nss/nssilckt.h>
|
||||
#include <nss/ssl.h>
|
||||
#include <nss/pk11func.h>
|
||||
#include <nss/secerr.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "tls.h"
|
||||
|
||||
static int tls_nss_ref_count = 0;
|
||||
|
||||
static PRDescIdentity nss_layer_id;
|
||||
|
||||
|
||||
struct tls_connection {
|
||||
PRFileDesc *fd;
|
||||
|
||||
int established;
|
||||
int verify_peer;
|
||||
u8 *push_buf, *pull_buf, *pull_buf_offset;
|
||||
size_t push_buf_len, pull_buf_len;
|
||||
};
|
||||
|
||||
|
||||
static PRStatus nss_io_close(PRFileDesc *fd)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O close");
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static PRInt32 nss_io_read(PRFileDesc *fd, void *buf, PRInt32 amount)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O read(%d)", amount);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
static PRInt32 nss_io_write(PRFileDesc *fd, const void *buf, PRInt32 amount)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O write(%d)", amount);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
static PRInt32 nss_io_writev(PRFileDesc *fd, const PRIOVec *iov,
|
||||
PRInt32 iov_size, PRIntervalTime timeout)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O writev(%d)", iov_size);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
static PRInt32 nss_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
|
||||
PRIntn flags, PRIntervalTime timeout)
|
||||
{
|
||||
struct tls_connection *conn = (struct tls_connection *) fd->secret;
|
||||
u8 *end;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O recv(%d)", amount);
|
||||
|
||||
if (conn->pull_buf == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "NSS: No data available to be read yet");
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
end = conn->pull_buf + conn->pull_buf_len;
|
||||
if (end - conn->pull_buf_offset < amount)
|
||||
amount = end - conn->pull_buf_offset;
|
||||
os_memcpy(buf, conn->pull_buf_offset, amount);
|
||||
conn->pull_buf_offset += amount;
|
||||
if (conn->pull_buf_offset == end) {
|
||||
wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
|
||||
os_free(conn->pull_buf);
|
||||
conn->pull_buf = conn->pull_buf_offset = NULL;
|
||||
conn->pull_buf_len = 0;
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
|
||||
__func__,
|
||||
(unsigned long) (end - conn->pull_buf_offset));
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
|
||||
|
||||
static PRInt32 nss_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
|
||||
PRIntn flags, PRIntervalTime timeout)
|
||||
{
|
||||
struct tls_connection *conn = (struct tls_connection *) fd->secret;
|
||||
u8 *nbuf;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
|
||||
wpa_hexdump(MSG_MSGDUMP, "NSS: I/O send data", buf, amount);
|
||||
|
||||
nbuf = os_realloc(conn->push_buf, conn->push_buf_len + amount);
|
||||
if (nbuf == NULL) {
|
||||
wpa_printf(MSG_ERROR, "NSS: Failed to allocate memory for the "
|
||||
"data to be sent");
|
||||
return PR_FAILURE;
|
||||
}
|
||||
os_memcpy(nbuf + conn->push_buf_len, buf, amount);
|
||||
conn->push_buf = nbuf;
|
||||
conn->push_buf_len += amount;
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
|
||||
static PRInt32 nss_io_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount,
|
||||
PRIntn flags, PRNetAddr *addr,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
static PRInt32 nss_io_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount,
|
||||
PRIntn flags, const PRNetAddr *addr,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
static PRStatus nss_io_getpeername(PRFileDesc *fd, PRNetAddr *addr)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O getpeername");
|
||||
|
||||
/*
|
||||
* It Looks like NSS only supports IPv4 and IPv6 TCP sockets. Provide a
|
||||
* fake IPv4 address to work around this even though we are not really
|
||||
* using TCP.
|
||||
*/
|
||||
os_memset(addr, 0, sizeof(*addr));
|
||||
addr->inet.family = PR_AF_INET;
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static PRStatus nss_io_getsocketoption(PRFileDesc *fd,
|
||||
PRSocketOptionData *data)
|
||||
{
|
||||
switch (data->option) {
|
||||
case PR_SockOpt_Nonblocking:
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(Nonblocking)");
|
||||
data->value.non_blocking = PR_TRUE;
|
||||
return PR_SUCCESS;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(%d)",
|
||||
data->option);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const PRIOMethods nss_io = {
|
||||
PR_DESC_LAYERED,
|
||||
nss_io_close,
|
||||
nss_io_read,
|
||||
nss_io_write,
|
||||
NULL /* available */,
|
||||
NULL /* available64 */,
|
||||
NULL /* fsync */,
|
||||
NULL /* fseek */,
|
||||
NULL /* fseek64 */,
|
||||
NULL /* fileinfo */,
|
||||
NULL /* fileinfo64 */,
|
||||
nss_io_writev,
|
||||
NULL /* connect */,
|
||||
NULL /* accept */,
|
||||
NULL /* bind */,
|
||||
NULL /* listen */,
|
||||
NULL /* shutdown */,
|
||||
nss_io_recv,
|
||||
nss_io_send,
|
||||
nss_io_recvfrom,
|
||||
nss_io_sendto,
|
||||
NULL /* poll */,
|
||||
NULL /* acceptread */,
|
||||
NULL /* transmitfile */,
|
||||
NULL /* getsockname */,
|
||||
nss_io_getpeername,
|
||||
NULL /* reserved_fn_6 */,
|
||||
NULL /* reserved_fn_5 */,
|
||||
nss_io_getsocketoption,
|
||||
NULL /* setsocketoption */,
|
||||
NULL /* sendfile */,
|
||||
NULL /* connectcontinue */,
|
||||
NULL /* reserved_fn_3 */,
|
||||
NULL /* reserved_fn_2 */,
|
||||
NULL /* reserved_fn_1 */,
|
||||
NULL /* reserved_fn_0 */
|
||||
};
|
||||
|
||||
|
||||
static char * nss_password_cb(PK11SlotInfo *slot, PRBool retry, void *arg)
|
||||
{
|
||||
wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void * tls_init(const struct tls_config *conf)
|
||||
{
|
||||
char *dir;
|
||||
|
||||
tls_nss_ref_count++;
|
||||
if (tls_nss_ref_count > 1)
|
||||
return (void *) 1;
|
||||
|
||||
PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
|
||||
|
||||
nss_layer_id = PR_GetUniqueIdentity("wpa_supplicant");
|
||||
|
||||
PK11_SetPasswordFunc(nss_password_cb);
|
||||
|
||||
dir = getenv("SSL_DIR");
|
||||
if (dir) {
|
||||
if (NSS_Init(dir) != SECSuccess) {
|
||||
wpa_printf(MSG_ERROR, "NSS: NSS_Init(cert_dir=%s) "
|
||||
"failed", dir);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (NSS_NoDB_Init(NULL) != SECSuccess) {
|
||||
wpa_printf(MSG_ERROR, "NSS: NSS_NoDB_Init(NULL) "
|
||||
"failed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, PR_FALSE) !=
|
||||
SECSuccess ||
|
||||
SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_FALSE) != SECSuccess ||
|
||||
SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess ||
|
||||
SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE) != SECSuccess) {
|
||||
wpa_printf(MSG_ERROR, "NSS: SSL_OptionSetDefault failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (NSS_SetDomesticPolicy() != SECSuccess) {
|
||||
wpa_printf(MSG_ERROR, "NSS: NSS_SetDomesticPolicy() failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *) 1;
|
||||
}
|
||||
|
||||
void tls_deinit(void *ssl_ctx)
|
||||
{
|
||||
tls_nss_ref_count--;
|
||||
if (tls_nss_ref_count == 0) {
|
||||
if (NSS_Shutdown() != SECSuccess)
|
||||
wpa_printf(MSG_ERROR, "NSS: NSS_Shutdown() failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int tls_get_errors(void *tls_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static SECStatus nss_bad_cert_cb(void *arg, PRFileDesc *fd)
|
||||
{
|
||||
struct tls_connection *conn = arg;
|
||||
SECStatus res = SECSuccess;
|
||||
PRErrorCode err;
|
||||
CERTCertificate *cert;
|
||||
char *subject, *issuer;
|
||||
|
||||
err = PR_GetError();
|
||||
if (IS_SEC_ERROR(err))
|
||||
wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (sec err "
|
||||
"%d)", err - SEC_ERROR_BASE);
|
||||
else
|
||||
wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (err %d)",
|
||||
err);
|
||||
cert = SSL_PeerCertificate(fd);
|
||||
subject = CERT_NameToAscii(&cert->subject);
|
||||
issuer = CERT_NameToAscii(&cert->issuer);
|
||||
wpa_printf(MSG_DEBUG, "NSS: Peer certificate subject='%s' issuer='%s'",
|
||||
subject, issuer);
|
||||
CERT_DestroyCertificate(cert);
|
||||
PR_Free(subject);
|
||||
PR_Free(issuer);
|
||||
if (conn->verify_peer)
|
||||
res = SECFailure;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static void nss_handshake_cb(PRFileDesc *fd, void *client_data)
|
||||
{
|
||||
struct tls_connection *conn = client_data;
|
||||
wpa_printf(MSG_DEBUG, "NSS: Handshake completed");
|
||||
conn->established = 1;
|
||||
}
|
||||
|
||||
|
||||
struct tls_connection * tls_connection_init(void *tls_ctx)
|
||||
{
|
||||
struct tls_connection *conn;
|
||||
|
||||
conn = os_zalloc(sizeof(*conn));
|
||||
if (conn == NULL)
|
||||
return NULL;
|
||||
|
||||
conn->fd = PR_CreateIOLayerStub(nss_layer_id, &nss_io);
|
||||
if (conn->fd == NULL) {
|
||||
os_free(conn);
|
||||
return NULL;
|
||||
}
|
||||
conn->fd->secret = (void *) conn;
|
||||
|
||||
conn->fd = SSL_ImportFD(NULL, conn->fd);
|
||||
if (conn->fd == NULL) {
|
||||
os_free(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (SSL_OptionSet(conn->fd, SSL_SECURITY, PR_TRUE) != SECSuccess ||
|
||||
SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) !=
|
||||
SECSuccess ||
|
||||
SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) !=
|
||||
SECSuccess ||
|
||||
SSL_OptionSet(conn->fd, SSL_ENABLE_TLS, PR_TRUE) != SECSuccess ||
|
||||
SSL_BadCertHook(conn->fd, nss_bad_cert_cb, conn) != SECSuccess ||
|
||||
SSL_HandshakeCallback(conn->fd, nss_handshake_cb, conn) !=
|
||||
SECSuccess) {
|
||||
wpa_printf(MSG_ERROR, "NSS: Failed to set options");
|
||||
PR_Close(conn->fd);
|
||||
os_free(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SSL_ResetHandshake(conn->fd, PR_FALSE);
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
||||
void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
PR_Close(conn->fd);
|
||||
os_free(conn->push_buf);
|
||||
os_free(conn->pull_buf);
|
||||
os_free(conn);
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return conn->established;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
||||
const struct tls_connection_params *params)
|
||||
{
|
||||
wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_global_set_params(void *tls_ctx,
|
||||
const struct tls_connection_params *params)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_global_set_verify(void *tls_ctx, int check_crl)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
|
||||
int verify_peer)
|
||||
{
|
||||
conn->verify_peer = verify_peer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
|
||||
int tls_ia)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
|
||||
struct tls_keys *keys)
|
||||
{
|
||||
static u8 hack[48]; /* FIX */
|
||||
wpa_printf(MSG_DEBUG, "NSS: TODO - %s", __func__);
|
||||
os_memset(keys, 0, sizeof(*keys));
|
||||
keys->master_key = hack;
|
||||
keys->master_key_len = 48;
|
||||
keys->client_random = hack;
|
||||
keys->server_random = hack;
|
||||
keys->client_random_len = 32;
|
||||
keys->server_random_len = 32;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||
const char *label, int server_random_first,
|
||||
u8 *out, size_t out_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
|
||||
const u8 *in_data, size_t in_len,
|
||||
size_t *out_len, u8 **appl_data,
|
||||
size_t *appl_data_len)
|
||||
{
|
||||
u8 *out_data;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u",
|
||||
(unsigned int) in_len);
|
||||
|
||||
if (appl_data)
|
||||
*appl_data = NULL;
|
||||
|
||||
if (in_data && in_len) {
|
||||
if (conn->pull_buf) {
|
||||
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
|
||||
"pull_buf", __func__,
|
||||
(unsigned long) conn->pull_buf_len);
|
||||
os_free(conn->pull_buf);
|
||||
}
|
||||
conn->pull_buf = os_malloc(in_len);
|
||||
if (conn->pull_buf == NULL)
|
||||
return NULL;
|
||||
os_memcpy(conn->pull_buf, in_data, in_len);
|
||||
conn->pull_buf_offset = conn->pull_buf;
|
||||
conn->pull_buf_len = in_len;
|
||||
}
|
||||
|
||||
SSL_ForceHandshake(conn->fd);
|
||||
|
||||
if (conn->established && conn->push_buf == NULL) {
|
||||
/* Need to return something to get final TLS ACK. */
|
||||
conn->push_buf = os_malloc(1);
|
||||
}
|
||||
|
||||
out_data = conn->push_buf;
|
||||
*out_len = conn->push_buf_len;
|
||||
conn->push_buf = NULL;
|
||||
conn->push_buf_len = 0;
|
||||
return out_data;
|
||||
}
|
||||
|
||||
|
||||
u8 * tls_connection_server_handshake(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const u8 *in_data, size_t in_len,
|
||||
size_t *out_len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn,
|
||||
const u8 *in_data, size_t in_len,
|
||||
u8 *out_data, size_t out_len)
|
||||
{
|
||||
PRInt32 res;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes", (int) in_len);
|
||||
res = PR_Send(conn->fd, in_data, in_len, 0, 0);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_ERROR, "NSS: Encryption failed");
|
||||
return -1;
|
||||
}
|
||||
if (conn->push_buf == NULL)
|
||||
return -1;
|
||||
if (conn->push_buf_len < out_len)
|
||||
out_len = conn->push_buf_len;
|
||||
else if (conn->push_buf_len > out_len) {
|
||||
wpa_printf(MSG_INFO, "NSS: Not enough buffer space for "
|
||||
"encrypted message (in_len=%lu push_buf_len=%lu "
|
||||
"out_len=%lu",
|
||||
(unsigned long) in_len,
|
||||
(unsigned long) conn->push_buf_len,
|
||||
(unsigned long) out_len);
|
||||
}
|
||||
os_memcpy(out_data, conn->push_buf, out_len);
|
||||
os_free(conn->push_buf);
|
||||
conn->push_buf = NULL;
|
||||
conn->push_buf_len = 0;
|
||||
return out_len;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn,
|
||||
const u8 *in_data, size_t in_len,
|
||||
u8 *out_data, size_t out_len)
|
||||
{
|
||||
PRInt32 res;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes", (int) in_len);
|
||||
if (conn->pull_buf) {
|
||||
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
|
||||
"pull_buf", __func__,
|
||||
(unsigned long) conn->pull_buf_len);
|
||||
os_free(conn->pull_buf);
|
||||
}
|
||||
conn->pull_buf = os_malloc(in_len);
|
||||
if (conn->pull_buf == NULL)
|
||||
return -1;
|
||||
os_memcpy(conn->pull_buf, in_data, in_len);
|
||||
conn->pull_buf_offset = conn->pull_buf;
|
||||
conn->pull_buf_len = in_len;
|
||||
|
||||
res = PR_Recv(conn->fd, out_data, out_len, 0, 0);
|
||||
wpa_printf(MSG_DEBUG, "NSS: PR_Recv: %d", res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
|
||||
u8 *ciphers)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_enable_workaround(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
|
||||
int ext_type, const u8 *data,
|
||||
size_t data_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_write_alerts(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_keyblock_size(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
unsigned int tls_capabilities(void *tls_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_send_phase_finished(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
int final,
|
||||
u8 *out_data, size_t out_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_final_phase_finished(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_session_ticket_cb(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
tls_session_ticket_cb cb,
|
||||
void *ctx)
|
||||
{
|
||||
return -1;
|
||||
}
|
|
@ -655,6 +655,10 @@ endif
|
|||
ifeq ($(CONFIG_TLS), schannel)
|
||||
OBJS += ../src/crypto/tls_schannel.o
|
||||
endif
|
||||
ifeq ($(CONFIG_TLS), nss)
|
||||
OBJS += ../src/crypto/tls_nss.o
|
||||
LIBS += -lnss3 -lssl3
|
||||
endif
|
||||
ifeq ($(CONFIG_TLS), internal)
|
||||
OBJS += ../src/crypto/tls_internal.o
|
||||
OBJS += ../src/tls/tlsv1_common.o ../src/tls/tlsv1_record.o
|
||||
|
@ -724,6 +728,9 @@ LIBS_p += -lgcrypt
|
|||
endif
|
||||
ifeq ($(CONFIG_TLS), schannel)
|
||||
endif
|
||||
ifeq ($(CONFIG_TLS), nss)
|
||||
LIBS += -lnss3
|
||||
endif
|
||||
ifeq ($(CONFIG_TLS), internal)
|
||||
ifeq ($(CONFIG_CRYPTO), libtomcrypt)
|
||||
LIBS += -ltomcrypt -ltfm
|
||||
|
@ -753,6 +760,14 @@ OBJS_p += ../src/crypto/crypto_cryptoapi.o
|
|||
CONFIG_INTERNAL_SHA256=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
endif
|
||||
ifeq ($(CONFIG_TLS), nss)
|
||||
OBJS += ../src/crypto/crypto_nss.o
|
||||
OBJS_p += ../src/crypto/crypto_nss.o
|
||||
CONFIG_INTERNAL_MD4=y
|
||||
ifdef NEED_FIPS186_2_PRF
|
||||
OBJS += ../src/crypto/fips_prf_nss.o
|
||||
endif
|
||||
endif
|
||||
ifeq ($(CONFIG_TLS), internal)
|
||||
ifeq ($(CONFIG_CRYPTO), libtomcrypt)
|
||||
OBJS += ../src/crypto/crypto_libtomcrypt.o
|
||||
|
@ -1081,6 +1096,9 @@ endif
|
|||
ifeq ($(CONFIG_TLS), gnutls)
|
||||
OBJS_priv += ../src/crypto/crypto_gnutls.o
|
||||
endif
|
||||
ifeq ($(CONFIG_TLS), nss)
|
||||
OBJS_priv += ../src/crypto/crypto_nss.o
|
||||
endif
|
||||
ifeq ($(CONFIG_TLS), internal)
|
||||
ifeq ($(CONFIG_CRYPTO), libtomcrypt)
|
||||
OBJS_priv += ../src/crypto/crypto_libtomcrypt.o
|
||||
|
|
Loading…
Reference in a new issue