diff options
Diffstat (limited to 'src/crypto')
-rw-r--r-- | src/crypto/Makefile | 3 | ||||
-rw-r--r-- | src/crypto/aes-internal-dec.c | 2 | ||||
-rw-r--r-- | src/crypto/aes-internal-enc.c | 2 | ||||
-rw-r--r-- | src/crypto/crypto.h | 3 | ||||
-rw-r--r-- | src/crypto/crypto_internal-rsa.c | 1 | ||||
-rw-r--r-- | src/crypto/crypto_internal.c | 84 | ||||
-rw-r--r-- | src/crypto/dh_group5.c | 2 | ||||
-rw-r--r-- | src/crypto/fips_prf_internal.c | 5 | ||||
-rw-r--r-- | src/crypto/md5-internal.c | 2 | ||||
-rw-r--r-- | src/crypto/ms_funcs.c | 106 | ||||
-rw-r--r-- | src/crypto/random.c | 18 | ||||
-rw-r--r-- | src/crypto/sha1-pbkdf2.c | 2 | ||||
-rw-r--r-- | src/crypto/sha1-tlsprf.c | 7 | ||||
-rw-r--r-- | src/crypto/sha1.h | 6 | ||||
-rw-r--r-- | src/crypto/sha256-internal.c | 43 | ||||
-rw-r--r-- | src/crypto/sha256-tlsprf.c | 72 | ||||
-rw-r--r-- | src/crypto/sha256.h | 5 | ||||
-rw-r--r-- | src/crypto/sha256_i.h | 31 | ||||
-rw-r--r-- | src/crypto/tls.h | 69 | ||||
-rw-r--r-- | src/crypto/tls_gnutls.c | 331 | ||||
-rw-r--r-- | src/crypto/tls_internal.c | 72 | ||||
-rw-r--r-- | src/crypto/tls_none.c | 29 | ||||
-rw-r--r-- | src/crypto/tls_nss.c | 29 | ||||
-rw-r--r-- | src/crypto/tls_openssl.c | 34 | ||||
-rw-r--r-- | src/crypto/tls_schannel.c | 29 |
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; -} |