aboutsummaryrefslogtreecommitdiffstats
path: root/src/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/Makefile3
-rw-r--r--src/crypto/aes-internal-dec.c2
-rw-r--r--src/crypto/aes-internal-enc.c2
-rw-r--r--src/crypto/crypto.h3
-rw-r--r--src/crypto/crypto_internal-rsa.c1
-rw-r--r--src/crypto/crypto_internal.c84
-rw-r--r--src/crypto/dh_group5.c2
-rw-r--r--src/crypto/fips_prf_internal.c5
-rw-r--r--src/crypto/md5-internal.c2
-rw-r--r--src/crypto/ms_funcs.c106
-rw-r--r--src/crypto/random.c18
-rw-r--r--src/crypto/sha1-pbkdf2.c2
-rw-r--r--src/crypto/sha1-tlsprf.c7
-rw-r--r--src/crypto/sha1.h6
-rw-r--r--src/crypto/sha256-internal.c43
-rw-r--r--src/crypto/sha256-tlsprf.c72
-rw-r--r--src/crypto/sha256.h5
-rw-r--r--src/crypto/sha256_i.h31
-rw-r--r--src/crypto/tls.h69
-rw-r--r--src/crypto/tls_gnutls.c331
-rw-r--r--src/crypto/tls_internal.c72
-rw-r--r--src/crypto/tls_none.c29
-rw-r--r--src/crypto/tls_nss.c29
-rw-r--r--src/crypto/tls_openssl.c34
-rw-r--r--src/crypto/tls_schannel.c29
25 files changed, 394 insertions, 593 deletions
diff --git a/src/crypto/Makefile b/src/crypto/Makefile
index 69aa16a..b221dd4 100644
--- a/src/crypto/Makefile
+++ b/src/crypto/Makefile
@@ -12,6 +12,7 @@ include ../lib.rules
CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT
CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
#CFLAGS += -DALL_DH_GROUPS
+CFLAGS += -DCONFIG_SHA256
LIB_OBJS= \
aes-cbc.o \
@@ -40,6 +41,7 @@ LIB_OBJS= \
sha1-tlsprf.o \
sha1-tprf.o \
sha256.o \
+ sha256-tlsprf.o \
sha256-internal.o
LIB_OBJS += crypto_internal.o
@@ -48,6 +50,7 @@ LIB_OBJS += crypto_internal-modexp.o
LIB_OBJS += crypto_internal-rsa.o
LIB_OBJS += tls_internal.o
LIB_OBJS += fips_prf_internal.o
+LIB_OBJS += random.o
libcrypto.a: $(LIB_OBJS)
diff --git a/src/crypto/aes-internal-dec.c b/src/crypto/aes-internal-dec.c
index 2d32c03..a0fc45b 100644
--- a/src/crypto/aes-internal-dec.c
+++ b/src/crypto/aes-internal-dec.c
@@ -32,7 +32,7 @@
*
* @return the number of rounds for the given cipher key size.
*/
-void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[])
+static void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[])
{
int Nr = 10, i, j;
u32 temp;
diff --git a/src/crypto/aes-internal-enc.c b/src/crypto/aes-internal-enc.c
index 2f19826..8726aa7 100644
--- a/src/crypto/aes-internal-enc.c
+++ b/src/crypto/aes-internal-enc.c
@@ -27,7 +27,7 @@
#include "crypto.h"
#include "aes_i.h"
-void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16])
+static void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16])
{
u32 s0, s1, s2, s3, t0, t1, t2, t3;
const int Nr = 10;
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index 587b5a9..6dca191 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -155,7 +155,8 @@ void aes_decrypt_deinit(void *ctx);
enum crypto_hash_alg {
CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1,
- CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1
+ CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1,
+ CRYPTO_HASH_ALG_SHA256, CRYPTO_HASH_ALG_HMAC_SHA256
};
struct crypto_hash;
diff --git a/src/crypto/crypto_internal-rsa.c b/src/crypto/crypto_internal-rsa.c
index 205042c..7f0a5cf 100644
--- a/src/crypto/crypto_internal-rsa.c
+++ b/src/crypto/crypto_internal-rsa.c
@@ -17,7 +17,6 @@
#include "common.h"
#include "crypto.h"
#include "tls/rsa.h"
-#include "tls/bignum.h"
#include "tls/pkcs1.h"
#include "tls/pkcs8.h"
diff --git a/src/crypto/crypto_internal.c b/src/crypto/crypto_internal.c
index 8fdba65..9362fe1 100644
--- a/src/crypto/crypto_internal.c
+++ b/src/crypto/crypto_internal.c
@@ -1,6 +1,6 @@
/*
* Crypto wrapper for internal crypto implementation
- * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2011, 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
@@ -16,6 +16,7 @@
#include "common.h"
#include "crypto.h"
+#include "sha256_i.h"
#include "sha1_i.h"
#include "md5_i.h"
@@ -24,6 +25,9 @@ struct crypto_hash {
union {
struct MD5Context md5;
struct SHA1Context sha1;
+#ifdef CONFIG_SHA256
+ struct sha256_state sha256;
+#endif /* CONFIG_SHA256 */
} u;
u8 key[64];
size_t key_len;
@@ -35,7 +39,7 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
{
struct crypto_hash *ctx;
u8 k_pad[64];
- u8 tk[20];
+ u8 tk[32];
size_t i;
ctx = os_zalloc(sizeof(*ctx));
@@ -51,6 +55,11 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
case CRYPTO_HASH_ALG_SHA1:
SHA1Init(&ctx->u.sha1);
break;
+#ifdef CONFIG_SHA256
+ case CRYPTO_HASH_ALG_SHA256:
+ sha256_init(&ctx->u.sha256);
+ break;
+#endif /* CONFIG_SHA256 */
case CRYPTO_HASH_ALG_HMAC_MD5:
if (key_len > sizeof(k_pad)) {
MD5Init(&ctx->u.md5);
@@ -63,7 +72,8 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
ctx->key_len = key_len;
os_memcpy(k_pad, key, key_len);
- os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
+ if (key_len < sizeof(k_pad))
+ os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
for (i = 0; i < sizeof(k_pad); i++)
k_pad[i] ^= 0x36;
MD5Init(&ctx->u.md5);
@@ -81,12 +91,34 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
ctx->key_len = key_len;
os_memcpy(k_pad, key, key_len);
- os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
+ if (key_len < sizeof(k_pad))
+ os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
for (i = 0; i < sizeof(k_pad); i++)
k_pad[i] ^= 0x36;
SHA1Init(&ctx->u.sha1);
SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
break;
+#ifdef CONFIG_SHA256
+ case CRYPTO_HASH_ALG_HMAC_SHA256:
+ if (key_len > sizeof(k_pad)) {
+ sha256_init(&ctx->u.sha256);
+ sha256_process(&ctx->u.sha256, key, key_len);
+ sha256_done(&ctx->u.sha256, tk);
+ key = tk;
+ key_len = 32;
+ }
+ os_memcpy(ctx->key, key, key_len);
+ ctx->key_len = key_len;
+
+ os_memcpy(k_pad, key, key_len);
+ if (key_len < sizeof(k_pad))
+ os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
+ for (i = 0; i < sizeof(k_pad); i++)
+ k_pad[i] ^= 0x36;
+ sha256_init(&ctx->u.sha256);
+ sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
+ break;
+#endif /* CONFIG_SHA256 */
default:
os_free(ctx);
return NULL;
@@ -110,6 +142,14 @@ void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
case CRYPTO_HASH_ALG_HMAC_SHA1:
SHA1Update(&ctx->u.sha1, data, len);
break;
+#ifdef CONFIG_SHA256
+ case CRYPTO_HASH_ALG_SHA256:
+ case CRYPTO_HASH_ALG_HMAC_SHA256:
+ sha256_process(&ctx->u.sha256, data, len);
+ break;
+#endif /* CONFIG_SHA256 */
+ default:
+ break;
}
}
@@ -146,6 +186,17 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
*len = 20;
SHA1Final(mac, &ctx->u.sha1);
break;
+#ifdef CONFIG_SHA256
+ case CRYPTO_HASH_ALG_SHA256:
+ if (*len < 32) {
+ *len = 32;
+ os_free(ctx);
+ return -1;
+ }
+ *len = 32;
+ sha256_done(&ctx->u.sha256, mac);
+ break;
+#endif /* CONFIG_SHA256 */
case CRYPTO_HASH_ALG_HMAC_MD5:
if (*len < 16) {
*len = 16;
@@ -186,6 +237,31 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
SHA1Update(&ctx->u.sha1, mac, 20);
SHA1Final(mac, &ctx->u.sha1);
break;
+#ifdef CONFIG_SHA256
+ case CRYPTO_HASH_ALG_HMAC_SHA256:
+ if (*len < 32) {
+ *len = 32;
+ os_free(ctx);
+ return -1;
+ }
+ *len = 32;
+
+ sha256_done(&ctx->u.sha256, mac);
+
+ os_memcpy(k_pad, ctx->key, ctx->key_len);
+ os_memset(k_pad + ctx->key_len, 0,
+ sizeof(k_pad) - ctx->key_len);
+ for (i = 0; i < sizeof(k_pad); i++)
+ k_pad[i] ^= 0x5c;
+ sha256_init(&ctx->u.sha256);
+ sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
+ sha256_process(&ctx->u.sha256, mac, 32);
+ sha256_done(&ctx->u.sha256, mac);
+ break;
+#endif /* CONFIG_SHA256 */
+ default:
+ os_free(ctx);
+ return -1;
}
os_free(ctx);
diff --git a/src/crypto/dh_group5.c b/src/crypto/dh_group5.c
index 8c475bf..2a67d99 100644
--- a/src/crypto/dh_group5.c
+++ b/src/crypto/dh_group5.c
@@ -22,7 +22,7 @@
void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
{
*publ = dh_init(dh_groups_get(5), priv);
- if (*publ == 0)
+ if (*publ == NULL)
return NULL;
return (void *) 1;
}
diff --git a/src/crypto/fips_prf_internal.c b/src/crypto/fips_prf_internal.c
index a85cb14..1e0c453 100644
--- a/src/crypto/fips_prf_internal.c
+++ b/src/crypto/fips_prf_internal.c
@@ -28,13 +28,14 @@ int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
u8 *xpos = x;
u32 carry;
- if (seed_len > sizeof(xkey))
+ if (seed_len < sizeof(xkey))
+ os_memset(xkey + seed_len, 0, sizeof(xkey) - seed_len);
+ else
seed_len = sizeof(xkey);
/* FIPS 186-2 + change notice 1 */
os_memcpy(xkey, seed, seed_len);
- os_memset(xkey + seed_len, 0, 64 - seed_len);
t[0] = 0x67452301;
t[1] = 0xEFCDAB89;
t[2] = 0x98BADCFE;
diff --git a/src/crypto/md5-internal.c b/src/crypto/md5-internal.c
index f8692a9..137ad91 100644
--- a/src/crypto/md5-internal.c
+++ b/src/crypto/md5-internal.c
@@ -188,7 +188,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
MD5Transform(ctx->buf, (u32 *) ctx->in);
byteReverse((unsigned char *) ctx->buf, 4);
os_memcpy(digest, ctx->buf, 16);
- os_memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
+ os_memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
/* The four core functions - F1 is optimized somewhat */
diff --git a/src/crypto/ms_funcs.c b/src/crypto/ms_funcs.c
index dae15ab..c439ae9 100644
--- a/src/crypto/ms_funcs.c
+++ b/src/crypto/ms_funcs.c
@@ -19,6 +19,60 @@
#include "ms_funcs.h"
#include "crypto.h"
+/**
+ * utf8_to_ucs2 - Convert UTF-8 string to UCS-2 encoding
+ * @utf8_string: UTF-8 string (IN)
+ * @utf8_string_len: Length of utf8_string (IN)
+ * @ucs2_buffer: UCS-2 buffer (OUT)
+ * @ucs2_buffer_size: Length of UCS-2 buffer (IN)
+ * @ucs2_string_size: Number of 2-byte words in the resulting UCS-2 string
+ * Returns: 0 on success, -1 on failure
+ */
+static int utf8_to_ucs2(const u8 *utf8_string, size_t utf8_string_len,
+ u8 *ucs2_buffer, size_t ucs2_buffer_size,
+ size_t *ucs2_string_size)
+{
+ size_t i, j;
+
+ for (i = 0, j = 0; i < utf8_string_len; i++) {
+ u8 c = utf8_string[i];
+ if (j >= ucs2_buffer_size) {
+ /* input too long */
+ return -1;
+ }
+ if (c <= 0x7F) {
+ WPA_PUT_LE16(ucs2_buffer + j, c);
+ j += 2;
+ } else if (i == utf8_string_len - 1 ||
+ j >= ucs2_buffer_size - 1) {
+ /* incomplete surrogate */
+ return -1;
+ } else {
+ u8 c2 = utf8_string[++i];
+ if ((c & 0xE0) == 0xC0) {
+ /* two-byte encoding */
+ WPA_PUT_LE16(ucs2_buffer + j,
+ ((c & 0x1F) << 6) | (c2 & 0x3F));
+ j += 2;
+ } else if (i == utf8_string_len ||
+ j >= ucs2_buffer_size - 1) {
+ /* incomplete surrogate */
+ return -1;
+ } else {
+ /* three-byte encoding */
+ u8 c3 = utf8_string[++i];
+ WPA_PUT_LE16(ucs2_buffer + j,
+ ((c & 0xF) << 12) |
+ ((c2 & 0x3F) << 6) | (c3 & 0x3F));
+ }
+ }
+ }
+
+ if (ucs2_string_size)
+ *ucs2_string_size = j / 2;
+ return 0;
+}
+
/**
* challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2
@@ -53,7 +107,7 @@ static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
/**
* nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3
- * @password: 0-to-256-unicode-char Password (IN; ASCII)
+ * @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @password_hash: 16-octet PasswordHash (OUT)
* Returns: 0 on success, -1 on failure
@@ -62,18 +116,13 @@ int nt_password_hash(const u8 *password, size_t password_len,
u8 *password_hash)
{
u8 buf[512], *pos;
- size_t i, len;
+ size_t len, max_len;
- if (password_len > 256)
- password_len = 256;
-
- /* Convert password into unicode */
- for (i = 0; i < password_len; i++) {
- buf[2 * i] = password[i];
- buf[2 * i + 1] = 0;
- }
+ max_len = sizeof(buf);
+ if (utf8_to_ucs2(password, password_len, buf, max_len, &len) < 0)
+ return -1;
- len = password_len * 2;
+ len *= 2;
pos = buf;
return md4_vector(1, (const u8 **) &pos, &len, password_hash);
}
@@ -117,7 +166,7 @@ void challenge_response(const u8 *challenge, const u8 *password_hash,
* @peer_challenge: 16-octet PeerChallenge (IN)
* @username: 0-to-256-char UserName (IN)
* @username_len: Length of username
- * @password: 0-to-256-unicode-char Password (IN; ASCII)
+ * @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @response: 24-octet Response (OUT)
* Returns: 0 on success, -1 on failure
@@ -225,7 +274,7 @@ int generate_authenticator_response_pwhash(
/**
* generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
- * @password: 0-to-256-unicode-char Password (IN; ASCII)
+ * @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @nt_response: 24-octet NT-Response (IN)
* @peer_challenge: 16-octet PeerChallenge (IN)
@@ -254,7 +303,7 @@ int generate_authenticator_response(const u8 *password, size_t password_len,
/**
* nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5
* @challenge: 8-octet Challenge (IN)
- * @password: 0-to-256-unicode-char Password (IN; ASCII)
+ * @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @response: 24-octet Response (OUT)
* Returns: 0 on success, -1 on failure
@@ -375,7 +424,7 @@ int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
/**
* encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10
- * @password: 0-to-256-unicode-char Password (IN; ASCII)
+ * @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @password_hash: 16-octet PasswordHash (IN)
* @pw_block: 516-byte PwBlock (OUT)
@@ -385,18 +434,23 @@ int encrypt_pw_block_with_password_hash(
const u8 *password, size_t password_len,
const u8 *password_hash, u8 *pw_block)
{
- size_t i, offset;
+ size_t ucs2_len, offset;
u8 *pos;
- if (password_len > 256)
+ os_memset(pw_block, 0, PWBLOCK_LEN);
+
+ if (utf8_to_ucs2(password, password_len, pw_block, 512, &ucs2_len) < 0)
return -1;
- os_memset(pw_block, 0, PWBLOCK_LEN);
- offset = (256 - password_len) * 2;
- if (os_get_random(pw_block, offset) < 0)
+ if (ucs2_len > 256)
return -1;
- for (i = 0; i < password_len; i++)
- pw_block[offset + i * 2] = password[i];
+
+ offset = (256 - ucs2_len) * 2;
+ if (offset != 0) {
+ os_memmove(pw_block + offset, pw_block, ucs2_len * 2);
+ if (os_get_random(pw_block, offset) < 0)
+ return -1;
+ }
/*
* PasswordLength is 4 octets, but since the maximum password length is
* 256, only first two (in little endian byte order) can be non-zero.
@@ -410,9 +464,9 @@ int encrypt_pw_block_with_password_hash(
/**
* new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9
- * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII)
+ * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
* @new_password_len: Length of new_password
- * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
+ * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
* @old_password_len: Length of old_password
* @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT)
* Returns: 0 on success, -1 on failure
@@ -450,9 +504,9 @@ void nt_password_hash_encrypted_with_block(const u8 *password_hash,
/**
* old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12
- * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII)
+ * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
* @new_password_len: Length of new_password
- * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
+ * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
* @old_password_len: Length of old_password
* @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT)
* Returns: 0 on success, -1 on failure
diff --git a/src/crypto/random.c b/src/crypto/random.c
index f545917..a54e197 100644
--- a/src/crypto/random.c
+++ b/src/crypto/random.c
@@ -354,23 +354,31 @@ static void random_write_entropy(void)
char buf[RANDOM_ENTROPY_SIZE];
FILE *f;
u8 opr;
+ int fail = 0;
if (!random_entropy_file)
return;
- random_get_bytes(buf, RANDOM_ENTROPY_SIZE);
+ if (random_get_bytes(buf, RANDOM_ENTROPY_SIZE) < 0)
+ return;
f = fopen(random_entropy_file, "wb");
if (f == NULL) {
- wpa_printf(MSG_ERROR, "random: Could not write %s",
- random_entropy_file);
+ wpa_printf(MSG_ERROR, "random: Could not open entropy file %s "
+ "for writing", random_entropy_file);
return;
}
opr = own_pool_ready > 0xff ? 0xff : own_pool_ready;
- fwrite(&opr, 1, 1, f);
- fwrite(buf, RANDOM_ENTROPY_SIZE, 1, f);
+ if (fwrite(&opr, 1, 1, f) != 1 ||
+ fwrite(buf, RANDOM_ENTROPY_SIZE, 1, f) != 1)
+ fail = 1;
fclose(f);
+ if (fail) {
+ wpa_printf(MSG_ERROR, "random: Could not write entropy data "
+ "to %s", random_entropy_file);
+ return;
+ }
wpa_printf(MSG_DEBUG, "random: Updated entropy file %s "
"(own_pool_ready=%u)",
diff --git a/src/crypto/sha1-pbkdf2.c b/src/crypto/sha1-pbkdf2.c
index 11323de..9dac977 100644
--- a/src/crypto/sha1-pbkdf2.c
+++ b/src/crypto/sha1-pbkdf2.c
@@ -16,8 +16,6 @@
#include "common.h"
#include "sha1.h"
-#include "md5.h"
-#include "crypto.h"
static int pbkdf2_sha1_f(const char *passphrase, const char *ssid,
size_t ssid_len, int iterations, unsigned int count,
diff --git a/src/crypto/sha1-tlsprf.c b/src/crypto/sha1-tlsprf.c
index 2c8c029..f98fd65 100644
--- a/src/crypto/sha1-tlsprf.c
+++ b/src/crypto/sha1-tlsprf.c
@@ -17,11 +17,10 @@
#include "common.h"
#include "sha1.h"
#include "md5.h"
-#include "crypto.h"
/**
- * tls_prf - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246)
+ * tls_prf_sha1_md5 - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246)
* @secret: Key for PRF
* @secret_len: Length of the key in bytes
* @label: A unique label for each purpose of the PRF
@@ -34,8 +33,8 @@
* This function is used to derive new, cryptographically separate keys from a
* given key in TLS. This PRF is defined in RFC 2246, Chapter 5.
*/
-int tls_prf(const u8 *secret, size_t secret_len, const char *label,
- const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
+int tls_prf_sha1_md5(const u8 *secret, size_t secret_len, const char *label,
+ const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
{
size_t L_S1, L_S2, i;
const u8 *S1, *S2;
diff --git a/src/crypto/sha1.h b/src/crypto/sha1.h
index c1a6233..f0c1a5f 100644
--- a/src/crypto/sha1.h
+++ b/src/crypto/sha1.h
@@ -25,9 +25,9 @@ int sha1_prf(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
int sha1_t_prf(const u8 *key, size_t key_len, const char *label,
const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len);
-int __must_check tls_prf(const u8 *secret, size_t secret_len,
- const char *label, const u8 *seed, size_t seed_len,
- u8 *out, size_t outlen);
+int __must_check tls_prf_sha1_md5(const u8 *secret, size_t secret_len,
+ const char *label, const u8 *seed,
+ size_t seed_len, u8 *out, size_t outlen);
int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
int iterations, u8 *buf, size_t buflen);
#endif /* SHA1_H */
diff --git a/src/crypto/sha256-internal.c b/src/crypto/sha256-internal.c
index b061373..ef5751d 100644
--- a/src/crypto/sha256-internal.c
+++ b/src/crypto/sha256-internal.c
@@ -1,6 +1,6 @@
/*
* SHA-256 hash implementation and interface functions
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2011, 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
@@ -16,19 +16,9 @@
#include "common.h"
#include "sha256.h"
+#include "sha256_i.h"
#include "crypto.h"
-struct sha256_state {
- u64 length;
- u32 state[8], curlen;
- u8 buf[64];
-};
-
-static void sha256_init(struct sha256_state *md);
-static int sha256_process(struct sha256_state *md, const unsigned char *in,
- unsigned long inlen);
-static int sha256_done(struct sha256_state *md, unsigned char *out);
-
/**
* sha256_vector - SHA256 hash for data vector
@@ -137,7 +127,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf)
/* Initialize the hash state */
-static void sha256_init(struct sha256_state *md)
+void sha256_init(struct sha256_state *md)
{
md->curlen = 0;
md->length = 0;
@@ -158,32 +148,31 @@ static void sha256_init(struct sha256_state *md)
@param inlen The length of the data (octets)
@return CRYPT_OK if successful
*/
-static int sha256_process(struct sha256_state *md, const unsigned char *in,
- unsigned long inlen)
+int sha256_process(struct sha256_state *md, const unsigned char *in,
+ unsigned long inlen)
{
unsigned long n;
-#define block_size 64
- if (md->curlen > sizeof(md->buf))
+ if (md->curlen >= sizeof(md->buf))
return -1;
while (inlen > 0) {
- if (md->curlen == 0 && inlen >= block_size) {
+ if (md->curlen == 0 && inlen >= SHA256_BLOCK_SIZE) {
if (sha256_compress(md, (unsigned char *) in) < 0)
return -1;
- md->length += block_size * 8;
- in += block_size;
- inlen -= block_size;
+ md->length += SHA256_BLOCK_SIZE * 8;
+ in += SHA256_BLOCK_SIZE;
+ inlen -= SHA256_BLOCK_SIZE;
} else {
- n = MIN(inlen, (block_size - md->curlen));
+ n = MIN(inlen, (SHA256_BLOCK_SIZE - md->curlen));
os_memcpy(md->buf + md->curlen, in, n);
md->curlen += n;
in += n;
inlen -= n;
- if (md->curlen == block_size) {
+ if (md->curlen == SHA256_BLOCK_SIZE) {
if (sha256_compress(md, md->buf) < 0)
return -1;
- md->length += 8 * block_size;
+ md->length += 8 * SHA256_BLOCK_SIZE;
md->curlen = 0;
}
}
@@ -199,7 +188,7 @@ static int sha256_process(struct sha256_state *md, const unsigned char *in,
@param out [out] The destination of the hash (32 bytes)
@return CRYPT_OK if successful
*/
-static int sha256_done(struct sha256_state *md, unsigned char *out)
+int sha256_done(struct sha256_state *md, unsigned char *out)
{
int i;
@@ -217,14 +206,14 @@ static int sha256_done(struct sha256_state *md, unsigned char *out)
* encoding like normal.
*/
if (md->curlen > 56) {
- while (md->curlen < 64) {
+ while (md->curlen < SHA256_BLOCK_SIZE) {
md->buf[md->curlen++] = (unsigned char) 0;
}
sha256_compress(md, md->buf);
md->curlen = 0;
}
- /* pad upto 56 bytes of zeroes */
+ /* pad up to 56 bytes of zeroes */
while (md->curlen < 56) {
md->buf[md->curlen++] = (unsigned char) 0;
}
diff --git a/src/crypto/sha256-tlsprf.c b/src/crypto/sha256-tlsprf.c
new file mode 100644
index 0000000..6763c96
--- /dev/null
+++ b/src/crypto/sha256-tlsprf.c
@@ -0,0 +1,72 @@
+/*
+ * TLS PRF P_SHA256
+ * Copyright (c) 2011, 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 "common.h"
+#include "sha256.h"
+
+
+/**
+ * tls_prf_sha256 - Pseudo-Random Function for TLS v1.2 (P_SHA256, RFC 5246)
+ * @secret: Key for PRF
+ * @secret_len: Length of the key in bytes
+ * @label: A unique label for each purpose of the PRF
+ * @seed: Seed value to bind into the key
+ * @seed_len: Length of the seed
+ * @out: Buffer for the generated pseudo-random key
+ * @outlen: Number of bytes of key to generate
+ * Returns: 0 on success, -1 on failure.
+ *
+ * This function is used to derive new, cryptographically separate keys from a
+ * given key in TLS. This PRF is defined in RFC 2246, Chapter 5.
+ */
+void tls_prf_sha256(const u8 *secret, size_t secret_len, const char *label,
+ const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
+{
+ size_t clen;
+ u8 A[SHA256_MAC_LEN];
+ u8 P[SHA256_MAC_LEN];
+ size_t pos;
+ const unsigned char *addr[3];
+ size_t len[3];
+
+ addr[0] = A;
+ len[0] = SHA256_MAC_LEN;
+ addr[1] = (unsigned char *) label;
+ len[1] = os_strlen(label);
+ addr[2] = seed;
+ len[2] = seed_len;
+
+ /*
+ * RFC 5246, Chapter 5
+ * A(0) = seed, A(i) = HMAC(secret, A(i-1))
+ * P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + ..
+ * PRF(secret, label, seed) = P_SHA256(secret, label + seed)
+ */
+
+ hmac_sha256_vector(secret, secret_len, 2, &addr[1], &len[1], A);
+
+ pos = 0;
+ while (pos < outlen) {
+ hmac_sha256_vector(secret, secret_len, 3, addr, len, P);
+ hmac_sha256(secret, secret_len, A, SHA256_MAC_LEN, A);
+
+ clen = outlen - pos;
+ if (clen > SHA256_MAC_LEN)
+ clen = SHA256_MAC_LEN;
+ os_memcpy(out + pos, P, clen);
+ pos += clen;
+ }
+}
diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h
index dc597f0..b1ce6af 100644
--- a/src/crypto/sha256.h
+++ b/src/crypto/sha256.h
@@ -1,6 +1,6 @@
/*
* SHA256 hash implementation and interface functions
- * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2011, 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
@@ -23,5 +23,8 @@ void hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
size_t data_len, u8 *mac);
void sha256_prf(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
+void tls_prf_sha256(const u8 *secret, size_t secret_len,
+ const char *label, const u8 *seed, size_t seed_len,
+ u8 *out, size_t outlen);
#endif /* SHA256_H */
diff --git a/src/crypto/sha256_i.h b/src/crypto/sha256_i.h
new file mode 100644
index 0000000..20ae488
--- /dev/null
+++ b/src/crypto/sha256_i.h
@@ -0,0 +1,31 @@
+/*
+ * SHA-256 internal definitions
+ * Copyright (c) 2003-2011, 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.
+ */
+
+#ifndef SHA256_I_H
+#define SHA256_I_H
+
+#define SHA256_BLOCK_SIZE 64
+
+struct sha256_state {
+ u64 length;
+ u32 state[8], curlen;
+ u8 buf[SHA256_BLOCK_SIZE];
+};
+
+void sha256_init(struct sha256_state *md);
+int sha256_process(struct sha256_state *md, const unsigned char *in,
+ unsigned long inlen);
+int sha256_done(struct sha256_state *md, unsigned char *out);
+
+#endif /* SHA256_I_H */
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index 0928b5b..d9d88cb 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -24,8 +24,6 @@ struct tls_keys {
size_t client_random_len;
const u8 *server_random;
size_t server_random_len;
- const u8 *inner_secret; /* TLS/IA inner secret */
- size_t inner_secret_len;
};
enum tls_event {
@@ -72,6 +70,7 @@ struct tls_config {
const char *pkcs11_engine_path;
const char *pkcs11_module_path;
int fips_mode;
+ int cert_in_cb;
void (*event_cb)(void *ctx, enum tls_event ev,
union tls_event_data *data);
@@ -114,7 +113,6 @@ struct tls_config {
* specific for now)
* @cert_id: the certificate's id when using engine
* @ca_cert_id: the CA certificate's id when using engine
- * @tls_ia: Whether to enable TLS/IA (for EAP-TTLSv1)
* @flags: Parameter options (TLS_CONN_*)
*
* TLS connection parameters to be configured with tls_connection_set_params()
@@ -142,7 +140,6 @@ struct tls_connection_params {
const char *dh_file;
const u8 *dh_blob;
size_t dh_blob_len;
- int tls_ia;
/* OpenSSL specific variables */
int engine;
@@ -282,20 +279,6 @@ int __must_check tls_connection_set_verify(void *tls_ctx,
int verify_peer);
/**
- * tls_connection_set_ia - Set TLS/IA parameters
- * @tls_ctx: TLS context data from tls_init()
- * @conn: Connection context data from tls_connection_init()
- * @tls_ia: 1 = enable TLS/IA
- * Returns: 0 on success, -1 on failure
- *
- * This function is used to configure TLS/IA in server mode where
- * tls_connection_set_params() is not used.
- */
-int __must_check tls_connection_set_ia(void *tls_ctx,
- struct tls_connection *conn,
- int tls_ia);
-
-/**
* tls_connection_get_keys - Get master key and random data from TLS connection
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
@@ -322,7 +305,7 @@ int __must_check tls_connection_get_keys(void *tls_ctx,
* not exported from the TLS library, tls_connection_prf() is required so that
* further keying material can be derived from the master secret. If not
* implemented, the function will still need to be defined, but it can just
- * return -1. Example implementation of this function is in tls_prf() function
+ * return -1. Example implementation of this function is in tls_prf_sha1_md5()
* when it is called with seed set to client_random|server_random (or
* server_random|client_random).
*/
@@ -364,6 +347,12 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
const struct wpabuf *in_data,
struct wpabuf **appl_data);
+struct wpabuf * tls_connection_handshake2(void *tls_ctx,
+ struct tls_connection *conn,
+ const struct wpabuf *in_data,
+ struct wpabuf **appl_data,
+ int *more_data_needed);
+
/**
* tls_connection_server_handshake - Process TLS handshake (server side)
* @tls_ctx: TLS context data from tls_init()
@@ -409,6 +398,11 @@ struct wpabuf * tls_connection_decrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data);
+struct wpabuf * tls_connection_decrypt2(void *tls_ctx,
+ struct tls_connection *conn,
+ const struct wpabuf *in_data,
+ int *more_data_needed);
+
/**
* tls_connection_resumed - Was session resumption used
* @tls_ctx: TLS context data from tls_init()
@@ -514,7 +508,6 @@ int tls_connection_get_write_alerts(void *tls_ctx,
int tls_connection_get_keyblock_size(void *tls_ctx,
struct tls_connection *conn);
-#define TLS_CAPABILITY_IA 0x0001 /* TLS Inner Application (TLS/IA) */
/**
* tls_capabilities - Get supported TLS capabilities
* @tls_ctx: TLS context data from tls_init()
@@ -522,42 +515,6 @@ int tls_connection_get_keyblock_size(void *tls_ctx,
*/
unsigned int tls_capabilities(void *tls_ctx);
-/**
- * tls_connection_ia_send_phase_finished - Send a TLS/IA PhaseFinished message
- * @tls_ctx: TLS context data from tls_init()
- * @conn: Connection context data from tls_connection_init()
- * @final: 1 = FinalPhaseFinished, 0 = IntermediatePhaseFinished
- * Returns: Encrypted TLS/IA data, %NULL on failure
- *
- * This function is used to send the TLS/IA end phase message, e.g., when the
- * EAP server completes EAP-TTLSv1.
- */
-struct wpabuf * tls_connection_ia_send_phase_finished(
- void *tls_ctx, struct tls_connection *conn, int final);
-
-/**
- * tls_connection_ia_final_phase_finished - Has final phase been completed
- * @tls_ctx: TLS context data from tls_init()
- * @conn: Connection context data from tls_connection_init()
- * Returns: 1 if valid FinalPhaseFinished has been received, 0 if not, or -1
- * on failure
- */
-int __must_check tls_connection_ia_final_phase_finished(
- void *tls_ctx, struct tls_connection *conn);
-
-/**
- * tls_connection_ia_permute_inner_secret - Permute TLS/IA inner secret
- * @tls_ctx: TLS context data from tls_init()
- * @conn: Connection context data from tls_connection_init()
- * @key: Session key material (session_key vectors with 2-octet length), or
- * %NULL if no session key was generating in the current phase
- * @key_len: Length of session key material
- * Returns: 0 on success, -1 on failure
- */
-int __must_check tls_connection_ia_permute_inner_secret(
- void *tls_ctx, struct tls_connection *conn,
- const u8 *key, size_t key_len);
-
typedef int (*tls_session_ticket_cb)
(void *ctx, const u8 *ticket, size_t len, const u8 *client_random,
const u8 *server_random, u8 *master_secret);
diff --git a/src/crypto/tls_gnutls.c b/src/crypto/tls_gnutls.c
index c3a7358..afa5268 100644
--- a/src/crypto/tls_gnutls.c
+++ b/src/crypto/tls_gnutls.c
@@ -1,6 +1,6 @@
/*
* SSL/TLS interface functions for GnuTLS
- * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2011, 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
@@ -19,28 +19,12 @@
#include <gnutls/pkcs12.h>
#endif /* PKCS12_FUNCS */
-#ifdef CONFIG_GNUTLS_EXTRA
-#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
-#define GNUTLS_IA
-#include <gnutls/extra.h>
-#if LIBGNUTLS_VERSION_NUMBER == 0x010302
-/* This function is not included in the current gnutls/extra.h even though it
- * should be, so define it here as a workaround for the time being. */
-int gnutls_ia_verify_endphase(gnutls_session_t session, char *checksum);
-#endif /* LIBGNUTLS_VERSION_NUMBER == 0x010302 */
-#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
-#endif /* CONFIG_GNUTLS_EXTRA */
-
#include "common.h"
#include "tls.h"
-#ifndef TLS_RANDOM_SIZE
-#define TLS_RANDOM_SIZE 32
-#endif
-#ifndef TLS_MASTER_SIZE
-#define TLS_MASTER_SIZE 48
-#endif
+#define WPA_TLS_RANDOM_SIZE 32
+#define WPA_TLS_MASTER_SIZE 48
#if LIBGNUTLS_VERSION_NUMBER < 0x010302
@@ -77,9 +61,9 @@ typedef struct {
gnutls_mac_algorithm_t write_mac_algorithm;
gnutls_compression_method_t write_compression_algorithm;
cipher_suite_st current_cipher_suite;
- opaque master_secret[TLS_MASTER_SIZE];
- opaque client_random[TLS_RANDOM_SIZE];
- opaque server_random[TLS_RANDOM_SIZE];
+ opaque master_secret[WPA_TLS_MASTER_SIZE];
+ opaque client_random[WPA_TLS_RANDOM_SIZE];
+ opaque server_random[WPA_TLS_RANDOM_SIZE];
/* followed by stuff we are not interested in */
} security_parameters_st;
@@ -118,21 +102,6 @@ struct tls_connection {
int params_set;
gnutls_certificate_credentials_t xcred;
-
- int tls_ia;
- int final_phase_finished;
-
-#ifdef GNUTLS_IA
- gnutls_ia_server_credentials_t iacred_srv;
- gnutls_ia_client_credentials_t iacred_cli;
-
- /* Session keys generated in the current phase for inner secret
- * permutation before generating/verifying PhaseFinished. */
- u8 *session_keys;
- size_t session_keys_len;
-
- u8 inner_secret[TLS_MASTER_SIZE];
-#endif /* GNUTLS_IA */
};
@@ -285,8 +254,12 @@ static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf,
static int tls_gnutls_init_session(struct tls_global *global,
struct tls_connection *conn)
{
+#if LIBGNUTLS_VERSION_NUMBER >= 0x020200
+ const char *err;
+#else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */
const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
const int protos[2] = { GNUTLS_TLS1, 0 };
+#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */
int ret;
ret = gnutls_init(&conn->session,
@@ -301,6 +274,15 @@ static int tls_gnutls_init_session(struct tls_global *global,
if (ret < 0)
goto fail;
+#if LIBGNUTLS_VERSION_NUMBER >= 0x020200
+ ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0",
+ &err);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at "
+ "'%s'", err);
+ goto fail;
+ }
+#else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */
ret = gnutls_certificate_type_set_priority(conn->session, cert_types);
if (ret < 0)
goto fail;
@@ -308,6 +290,7 @@ static int tls_gnutls_init_session(struct tls_global *global,
ret = gnutls_protocol_set_priority(conn->session, protos);
if (ret < 0)
goto fail;
+#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */
gnutls_transport_set_pull_function(conn->session, tls_pull_func);
gnutls_transport_set_push_function(conn->session, tls_push_func);
@@ -364,17 +347,6 @@ void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
if (conn == NULL)
return;
-#ifdef GNUTLS_IA
- if (conn->iacred_srv)
- gnutls_ia_free_server_credentials(conn->iacred_srv);
- if (conn->iacred_cli)
- gnutls_ia_free_client_credentials(conn->iacred_cli);
- if (conn->session_keys) {
- os_memset(conn->session_keys, 0, conn->session_keys_len);
- os_free(conn->session_keys);
- }
-#endif /* GNUTLS_IA */
-
gnutls_certificate_free_credentials(conn->xcred);
gnutls_deinit(conn->session);
os_free(conn->pre_shared_secret);
@@ -407,14 +379,6 @@ int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
wpabuf_free(conn->push_buf);
conn->push_buf = NULL;
conn->established = 0;
- conn->final_phase_finished = 0;
-#ifdef GNUTLS_IA
- if (conn->session_keys) {
- os_memset(conn->session_keys, 0, conn->session_keys_len);
- os_free(conn->session_keys);
- }
- conn->session_keys_len = 0;
-#endif /* GNUTLS_IA */
gnutls_deinit(conn->session);
if (tls_gnutls_init_session(global, conn)) {
@@ -597,11 +561,13 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
}
+#if LIBGNUTLS_VERSION_NUMBER >= 0x020800
if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
gnutls_certificate_set_verify_flags(
conn->xcred,
GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
}
+#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
}
if (params->client_cert && params->private_key) {
@@ -646,7 +612,6 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
}
}
- conn->tls_ia = params->tls_ia;
conn->params_set = 1;
ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
@@ -656,28 +621,6 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
gnutls_strerror(ret));
}
-#ifdef GNUTLS_IA
- if (conn->iacred_cli)
- gnutls_ia_free_client_credentials(conn->iacred_cli);
-
- ret = gnutls_ia_allocate_client_credentials(&conn->iacred_cli);
- if (ret) {
- wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
- gnutls_strerror(ret));
- return -1;
- }
-
- ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
- conn->iacred_cli);
- if (ret) {
- wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
- gnutls_strerror(ret));
- gnutls_ia_free_client_credentials(conn->iacred_cli);
- conn->iacred_cli = NULL;
- return -1;
- }
-#endif /* GNUTLS_IE */
-
return ret;
}
@@ -729,11 +672,13 @@ int tls_global_set_params(void *tls_ctx,
GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
}
+#if LIBGNUTLS_VERSION_NUMBER >= 0x020800
if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
gnutls_certificate_set_verify_flags(
global->xcred,
GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
}
+#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
}
if (params->client_cert && params->private_key) {
@@ -822,10 +767,11 @@ int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
os_memset(keys, 0, sizeof(*keys));
+#if LIBGNUTLS_VERSION_NUMBER < 0x020c00
#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
sec = &conn->session->security_parameters;
keys->master_key = sec->master_secret;
- keys->master_key_len = TLS_MASTER_SIZE;
+ keys->master_key_len = WPA_TLS_MASTER_SIZE;
keys->client_random = sec->client_random;
keys->server_random = sec->server_random;
#else /* GNUTLS_INTERNAL_STRUCTURE_HACK */
@@ -835,16 +781,12 @@ int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
(u8 *) gnutls_session_get_server_random(conn->session);
/* No access to master_secret */
#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
+#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020c00 */
-#ifdef GNUTLS_IA
- gnutls_ia_extract_inner_secret(conn->session,
- (char *) conn->inner_secret);
- keys->inner_secret = conn->inner_secret;
- keys->inner_secret_len = TLS_MASTER_SIZE;
-#endif /* GNUTLS_IA */
-
- keys->client_random_len = TLS_RANDOM_SIZE;
- keys->server_random_len = TLS_RANDOM_SIZE;
+#if LIBGNUTLS_VERSION_NUMBER < 0x020c00
+ keys->client_random_len = WPA_TLS_RANDOM_SIZE;
+ keys->server_random_len = WPA_TLS_RANDOM_SIZE;
+#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020c00 */
return 0;
}
@@ -883,11 +825,13 @@ static int tls_connection_verify_peer(struct tls_connection *conn,
if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
+ *err = GNUTLS_A_INTERNAL_ERROR;
if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
"algorithm");
*err = GNUTLS_A_INSUFFICIENT_SECURITY;
}
+#if LIBGNUTLS_VERSION_NUMBER >= 0x020800
if (status & GNUTLS_CERT_NOT_ACTIVATED) {
wpa_printf(MSG_INFO, "TLS: Certificate not yet "
"activated");
@@ -897,6 +841,7 @@ static int tls_connection_verify_peer(struct tls_connection *conn,
wpa_printf(MSG_INFO, "TLS: Certificate expired");
*err = GNUTLS_A_CERTIFICATE_EXPIRED;
}
+#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
return -1;
}
@@ -988,7 +933,7 @@ static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
wpabuf_size(ad));
wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
if (res < 0) {
- wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
+ wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
"(%s)", __func__, (int) res,
gnutls_strerror(res));
wpabuf_free(ad);
@@ -1062,20 +1007,7 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
goto out;
}
-#ifdef CONFIG_GNUTLS_EXTRA
- if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) {
- wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation");
- conn->failed++;
- return NULL;
- }
-#endif /* CONFIG_GNUTLS_EXTRA */
-
- if (conn->tls_ia)
- wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake");
- else {
- wpa_printf(MSG_DEBUG, "TLS: Handshake completed "
- "successfully");
- }
+ wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
conn->established = 1;
if (conn->push_buf == NULL) {
/* Need to return something to get final TLS ACK. */
@@ -1122,12 +1054,6 @@ struct wpabuf * tls_connection_encrypt(void *tls_ctx,
ssize_t res;
struct wpabuf *buf;
-#ifdef GNUTLS_IA
- if (conn->tls_ia)
- res = gnutls_ia_send(conn->session, wpabuf_head(in_data),
- wpabuf_len(in_data));
- else
-#endif /* GNUTLS_IA */
res = gnutls_record_send(conn->session, wpabuf_head(in_data),
wpabuf_len(in_data));
if (res < 0) {
@@ -1170,65 +1096,6 @@ struct wpabuf * tls_connection_decrypt(void *tls_ctx,
if (out == NULL)
return NULL;
-#ifdef GNUTLS_IA
- if (conn->tls_ia) {
- res = gnutls_ia_recv(conn->session, wpabuf_mhead(out),
- wpabuf_size(out));
- if (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
- res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) {
- int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
- wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished",
- __func__, final ? "Final" : "Intermediate");
-
- res = gnutls_ia_permute_inner_secret(
- conn->session, conn->session_keys_len,
- (char *) conn->session_keys);
- if (conn->session_keys) {
- os_memset(conn->session_keys, 0,
- conn->session_keys_len);
- os_free(conn->session_keys);
- }
- conn->session_keys = NULL;
- conn->session_keys_len = 0;
- if (res) {
- wpa_printf(MSG_DEBUG, "%s: Failed to permute "
- "inner secret: %s",
- __func__, gnutls_strerror(res));
- wpabuf_free(out);
- return NULL;
- }
-
- res = gnutls_ia_verify_endphase(conn->session,
- wpabuf_head(out));
- if (res == 0) {
- wpa_printf(MSG_DEBUG, "%s: Correct endphase "
- "checksum", __func__);
- } else {
- wpa_printf(MSG_INFO, "%s: Endphase "
- "verification failed: %s",
- __func__, gnutls_strerror(res));
- wpabuf_free(out);
- return NULL;
- }
-
- if (final)
- conn->final_phase_finished = 1;
-
- return out;
- }
-
- if (res < 0) {
- wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
- "(%s)", __func__, (int) res,
- gnutls_strerror(res));
- wpabuf_free(out);
- return NULL;
- }
- wpabuf_put(out, res);
- return out;
- }
-#endif /* GNUTLS_IA */
-
res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
wpabuf_size(out));
if (res < 0) {
@@ -1319,133 +1186,7 @@ int tls_connection_get_keyblock_size(void *tls_ctx,
unsigned int tls_capabilities(void *tls_ctx)
{
- unsigned int capa = 0;
-
-#ifdef GNUTLS_IA
- capa |= TLS_CAPABILITY_IA;
-#endif /* GNUTLS_IA */
-
- return capa;
-}
-
-
-int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
- int tls_ia)
-{
-#ifdef GNUTLS_IA
- int ret;
-
- if (conn == NULL)
- return -1;
-
- conn->tls_ia = tls_ia;
- if (!tls_ia)
- return 0;
-
- ret = gnutls_ia_allocate_server_credentials(&conn->iacred_srv);
- if (ret) {
- wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
- gnutls_strerror(ret));
- return -1;
- }
-
- ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
- conn->iacred_srv);
- if (ret) {
- wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
- gnutls_strerror(ret));
- gnutls_ia_free_server_credentials(conn->iacred_srv);
- conn->iacred_srv = NULL;
- return -1;
- }
-
- return 0;
-#else /* GNUTLS_IA */
- return -1;
-#endif /* GNUTLS_IA */
-}
-
-
-struct wpabuf * tls_connection_ia_send_phase_finished(
- void *tls_ctx, struct tls_connection *conn, int final)
-{
-#ifdef GNUTLS_IA
- int ret;
- struct wpabuf *buf;
-
- if (conn == NULL || conn->session == NULL || !conn->tls_ia)
- return NULL;
-
- ret = gnutls_ia_permute_inner_secret(conn->session,
- conn->session_keys_len,
- (char *) conn->session_keys);
- if (conn->session_keys) {
- os_memset(conn->session_keys, 0, conn->session_keys_len);
- os_free(conn->session_keys);
- }
- conn->session_keys = NULL;
- conn->session_keys_len = 0;
- if (ret) {
- wpa_printf(MSG_DEBUG, "%s: Failed to permute inner secret: %s",
- __func__, gnutls_strerror(ret));
- return NULL;
- }
-
- ret = gnutls_ia_endphase_send(conn->session, final);
- if (ret) {
- wpa_printf(MSG_DEBUG, "%s: Failed to send endphase: %s",
- __func__, gnutls_strerror(ret));
- return NULL;
- }
-
- buf = conn->push_buf;
- conn->push_buf = NULL;
- return buf;
-#else /* GNUTLS_IA */
- return NULL;
-#endif /* GNUTLS_IA */
-}
-
-
-int tls_connection_ia_final_phase_finished(void *tls_ctx,
- struct tls_connection *conn)
-{
- if (conn == NULL)
- return -1;
-
- return conn->final_phase_finished;
-}
-
-
-int tls_connection_ia_permute_inner_secret(void *tls_ctx,
- struct tls_connection *conn,
- const u8 *key, size_t key_len)
-{
-#ifdef GNUTLS_IA
- if (conn == NULL || !conn->tls_ia)
- return -1;
-
- if (conn->session_keys) {
- os_memset(conn->session_keys, 0, conn->session_keys_len);
- os_free(conn->session_keys);
- }
- conn->session_keys_len = 0;
-
- if (key) {
- conn->session_keys = os_malloc(key_len);
- if (conn->session_keys == NULL)
- return -1;
- os_memcpy(conn->session_keys, key, key_len);
- conn->session_keys_len = key_len;
- } else {
- conn->session_keys = NULL;
- conn->session_keys_len = 0;
- }
-
return 0;
-#else /* GNUTLS_IA */
- return -1;
-#endif /* GNUTLS_IA */
}
diff --git a/src/crypto/tls_internal.c b/src/crypto/tls_internal.c
index cc165f6..f5e31d9 100644
--- a/src/crypto/tls_internal.c
+++ b/src/crypto/tls_internal.c
@@ -290,13 +290,6 @@ int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
}
-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)
{
@@ -339,6 +332,17 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
+ return tls_connection_handshake2(tls_ctx, conn, in_data, appl_data,
+ NULL);
+}
+
+
+struct wpabuf * tls_connection_handshake2(void *tls_ctx,
+ struct tls_connection *conn,
+ const struct wpabuf *in_data,
+ struct wpabuf **appl_data,
+ int *need_more_data)
+{
#ifdef CONFIG_TLS_INTERNAL_CLIENT
u8 *res, *ad;
size_t res_len, ad_len;
@@ -351,7 +355,7 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
res = tlsv1_client_handshake(conn->client,
in_data ? wpabuf_head(in_data) : NULL,
in_data ? wpabuf_len(in_data) : 0,
- &res_len, &ad, &ad_len);
+ &res_len, &ad, &ad_len, need_more_data);
if (res == NULL)
return NULL;
out = wpabuf_alloc_ext_data(res, res_len);
@@ -462,23 +466,23 @@ struct wpabuf * tls_connection_decrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
+ return tls_connection_decrypt2(tls_ctx, conn, in_data, NULL);
+}
+
+
+struct wpabuf * tls_connection_decrypt2(void *tls_ctx,
+ struct tls_connection *conn,
+ const struct wpabuf *in_data,
+ int *need_more_data)
+{
+ if (need_more_data)
+ *need_more_data = 0;
+
#ifdef CONFIG_TLS_INTERNAL_CLIENT
if (conn->client) {
- struct wpabuf *buf;
- int res;
- buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
- if (buf == NULL)
- return NULL;
- res = tlsv1_client_decrypt(conn->client, wpabuf_head(in_data),
- wpabuf_len(in_data),
- wpabuf_mhead(buf),
- wpabuf_size(buf));
- if (res < 0) {
- wpabuf_free(buf);
- return NULL;
- }
- wpabuf_put(buf, res);
- return buf;
+ return tlsv1_client_decrypt(conn->client, wpabuf_head(in_data),
+ wpabuf_len(in_data),
+ need_more_data);
}
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
#ifdef CONFIG_TLS_INTERNAL_SERVER
@@ -611,28 +615,6 @@ unsigned int tls_capabilities(void *tls_ctx)
}
-struct wpabuf * tls_connection_ia_send_phase_finished(
- void *tls_ctx, struct tls_connection *conn, int final)
-{
- return NULL;
-}
-
-
-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,
diff --git a/src/crypto/tls_none.c b/src/crypto/tls_none.c
index 0c836bb..927edf5 100644
--- a/src/crypto/tls_none.c
+++ b/src/crypto/tls_none.c
@@ -84,13 +84,6 @@ int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
}
-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)
{
@@ -205,25 +198,3 @@ unsigned int tls_capabilities(void *tls_ctx)
{
return 0;
}
-
-
-struct wpabuf * tls_connection_ia_send_phase_finished(
- void *tls_ctx, struct tls_connection *conn, int final)
-{
- return NULL;
-}
-
-
-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;
-}
diff --git a/src/crypto/tls_nss.c b/src/crypto/tls_nss.c
index ad834b6..09a1e73 100644
--- a/src/crypto/tls_nss.c
+++ b/src/crypto/tls_nss.c
@@ -419,13 +419,6 @@ int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
}
-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)
{
@@ -649,28 +642,6 @@ unsigned int tls_capabilities(void *tls_ctx)
}
-struct wpabuf * tls_connection_ia_send_phase_finished(
- void *tls_ctx, struct tls_connection *conn, int final)
-{
- return NULL;
-}
-
-
-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,
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 14ff87e..8374096 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -59,6 +59,7 @@ struct tls_global {
void (*event_cb)(void *ctx, enum tls_event ev,
union tls_event_data *data);
void *cb_ctx;
+ int cert_in_cb;
};
static struct tls_global *tls_global = NULL;
@@ -694,6 +695,7 @@ void * tls_init(const struct tls_config *conf)
if (conf) {
tls_global->event_cb = conf->event_cb;
tls_global->cb_ctx = conf->cb_ctx;
+ tls_global->cert_in_cb = conf->cert_in_cb;
}
#ifdef CONFIG_FIPS
@@ -1144,7 +1146,7 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
return;
os_memset(&ev, 0, sizeof(ev));
- if (conn->cert_probe) {
+ if (conn->cert_probe || tls_global->cert_in_cb) {
cert = get_x509_cert(err_cert);
ev.peer_cert.cert = cert;
}
@@ -1661,6 +1663,7 @@ static int tls_global_client_cert(SSL_CTX *ssl_ctx, const char *client_cert)
if (SSL_CTX_use_certificate_file(ssl_ctx, client_cert,
SSL_FILETYPE_ASN1) != 1 &&
+ SSL_CTX_use_certificate_chain_file(ssl_ctx, client_cert) != 1 &&
SSL_CTX_use_certificate_file(ssl_ctx, client_cert,
SSL_FILETYPE_PEM) != 1) {
tls_show_errors(MSG_INFO, __func__,
@@ -2809,35 +2812,6 @@ unsigned int tls_capabilities(void *tls_ctx)
}
-int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
- int tls_ia)
-{
- return -1;
-}
-
-
-struct wpabuf * tls_connection_ia_send_phase_finished(
- void *tls_ctx, struct tls_connection *conn, int final)
-{
- return NULL;
-}
-
-
-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;
-}
-
-
#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
/* Pre-shared secred requires a patch to openssl, so this function is
* commented out unless explicitly needed for EAP-FAST in order to be able to
diff --git a/src/crypto/tls_schannel.c b/src/crypto/tls_schannel.c
index 4a94e99..a33d24e 100644
--- a/src/crypto/tls_schannel.c
+++ b/src/crypto/tls_schannel.c
@@ -736,32 +736,3 @@ unsigned int tls_capabilities(void *tls_ctx)
{
return 0;
}
-
-
-int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
- int tls_ia)
-{
- return -1;
-}
-
-
-struct wpabuf * tls_connection_ia_send_phase_finished(
- void *tls_ctx, struct tls_connection *conn, int final);
-{
- return NULL;
-}
-
-
-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;
-}