diff options
Diffstat (limited to 'freebsd/contrib/wpa/src/crypto')
-rw-r--r-- | freebsd/contrib/wpa/src/crypto/aes-omac1.c | 3 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/crypto/crypto.h | 25 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/crypto/crypto_openssl.c | 403 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/crypto/ms_funcs.c | 2 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/crypto/sha256-internal.c | 3 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/crypto/sha256-prf.c | 26 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/crypto/sha256.h | 12 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/crypto/tls.h | 47 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/crypto/tls_internal.c | 64 |
9 files changed, 442 insertions, 143 deletions
diff --git a/freebsd/contrib/wpa/src/crypto/aes-omac1.c b/freebsd/contrib/wpa/src/crypto/aes-omac1.c index 7e62ef85..8ad5a356 100644 --- a/freebsd/contrib/wpa/src/crypto/aes-omac1.c +++ b/freebsd/contrib/wpa/src/crypto/aes-omac1.c @@ -50,6 +50,9 @@ int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *pos, *end; size_t i, e, left, total_len; + if (TEST_FAIL()) + return -1; + ctx = aes_encrypt_init(key, key_len); if (ctx == NULL) return -1; diff --git a/freebsd/contrib/wpa/src/crypto/crypto.h b/freebsd/contrib/wpa/src/crypto/crypto.h index 534c4bd7..bdc3ba6f 100644 --- a/freebsd/contrib/wpa/src/crypto/crypto.h +++ b/freebsd/contrib/wpa/src/crypto/crypto.h @@ -80,6 +80,28 @@ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); /** + * sha384_vector - SHA384 hash for data vector + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure + */ +int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac); + +/** + * sha512_vector - SHA512 hash for data vector + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure + */ +int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac); + +/** * des_encrypt - Encrypt one block with DES * @clear: 8 octets (in) * @key: 7 octets (in) (no parity bits included) @@ -135,7 +157,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_SHA256, CRYPTO_HASH_ALG_HMAC_SHA256 + CRYPTO_HASH_ALG_SHA256, CRYPTO_HASH_ALG_HMAC_SHA256, + CRYPTO_HASH_ALG_SHA384, CRYPTO_HASH_ALG_SHA512 }; struct crypto_hash; diff --git a/freebsd/contrib/wpa/src/crypto/crypto_openssl.c b/freebsd/contrib/wpa/src/crypto/crypto_openssl.c index 83630422..ee4d55eb 100644 --- a/freebsd/contrib/wpa/src/crypto/crypto_openssl.c +++ b/freebsd/contrib/wpa/src/crypto/crypto_openssl.c @@ -31,11 +31,61 @@ #include "sha1.h" #include "sha256.h" #include "sha384.h" +#include "md5.h" +#include "aes_wrap.h" #include "crypto.h" +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) +/* Compatibility wrappers for older versions. */ + +static HMAC_CTX * HMAC_CTX_new(void) +{ + HMAC_CTX *ctx; + + ctx = os_zalloc(sizeof(*ctx)); + if (ctx) + HMAC_CTX_init(ctx); + return ctx; +} + + +static void HMAC_CTX_free(HMAC_CTX *ctx) +{ + if (!ctx) + return; + HMAC_CTX_cleanup(ctx); + bin_clear_free(ctx, sizeof(*ctx)); +} + + +static EVP_MD_CTX * EVP_MD_CTX_new(void) +{ + EVP_MD_CTX *ctx; + + ctx = os_zalloc(sizeof(*ctx)); + if (ctx) + EVP_MD_CTX_init(ctx); + return ctx; +} + + +static void EVP_MD_CTX_free(EVP_MD_CTX *ctx) +{ + if (!ctx) + return; + EVP_MD_CTX_cleanup(ctx); + bin_clear_free(ctx, sizeof(*ctx)); +} + +#endif /* OpenSSL version < 1.1.0 */ + static BIGNUM * get_group5_prime(void) { -#ifdef OPENSSL_IS_BORINGSSL +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) + return BN_get_rfc3526_prime_1536(NULL); +#elif !defined(OPENSSL_IS_BORINGSSL) + return get_rfc3526_prime_1536(NULL); +#else static const unsigned char RFC3526_PRIME_1536[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2, 0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1, @@ -55,9 +105,7 @@ static BIGNUM * get_group5_prime(void) 0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }; return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL); -#else /* OPENSSL_IS_BORINGSSL */ - return get_rfc3526_prime_1536(NULL); -#endif /* OPENSSL_IS_BORINGSSL */ +#endif } #ifdef OPENSSL_NO_SHA256 @@ -67,29 +115,38 @@ static BIGNUM * get_group5_prime(void) static int openssl_digest_vector(const EVP_MD *type, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { - EVP_MD_CTX ctx; + EVP_MD_CTX *ctx; size_t i; unsigned int mac_len; - EVP_MD_CTX_init(&ctx); - if (!EVP_DigestInit_ex(&ctx, type, NULL)) { + if (TEST_FAIL()) + return -1; + + ctx = EVP_MD_CTX_new(); + if (!ctx) + return -1; + if (!EVP_DigestInit_ex(ctx, type, NULL)) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s", ERR_error_string(ERR_get_error(), NULL)); + EVP_MD_CTX_free(ctx); return -1; } for (i = 0; i < num_elem; i++) { - if (!EVP_DigestUpdate(&ctx, addr[i], len[i])) { + if (!EVP_DigestUpdate(ctx, addr[i], len[i])) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate " "failed: %s", ERR_error_string(ERR_get_error(), NULL)); + EVP_MD_CTX_free(ctx); return -1; } } - if (!EVP_DigestFinal(&ctx, mac, &mac_len)) { + if (!EVP_DigestFinal(ctx, mac, &mac_len)) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s", ERR_error_string(ERR_get_error(), NULL)); + EVP_MD_CTX_free(ctx); return -1; } + EVP_MD_CTX_free(ctx); return 0; } @@ -131,32 +188,34 @@ int rc4_skip(const u8 *key, size_t keylen, size_t skip, #ifdef OPENSSL_NO_RC4 return -1; #else /* OPENSSL_NO_RC4 */ - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; int outl; int res = -1; unsigned char skip_buf[16]; - EVP_CIPHER_CTX_init(&ctx); - if (!EVP_CIPHER_CTX_set_padding(&ctx, 0) || - !EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1) || - !EVP_CIPHER_CTX_set_key_length(&ctx, keylen) || - !EVP_CipherInit_ex(&ctx, NULL, NULL, key, NULL, 1)) + ctx = EVP_CIPHER_CTX_new(); + if (!ctx || + !EVP_CIPHER_CTX_set_padding(ctx, 0) || + !EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, NULL, NULL, 1) || + !EVP_CIPHER_CTX_set_key_length(ctx, keylen) || + !EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, 1)) goto out; while (skip >= sizeof(skip_buf)) { size_t len = skip; if (len > sizeof(skip_buf)) len = sizeof(skip_buf); - if (!EVP_CipherUpdate(&ctx, skip_buf, &outl, skip_buf, len)) + if (!EVP_CipherUpdate(ctx, skip_buf, &outl, skip_buf, len)) goto out; skip -= len; } - if (EVP_CipherUpdate(&ctx, data, &outl, data, data_len)) + if (EVP_CipherUpdate(ctx, data, &outl, data, data_len)) res = 0; out: - EVP_CIPHER_CTX_cleanup(&ctx); + if (ctx) + EVP_CIPHER_CTX_free(ctx); return res; #endif /* OPENSSL_NO_RC4 */ } @@ -208,14 +267,16 @@ void * aes_encrypt_init(const u8 *key, size_t len) EVP_CIPHER_CTX *ctx; const EVP_CIPHER *type; + if (TEST_FAIL()) + return NULL; + type = aes_get_evp_cipher(len); if (type == NULL) return NULL; - ctx = os_malloc(sizeof(*ctx)); + ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) return NULL; - EVP_CIPHER_CTX_init(ctx); if (EVP_EncryptInit_ex(ctx, type, NULL, key, NULL) != 1) { os_free(ctx); return NULL; @@ -249,8 +310,7 @@ void aes_encrypt_deinit(void *ctx) wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d " "in AES encrypt", len); } - EVP_CIPHER_CTX_cleanup(c); - bin_clear_free(c, sizeof(*c)); + EVP_CIPHER_CTX_free(c); } @@ -259,16 +319,18 @@ void * aes_decrypt_init(const u8 *key, size_t len) EVP_CIPHER_CTX *ctx; const EVP_CIPHER *type; + if (TEST_FAIL()) + return NULL; + type = aes_get_evp_cipher(len); if (type == NULL) return NULL; - ctx = os_malloc(sizeof(*ctx)); + ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) return NULL; - EVP_CIPHER_CTX_init(ctx); if (EVP_DecryptInit_ex(ctx, type, NULL, key, NULL) != 1) { - os_free(ctx); + EVP_CIPHER_CTX_free(ctx); return NULL; } EVP_CIPHER_CTX_set_padding(ctx, 0); @@ -300,8 +362,7 @@ void aes_decrypt_deinit(void *ctx) wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d " "in AES decrypt", len); } - EVP_CIPHER_CTX_cleanup(c); - bin_clear_free(c, sizeof(*c)); + EVP_CIPHER_CTX_free(c); } @@ -340,51 +401,56 @@ int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) { - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; int clen, len; u8 buf[16]; + int res = -1; - EVP_CIPHER_CTX_init(&ctx); - if (EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv) != 1) + if (TEST_FAIL()) return -1; - EVP_CIPHER_CTX_set_padding(&ctx, 0); - clen = data_len; - if (EVP_EncryptUpdate(&ctx, data, &clen, data, data_len) != 1 || - clen != (int) data_len) + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) return -1; - + clen = data_len; len = sizeof(buf); - if (EVP_EncryptFinal_ex(&ctx, buf, &len) != 1 || len != 0) - return -1; - EVP_CIPHER_CTX_cleanup(&ctx); + if (EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) == 1 && + EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 && + EVP_EncryptUpdate(ctx, data, &clen, data, data_len) == 1 && + clen == (int) data_len && + EVP_EncryptFinal_ex(ctx, buf, &len) == 1 && len == 0) + res = 0; + EVP_CIPHER_CTX_free(ctx); - return 0; + return res; } int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) { - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; int plen, len; u8 buf[16]; + int res = -1; - EVP_CIPHER_CTX_init(&ctx); - if (EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv) != 1) + if (TEST_FAIL()) return -1; - EVP_CIPHER_CTX_set_padding(&ctx, 0); - plen = data_len; - if (EVP_DecryptUpdate(&ctx, data, &plen, data, data_len) != 1 || - plen != (int) data_len) + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) return -1; - + plen = data_len; len = sizeof(buf); - if (EVP_DecryptFinal_ex(&ctx, buf, &len) != 1 || len != 0) - return -1; - EVP_CIPHER_CTX_cleanup(&ctx); + if (EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) == 1 && + EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 && + EVP_DecryptUpdate(ctx, data, &plen, data, data_len) == 1 && + plen == (int) data_len && + EVP_DecryptFinal_ex(ctx, buf, &len) == 1 && len == 0) + res = 0; + EVP_CIPHER_CTX_free(ctx); + + return res; - return 0; } @@ -427,8 +493,8 @@ error: struct crypto_cipher { - EVP_CIPHER_CTX enc; - EVP_CIPHER_CTX dec; + EVP_CIPHER_CTX *enc; + EVP_CIPHER_CTX *dec; }; @@ -489,23 +555,25 @@ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, return NULL; } - EVP_CIPHER_CTX_init(&ctx->enc); - EVP_CIPHER_CTX_set_padding(&ctx->enc, 0); - if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) || - !EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) || - !EVP_EncryptInit_ex(&ctx->enc, NULL, NULL, key, iv)) { - EVP_CIPHER_CTX_cleanup(&ctx->enc); + if (!(ctx->enc = EVP_CIPHER_CTX_new()) || + !EVP_CIPHER_CTX_set_padding(ctx->enc, 0) || + !EVP_EncryptInit_ex(ctx->enc, cipher, NULL, NULL, NULL) || + !EVP_CIPHER_CTX_set_key_length(ctx->enc, key_len) || + !EVP_EncryptInit_ex(ctx->enc, NULL, NULL, key, iv)) { + if (ctx->enc) + EVP_CIPHER_CTX_free(ctx->enc); os_free(ctx); return NULL; } - EVP_CIPHER_CTX_init(&ctx->dec); - EVP_CIPHER_CTX_set_padding(&ctx->dec, 0); - if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) || - !EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) || - !EVP_DecryptInit_ex(&ctx->dec, NULL, NULL, key, iv)) { - EVP_CIPHER_CTX_cleanup(&ctx->enc); - EVP_CIPHER_CTX_cleanup(&ctx->dec); + if (!(ctx->dec = EVP_CIPHER_CTX_new()) || + !EVP_CIPHER_CTX_set_padding(ctx->dec, 0) || + !EVP_DecryptInit_ex(ctx->dec, cipher, NULL, NULL, NULL) || + !EVP_CIPHER_CTX_set_key_length(ctx->dec, key_len) || + !EVP_DecryptInit_ex(ctx->dec, NULL, NULL, key, iv)) { + EVP_CIPHER_CTX_free(ctx->enc); + if (ctx->dec) + EVP_CIPHER_CTX_free(ctx->dec); os_free(ctx); return NULL; } @@ -518,7 +586,7 @@ int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { int outl; - if (!EVP_EncryptUpdate(&ctx->enc, crypt, &outl, plain, len)) + if (!EVP_EncryptUpdate(ctx->enc, crypt, &outl, plain, len)) return -1; return 0; } @@ -529,7 +597,7 @@ int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, { int outl; outl = len; - if (!EVP_DecryptUpdate(&ctx->dec, plain, &outl, crypt, len)) + if (!EVP_DecryptUpdate(ctx->dec, plain, &outl, crypt, len)) return -1; return 0; } @@ -537,19 +605,21 @@ int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, void crypto_cipher_deinit(struct crypto_cipher *ctx) { - EVP_CIPHER_CTX_cleanup(&ctx->enc); - EVP_CIPHER_CTX_cleanup(&ctx->dec); + EVP_CIPHER_CTX_free(ctx->enc); + EVP_CIPHER_CTX_free(ctx->dec); os_free(ctx); } void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L DH *dh; struct wpabuf *pubkey = NULL, *privkey = NULL; size_t publen, privlen; *priv = NULL; + wpabuf_free(*publ); *publ = NULL; dh = DH_new(); @@ -588,11 +658,63 @@ err: wpabuf_clear_free(privkey); DH_free(dh); return NULL; +#else + DH *dh; + struct wpabuf *pubkey = NULL, *privkey = NULL; + size_t publen, privlen; + BIGNUM *p = NULL, *g; + const BIGNUM *priv_key = NULL, *pub_key = NULL; + + *priv = NULL; + wpabuf_free(*publ); + *publ = NULL; + + dh = DH_new(); + if (dh == NULL) + return NULL; + + g = BN_new(); + p = get_group5_prime(); + if (!g || BN_set_word(g, 2) != 1 || !p || + DH_set0_pqg(dh, p, NULL, g) != 1) + goto err; + p = NULL; + g = NULL; + + if (DH_generate_key(dh) != 1) + goto err; + + DH_get0_key(dh, &pub_key, &priv_key); + publen = BN_num_bytes(pub_key); + pubkey = wpabuf_alloc(publen); + if (!pubkey) + goto err; + privlen = BN_num_bytes(priv_key); + privkey = wpabuf_alloc(privlen); + if (!privkey) + goto err; + + BN_bn2bin(pub_key, wpabuf_put(pubkey, publen)); + BN_bn2bin(priv_key, wpabuf_put(privkey, privlen)); + + *priv = privkey; + *publ = pubkey; + return dh; + +err: + BN_free(p); + BN_free(g); + wpabuf_clear_free(pubkey); + wpabuf_clear_free(privkey); + DH_free(dh); + return NULL; +#endif } void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L DH *dh; dh = DH_new(); @@ -623,6 +745,42 @@ void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ) err: DH_free(dh); return NULL; +#else + DH *dh; + BIGNUM *p = NULL, *g, *priv_key = NULL, *pub_key = NULL; + + dh = DH_new(); + if (dh == NULL) + return NULL; + + g = BN_new(); + p = get_group5_prime(); + if (!g || BN_set_word(g, 2) != 1 || !p || + DH_set0_pqg(dh, p, NULL, g) != 1) + goto err; + p = NULL; + g = NULL; + + priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL); + pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL); + if (!priv_key || !pub_key || DH_set0_key(dh, pub_key, priv_key) != 1) + goto err; + pub_key = NULL; + priv_key = NULL; + + if (DH_generate_key(dh) != 1) + goto err; + + return dh; + +err: + BN_free(p); + BN_free(g); + BN_free(pub_key); + BN_clear_free(priv_key); + DH_free(dh); + return NULL; +#endif } @@ -674,7 +832,7 @@ void dh5_free(void *ctx) struct crypto_hash { - HMAC_CTX ctx; + HMAC_CTX *ctx; }; @@ -709,16 +867,17 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; - HMAC_CTX_init(&ctx->ctx); + ctx->ctx = HMAC_CTX_new(); + if (!ctx->ctx) { + os_free(ctx); + return NULL; + } -#if OPENSSL_VERSION_NUMBER < 0x00909000 - HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL); -#else /* openssl < 0.9.9 */ - if (HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL) != 1) { + if (HMAC_Init_ex(ctx->ctx, key, key_len, md, NULL) != 1) { + HMAC_CTX_free(ctx->ctx); bin_clear_free(ctx, sizeof(*ctx)); return NULL; } -#endif /* openssl < 0.9.9 */ return ctx; } @@ -728,7 +887,7 @@ void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) { if (ctx == NULL) return; - HMAC_Update(&ctx->ctx, data, len); + HMAC_Update(ctx->ctx, data, len); } @@ -741,18 +900,14 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) return -2; if (mac == NULL || len == NULL) { + HMAC_CTX_free(ctx->ctx); bin_clear_free(ctx, sizeof(*ctx)); return 0; } mdlen = *len; -#if OPENSSL_VERSION_NUMBER < 0x00909000 - HMAC_Final(&ctx->ctx, mac, &mdlen); - res = 1; -#else /* openssl < 0.9.9 */ - res = HMAC_Final(&ctx->ctx, mac, &mdlen); -#endif /* openssl < 0.9.9 */ - HMAC_CTX_cleanup(&ctx->ctx); + res = HMAC_Final(ctx->ctx, mac, &mdlen); + HMAC_CTX_free(ctx->ctx); bin_clear_free(ctx, sizeof(*ctx)); if (res == 1) { @@ -769,28 +924,26 @@ static int openssl_hmac_vector(const EVP_MD *type, const u8 *key, const u8 *addr[], const size_t *len, u8 *mac, unsigned int mdlen) { - HMAC_CTX ctx; + HMAC_CTX *ctx; size_t i; int res; - HMAC_CTX_init(&ctx); -#if OPENSSL_VERSION_NUMBER < 0x00909000 - HMAC_Init_ex(&ctx, key, key_len, type, NULL); -#else /* openssl < 0.9.9 */ - if (HMAC_Init_ex(&ctx, key, key_len, type, NULL) != 1) + if (TEST_FAIL()) return -1; -#endif /* openssl < 0.9.9 */ + + ctx = HMAC_CTX_new(); + if (!ctx) + return -1; + res = HMAC_Init_ex(ctx, key, key_len, type, NULL); + if (res != 1) + goto done; for (i = 0; i < num_elem; i++) - HMAC_Update(&ctx, addr[i], len[i]); + HMAC_Update(ctx, addr[i], len[i]); -#if OPENSSL_VERSION_NUMBER < 0x00909000 - HMAC_Final(&ctx, mac, &mdlen); - res = 1; -#else /* openssl < 0.9.9 */ - res = HMAC_Final(&ctx, mac, &mdlen); -#endif /* openssl < 0.9.9 */ - HMAC_CTX_cleanup(&ctx); + res = HMAC_Final(ctx, mac, &mdlen); +done: + HMAC_CTX_free(ctx); return res == 1 ? 0 : -1; } @@ -894,6 +1047,9 @@ int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem, int ret = -1; size_t outlen, i; + if (TEST_FAIL()) + return -1; + ctx = CMAC_CTX_new(); if (ctx == NULL) return -1; @@ -943,13 +1099,20 @@ int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac) struct crypto_bignum * crypto_bignum_init(void) { + if (TEST_FAIL()) + return NULL; return (struct crypto_bignum *) BN_new(); } struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len) { - BIGNUM *bn = BN_bin2bn(buf, len, NULL); + BIGNUM *bn; + + if (TEST_FAIL()) + return NULL; + + bn = BN_bin2bn(buf, len, NULL); return (struct crypto_bignum *) bn; } @@ -968,6 +1131,9 @@ int crypto_bignum_to_bin(const struct crypto_bignum *a, { int num_bytes, offset; + if (TEST_FAIL()) + return -1; + if (padlen > buflen) return -1; @@ -1021,6 +1187,9 @@ int crypto_bignum_exptmod(const struct crypto_bignum *a, int res; BN_CTX *bnctx; + if (TEST_FAIL()) + return -1; + bnctx = BN_CTX_new(); if (bnctx == NULL) return -1; @@ -1039,6 +1208,8 @@ int crypto_bignum_inverse(const struct crypto_bignum *a, BIGNUM *res; BN_CTX *bnctx; + if (TEST_FAIL()) + return -1; bnctx = BN_CTX_new(); if (bnctx == NULL) return -1; @@ -1054,6 +1225,8 @@ int crypto_bignum_sub(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c) { + if (TEST_FAIL()) + return -1; return BN_sub((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ? 0 : -1; } @@ -1067,6 +1240,9 @@ int crypto_bignum_div(const struct crypto_bignum *a, BN_CTX *bnctx; + if (TEST_FAIL()) + return -1; + bnctx = BN_CTX_new(); if (bnctx == NULL) return -1; @@ -1087,6 +1263,9 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a, BN_CTX *bnctx; + if (TEST_FAIL()) + return -1; + bnctx = BN_CTX_new(); if (bnctx == NULL) return -1; @@ -1130,6 +1309,9 @@ int crypto_bignum_legendre(const struct crypto_bignum *a, BIGNUM *exp = NULL, *tmp = NULL; int res = -2; + if (TEST_FAIL()) + return -2; + bnctx = BN_CTX_new(); if (bnctx == NULL) return -2; @@ -1254,6 +1436,8 @@ void crypto_ec_deinit(struct crypto_ec *e) struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e) { + if (TEST_FAIL()) + return NULL; if (e == NULL) return NULL; return (struct crypto_ec_point *) EC_POINT_new(e->group); @@ -1300,6 +1484,9 @@ int crypto_ec_point_to_bin(struct crypto_ec *e, int ret = -1; int len = BN_num_bytes(e->prime); + if (TEST_FAIL()) + return -1; + x_bn = BN_new(); y_bn = BN_new(); @@ -1330,6 +1517,9 @@ struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e, EC_POINT *elem; int len = BN_num_bytes(e->prime); + if (TEST_FAIL()) + return NULL; + x = BN_bin2bn(val, len, NULL); y = BN_bin2bn(val + len, len, NULL); elem = EC_POINT_new(e->group); @@ -1357,6 +1547,8 @@ int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a, const struct crypto_ec_point *b, struct crypto_ec_point *c) { + if (TEST_FAIL()) + return -1; return EC_POINT_add(e->group, (EC_POINT *) c, (const EC_POINT *) a, (const EC_POINT *) b, e->bnctx) ? 0 : -1; } @@ -1366,6 +1558,8 @@ int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p, const struct crypto_bignum *b, struct crypto_ec_point *res) { + if (TEST_FAIL()) + return -1; return EC_POINT_mul(e->group, (EC_POINT *) res, NULL, (const EC_POINT *) p, (const BIGNUM *) b, e->bnctx) ? 0 : -1; @@ -1374,6 +1568,8 @@ int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p, int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p) { + if (TEST_FAIL()) + return -1; return EC_POINT_invert(e->group, (EC_POINT *) p, e->bnctx) ? 0 : -1; } @@ -1382,6 +1578,8 @@ int crypto_ec_point_solve_y_coord(struct crypto_ec *e, struct crypto_ec_point *p, const struct crypto_bignum *x, int y_bit) { + if (TEST_FAIL()) + return -1; if (!EC_POINT_set_compressed_coordinates_GFp(e->group, (EC_POINT *) p, (const BIGNUM *) x, y_bit, e->bnctx) || @@ -1397,6 +1595,9 @@ crypto_ec_point_compute_y_sqr(struct crypto_ec *e, { BIGNUM *tmp, *tmp2, *y_sqr = NULL; + if (TEST_FAIL()) + return NULL; + tmp = BN_new(); tmp2 = BN_new(); diff --git a/freebsd/contrib/wpa/src/crypto/ms_funcs.c b/freebsd/contrib/wpa/src/crypto/ms_funcs.c index dda2ba7c..67e98dbf 100644 --- a/freebsd/contrib/wpa/src/crypto/ms_funcs.c +++ b/freebsd/contrib/wpa/src/crypto/ms_funcs.c @@ -50,7 +50,7 @@ static int utf8_to_ucs2(const u8 *utf8_string, size_t utf8_string_len, WPA_PUT_LE16(ucs2_buffer + j, ((c & 0x1F) << 6) | (c2 & 0x3F)); j += 2; - } else if (i == utf8_string_len || + } else if (i == utf8_string_len - 1 || j >= ucs2_buffer_size - 1) { /* incomplete surrogate */ return -1; diff --git a/freebsd/contrib/wpa/src/crypto/sha256-internal.c b/freebsd/contrib/wpa/src/crypto/sha256-internal.c index c2ef3154..174bf3c4 100644 --- a/freebsd/contrib/wpa/src/crypto/sha256-internal.c +++ b/freebsd/contrib/wpa/src/crypto/sha256-internal.c @@ -30,6 +30,9 @@ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, struct sha256_state ctx; size_t i; + if (TEST_FAIL()) + return -1; + sha256_init(&ctx); for (i = 0; i < num_elem; i++) if (sha256_process(&ctx, addr[i], len[i])) diff --git a/freebsd/contrib/wpa/src/crypto/sha256-prf.c b/freebsd/contrib/wpa/src/crypto/sha256-prf.c index 76496214..e2150e21 100644 --- a/freebsd/contrib/wpa/src/crypto/sha256-prf.c +++ b/freebsd/contrib/wpa/src/crypto/sha256-prf.c @@ -2,7 +2,7 @@ /* * SHA256-based PRF (IEEE 802.11r) - * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -24,14 +24,16 @@ * @data_len: Length of the data * @buf: Buffer for the generated pseudo-random key * @buf_len: 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. */ -void sha256_prf(const u8 *key, size_t key_len, const char *label, +int 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) { - sha256_prf_bits(key, key_len, label, data, data_len, buf, buf_len * 8); + return sha256_prf_bits(key, key_len, label, data, data_len, buf, + buf_len * 8); } @@ -44,15 +46,16 @@ void sha256_prf(const u8 *key, size_t key_len, const char *label, * @data_len: Length of the data * @buf: Buffer for the generated pseudo-random key * @buf_len: Number of bits 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. If the requested buf_len is not divisible by eight, the least * significant 1-7 bits of the last octet in the output are not part of the * requested output. */ -void sha256_prf_bits(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, - size_t buf_len_bits) +int sha256_prf_bits(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, + size_t buf_len_bits) { u16 counter = 1; size_t pos, plen; @@ -77,11 +80,14 @@ void sha256_prf_bits(const u8 *key, size_t key_len, const char *label, plen = buf_len - pos; WPA_PUT_LE16(counter_le, counter); if (plen >= SHA256_MAC_LEN) { - hmac_sha256_vector(key, key_len, 4, addr, len, - &buf[pos]); + if (hmac_sha256_vector(key, key_len, 4, addr, len, + &buf[pos]) < 0) + return -1; pos += SHA256_MAC_LEN; } else { - hmac_sha256_vector(key, key_len, 4, addr, len, hash); + if (hmac_sha256_vector(key, key_len, 4, addr, len, + hash) < 0) + return -1; os_memcpy(&buf[pos], hash, plen); pos += plen; break; @@ -99,4 +105,6 @@ void sha256_prf_bits(const u8 *key, size_t key_len, const char *label, } os_memset(hash, 0, sizeof(hash)); + + return 0; } diff --git a/freebsd/contrib/wpa/src/crypto/sha256.h b/freebsd/contrib/wpa/src/crypto/sha256.h index b15f5115..5219022e 100644 --- a/freebsd/contrib/wpa/src/crypto/sha256.h +++ b/freebsd/contrib/wpa/src/crypto/sha256.h @@ -1,6 +1,6 @@ /* * SHA256 hash implementation and interface functions - * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -15,11 +15,11 @@ int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); int 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 sha256_prf_bits(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, - size_t buf_len_bits); +int 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); +int sha256_prf_bits(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, + size_t buf_len_bits); 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); diff --git a/freebsd/contrib/wpa/src/crypto/tls.h b/freebsd/contrib/wpa/src/crypto/tls.h index 2e562339..11d504a9 100644 --- a/freebsd/contrib/wpa/src/crypto/tls.h +++ b/freebsd/contrib/wpa/src/crypto/tls.h @@ -95,6 +95,8 @@ struct tls_config { #define TLS_CONN_DISABLE_TLSv1_2 BIT(6) #define TLS_CONN_EAP_FAST BIT(7) #define TLS_CONN_DISABLE_TLSv1_0 BIT(8) +#define TLS_CONN_EXT_CERT_CHECK BIT(9) +#define TLS_CONN_REQUIRE_OCSP_ALL BIT(10) /** * struct tls_connection_params - Parameters for TLS connection @@ -139,6 +141,9 @@ struct tls_config { * @flags: Parameter options (TLS_CONN_*) * @ocsp_stapling_response: DER encoded file with cached OCSP stapling response * or %NULL if OCSP is not enabled + * @ocsp_stapling_response_multi: DER encoded file with cached OCSP stapling + * response list (OCSPResponseList for ocsp_multi in RFC 6961) or %NULL if + * ocsp_multi is not enabled * * TLS connection parameters to be configured with tls_connection_set_params() * and tls_global_set_params(). @@ -179,6 +184,7 @@ struct tls_connection_params { unsigned int flags; const char *ocsp_stapling_response; + const char *ocsp_stapling_response_multi; }; @@ -330,29 +336,36 @@ int __must_check tls_connection_get_random(void *tls_ctx, struct tls_random *data); /** - * tls_connection_prf - Use TLS-PRF to derive keying material + * tls_connection_export_key - Derive keying material from a TLS connection * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @label: Label (e.g., description of the key) for PRF - * @server_random_first: seed is 0 = client_random|server_random, - * 1 = server_random|client_random - * @skip_keyblock: Skip TLS key block from the beginning of PRF output * @out: Buffer for output data from TLS-PRF * @out_len: Length of the output buffer * Returns: 0 on success, -1 on failure * - * tls_connection_prf() is required so that further keying material can be - * derived from the master secret. 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). For TLSv1.2 and - * newer, a different PRF is needed, though. + * Exports keying material using the mechanism described in RFC 5705. */ -int __must_check tls_connection_prf(void *tls_ctx, - struct tls_connection *conn, - const char *label, - int server_random_first, - int skip_keyblock, - u8 *out, size_t out_len); +int __must_check tls_connection_export_key(void *tls_ctx, + struct tls_connection *conn, + const char *label, + u8 *out, size_t out_len); + +/** + * tls_connection_get_eap_fast_key - Derive key material for EAP-FAST + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * @out: Buffer for output data from TLS-PRF + * @out_len: Length of the output buffer + * Returns: 0 on success, -1 on failure + * + * Exports key material after the normal TLS key block for use with + * EAP-FAST. Most callers will want tls_connection_export_key(), but EAP-FAST + * uses a different legacy mechanism. + */ +int __must_check tls_connection_get_eap_fast_key(void *tls_ctx, + struct tls_connection *conn, + u8 *out, size_t out_len); /** * tls_connection_handshake - Process TLS handshake (client side) @@ -455,7 +468,9 @@ enum { TLS_CIPHER_RC4_SHA /* 0x0005 */, TLS_CIPHER_AES128_SHA /* 0x002f */, TLS_CIPHER_RSA_DHE_AES128_SHA /* 0x0031 */, - TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */ + TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */, + TLS_CIPHER_RSA_DHE_AES256_SHA /* 0x0039 */, + TLS_CIPHER_AES256_SHA /* 0x0035 */, }; /** diff --git a/freebsd/contrib/wpa/src/crypto/tls_internal.c b/freebsd/contrib/wpa/src/crypto/tls_internal.c index 6a91f497..c6f65dc0 100644 --- a/freebsd/contrib/wpa/src/crypto/tls_internal.c +++ b/freebsd/contrib/wpa/src/crypto/tls_internal.c @@ -25,6 +25,11 @@ struct tls_global { int server; struct tlsv1_credentials *server_cred; int check_crl; + + void (*event_cb)(void *ctx, enum tls_event ev, + union tls_event_data *data); + void *cb_ctx; + int cert_in_cb; }; struct tls_connection { @@ -53,6 +58,11 @@ void * tls_init(const struct tls_config *conf) global = os_zalloc(sizeof(*global)); if (global == NULL) return NULL; + if (conf) { + global->event_cb = conf->event_cb; + global->cb_ctx = conf->cb_ctx; + global->cert_in_cb = conf->cert_in_cb; + } return global; } @@ -66,10 +76,12 @@ void tls_deinit(void *ssl_ctx) tlsv1_client_global_deinit(); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER - tlsv1_cred_free(global->server_cred); tlsv1_server_global_deinit(); #endif /* CONFIG_TLS_INTERNAL_SERVER */ } +#ifdef CONFIG_TLS_INTERNAL_SERVER + tlsv1_cred_free(global->server_cred); +#endif /* CONFIG_TLS_INTERNAL_SERVER */ os_free(global); } @@ -97,6 +109,8 @@ struct tls_connection * tls_connection_init(void *tls_ctx) os_free(conn); return NULL; } + tlsv1_client_set_cb(conn->client, global->event_cb, + global->cb_ctx, global->cert_in_cb); } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER @@ -188,6 +202,12 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, if (conn->client == NULL) return -1; + if (params->flags & TLS_CONN_EXT_CERT_CHECK) { + wpa_printf(MSG_INFO, + "TLS: tls_ext_cert_check=1 not supported"); + return -1; + } + cred = tlsv1_cred_alloc(); if (cred == NULL) return -1; @@ -261,8 +281,7 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, return -1; } - tlsv1_client_set_time_checks( - conn->client, !(params->flags & TLS_CONN_DISABLE_TIME_CHECKS)); + tlsv1_client_set_flags(conn->client, params->flags); return 0; #else /* CONFIG_TLS_INTERNAL_CLIENT */ @@ -314,6 +333,13 @@ int tls_global_set_params(void *tls_ctx, return -1; } + if (params->ocsp_stapling_response) + cred->ocsp_stapling_response = + os_strdup(params->ocsp_stapling_response); + if (params->ocsp_stapling_response_multi) + cred->ocsp_stapling_response_multi = + os_strdup(params->ocsp_stapling_response_multi); + return 0; #else /* CONFIG_TLS_INTERNAL_SERVER */ return -1; @@ -370,9 +396,9 @@ static int tls_get_keyblock_size(struct tls_connection *conn) } -int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, - int skip_keyblock, u8 *out, size_t out_len) +static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, + const char *label, int server_random_first, + int skip_keyblock, u8 *out, size_t out_len) { int ret = -1, skip = 0; u8 *tmp_out = NULL; @@ -392,14 +418,14 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, if (conn->client) { ret = tlsv1_client_prf(conn->client, label, server_random_first, - _out, out_len); + _out, skip + out_len); } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) { ret = tlsv1_server_prf(conn->server, label, server_random_first, - _out, out_len); + _out, skip + out_len); } #endif /* CONFIG_TLS_INTERNAL_SERVER */ if (ret == 0 && skip_keyblock) @@ -410,6 +436,21 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, } +int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn, + const char *label, u8 *out, size_t out_len) +{ + return tls_connection_prf(tls_ctx, conn, label, 0, 0, out, out_len); +} + + +int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn, + u8 *out, size_t out_len) +{ + return tls_connection_prf(tls_ctx, conn, "key expansion", 1, 1, out, + out_len); +} + + struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, @@ -623,7 +664,12 @@ int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, int tls_get_version(void *ssl_ctx, struct tls_connection *conn, char *buf, size_t buflen) { - /* TODO */ + if (conn == NULL) + return -1; +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (conn->client) + return tlsv1_client_get_version(conn->client, buf, buflen); +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ return -1; } |