control: tags -1 patch On 2016-06-26 12:23:04 [+0200], Kurt Roeckx wrote: > OpenSSL 1.1.0 is about to released. During a rebuild of all packages using > OpenSSL this package fail to build. A log of that build can be found at: > https://breakpoint.cc/openssl-1.1-rebuild-2016-05-29/Attempted/moonshot-gss-eap_0.9.5-1_amd64-20160529-1451
this builds now. Do you have anything to verify? > Kurt Sebastian
>From 50b12a010649c57ca7080cc728c8088abf53f73e Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior <sebast...@breakpoint.cc> Date: Tue, 1 Nov 2016 20:41:46 +0000 Subject: [PATCH] moonshot-gss-eap: add support for openssl 1.1.0 and remain compatible with openssl 1.0.1k. Functions like DH_set0_pqg() are new accecssors in 1.1.0 and have been added as a compatibiliry wrapper. SSL_CTX_set_cert_store() for instance are already available in earlier openssl version and since SSL struct (among others) are opaque the accessors are used now. struct tls_keys contains now the copy of the key / random since the pointer are not exported anymore and a copy saves a malloc() + free() operation. I replaced TLSv1_method with SSLv23_method because the former makes only TLSv1 available. The latter provides multiple versions of the SSL protocol and try the highest possible version (currently TLSv1.2). Signed-off-by: Sebastian Andrzej Siewior <sebast...@breakpoint.cc> --- libeap/src/crypto/crypto_openssl.c | 178 ++++++++++++++++++++++++++--------- libeap/src/crypto/tls.h | 8 +- libeap/src/crypto/tls_openssl.c | 91 +++++++++++++++--- libeap/src/eap_peer/eap_tls_common.c | 2 + libeap/src/eap_peer/eap_ttls.c | 4 + 5 files changed, 218 insertions(+), 65 deletions(-) diff --git a/libeap/src/crypto/crypto_openssl.c b/libeap/src/crypto/crypto_openssl.c index 08c98af..ac33a35 100644 --- a/libeap/src/crypto/crypto_openssl.c +++ b/libeap/src/crypto/crypto_openssl.c @@ -34,6 +34,56 @@ des_ecb_encrypt((input), (output), *(ks), (enc)) #endif /* openssl < 0.9.7 */ +#if OPENSSL_VERSION_NUMBER < 0x10100000 +static EVP_MD_CTX *EVP_MD_CTX_new(void) +{ + return EVP_MD_CTX_create(); +} + +static void EVP_MD_CTX_free(EVP_MD_CTX *ctx) +{ + EVP_MD_CTX_destroy(ctx); +} +static int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) +{ + /* If the fields p and g in d are NULL, the corresponding input + * parameters MUST be non-NULL. q may remain NULL. + */ + if ((dh->p == NULL && p == NULL) + || (dh->g == NULL && g == NULL)) + return 0; + + if (p != NULL) { + BN_free(dh->p); + dh->p = p; + } + if (q != NULL) { + BN_free(dh->q); + dh->q = q; + } + if (g != NULL) { + BN_free(dh->g); + dh->g = g; + } + + if (q != NULL) { + dh->length = BN_num_bits(q); + } + + return 1; +} + +static void DH_get0_key(const DH *dh, const BIGNUM **pub_key, + const BIGNUM **priv_key) +{ + if (pub_key != NULL) + *pub_key = dh->pub_key; + if (priv_key != NULL) + *priv_key = dh->priv_key; +} + +#endif + static BIGNUM * get_group5_prime(void) { #if OPENSSL_VERSION_NUMBER < 0x00908000 @@ -78,37 +128,45 @@ static int openssl_digest_vector(const EVP_MD *type, int non_fips, 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); + ctx = EVP_MD_CTX_new(); + if (!ctx) { + wpa_printf(MSG_ERROR, "OpenSSL: EVP_MD_CTX_new failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } #ifdef CONFIG_FIPS #ifdef OPENSSL_FIPS if (non_fips) - EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); #endif /* OPENSSL_FIPS */ #endif /* CONFIG_FIPS */ - if (!EVP_DigestInit_ex(&ctx, type, NULL)) { + if (!EVP_DigestInit_ex(ctx, type, NULL)) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return -1; + goto err; } 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)); - return -1; + goto err; } } - 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)); - return -1; + goto err; } return 0; +err: + EVP_MD_CTX_free(ctx); + return -1; } @@ -145,32 +203,35 @@ 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) + return -1; + + 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)) 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); + EVP_CIPHER_CTX_free(ctx); return res; #endif /* OPENSSL_NO_RC4 */ } @@ -298,8 +359,8 @@ error: struct crypto_cipher { - EVP_CIPHER_CTX enc; - EVP_CIPHER_CTX dec; + EVP_CIPHER_CTX *enc; + EVP_CIPHER_CTX *dec; }; @@ -314,6 +375,15 @@ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, if (ctx == NULL) return NULL; + ctx->enc = EVP_CIPHER_CTX_new(); + ctx->dec = EVP_CIPHER_CTX_new(); + if (!ctx->enc || !ctx->dec) { + EVP_CIPHER_CTX_free(ctx->enc); + EVP_CIPHER_CTX_free(ctx->dec); + os_free(ctx); + return NULL; + } + switch (alg) { #ifndef OPENSSL_NO_RC4 case CRYPTO_CIPHER_ALG_RC4: @@ -352,27 +422,30 @@ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, break; #endif /* OPENSSL_NO_RC2 */ default: + EVP_CIPHER_CTX_free(ctx->enc); + EVP_CIPHER_CTX_free(ctx->dec); os_free(ctx); 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); + 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); + EVP_CIPHER_CTX_free(ctx->enc); + EVP_CIPHER_CTX_free(ctx->dec); 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); + 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_free(ctx->enc); + EVP_CIPHER_CTX_free(ctx->dec); os_free(ctx); return NULL; } @@ -385,7 +458,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; } @@ -396,7 +469,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; } @@ -404,8 +477,8 @@ 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); } @@ -415,36 +488,45 @@ void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) DH *dh; struct wpabuf *pubkey = NULL, *privkey = NULL; size_t publen, privlen; + BIGNUM *g, *p; + const BIGNUM *bn_pub_key, *bn_priv_key; *priv = NULL; *publ = NULL; dh = DH_new(); - if (dh == NULL) - return NULL; + g = BN_new(); + p = BN_new(); + if (dh == NULL || !g || !p) + goto err; - dh->g = BN_new(); - if (dh->g == NULL || BN_set_word(dh->g, 2) != 1) + if (BN_set_word(g, 2) != 1) goto err; - dh->p = get_group5_prime(); - if (dh->p == NULL) + p = get_group5_prime(); + if (p == NULL) goto err; + if (DH_set0_pqg(dh, p, NULL, g) == 0) + goto err; + + p = NULL; + g = NULL; if (DH_generate_key(dh) != 1) goto err; + DH_get0_key(dh, &bn_pub_key, &bn_priv_key); - publen = BN_num_bytes(dh->pub_key); + publen = BN_num_bytes(bn_pub_key); pubkey = wpabuf_alloc(publen); if (pubkey == NULL) goto err; - privlen = BN_num_bytes(dh->priv_key); + privlen = BN_num_bytes(bn_priv_key); privkey = wpabuf_alloc(privlen); if (privkey == NULL) goto err; - BN_bn2bin(dh->pub_key, wpabuf_put(pubkey, publen)); - BN_bn2bin(dh->priv_key, wpabuf_put(privkey, privlen)); + BN_bn2bin(bn_pub_key, wpabuf_put(pubkey, publen)); + BN_bn2bin(bn_priv_key, wpabuf_put(privkey, privlen)); *priv = privkey; *publ = pubkey; @@ -453,6 +535,8 @@ void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) err: wpabuf_free(pubkey); wpabuf_free(privkey); + BN_free(g); + BN_free(p); DH_free(dh); return NULL; } diff --git a/libeap/src/crypto/tls.h b/libeap/src/crypto/tls.h index 0928b5b..47be6cb 100644 --- a/libeap/src/crypto/tls.h +++ b/libeap/src/crypto/tls.h @@ -15,14 +15,16 @@ #ifndef TLS_H #define TLS_H +#include <openssl/ssl.h> + struct tls_connection; struct tls_keys { - const u8 *master_key; /* TLS master secret */ + u8 master_key[SSL_MAX_MASTER_KEY_LENGTH]; /* TLS master secret */ size_t master_key_len; - const u8 *client_random; + u8 client_random[SSL3_RANDOM_SIZE]; size_t client_random_len; - const u8 *server_random; + u8 server_random[SSL3_RANDOM_SIZE]; size_t server_random_len; const u8 *inner_secret; /* TLS/IA inner secret */ size_t inner_secret_len; diff --git a/libeap/src/crypto/tls_openssl.c b/libeap/src/crypto/tls_openssl.c index d155c09..aa510db 100644 --- a/libeap/src/crypto/tls_openssl.c +++ b/libeap/src/crypto/tls_openssl.c @@ -83,6 +83,43 @@ struct tls_connection { u8 srv_cert_hash[32]; }; +#if OPENSSL_VERSION_NUMBER < 0x10100000 +static size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, + unsigned char *out, size_t outlen) +{ + if (session->master_key_length < 0) { + /* Should never happen */ + return 0; + } + if (outlen == 0) + return session->master_key_length; + if (outlen > (size_t)session->master_key_length) + outlen = session->master_key_length; + memcpy(out, session->master_key, outlen); + return outlen; +} + +static size_t SSL_get_client_random(const SSL *ssl, unsigned char *out, + size_t outlen) +{ + if (outlen == 0) + return sizeof(ssl->s3->client_random); + if (outlen > sizeof(ssl->s3->client_random)) + outlen = sizeof(ssl->s3->client_random); + memcpy(out, ssl->s3->client_random, outlen); + return outlen; +} + +size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, size_t outlen) +{ + if (outlen == 0) + return sizeof(ssl->s3->server_random); + if (outlen > sizeof(ssl->s3->server_random)) + outlen = sizeof(ssl->s3->server_random); + memcpy(out, ssl->s3->server_random, outlen); + return outlen; +} +#endif #ifdef CONFIG_NO_STDOUT_DEBUG @@ -733,7 +770,7 @@ void * tls_init(const struct tls_config *conf) } tls_openssl_ref_count++; - ssl = SSL_CTX_new(TLSv1_method()); + ssl = SSL_CTX_new(SSLv23_method()); if (ssl == NULL) return NULL; @@ -767,7 +804,9 @@ void tls_deinit(void *ssl_ctx) tls_openssl_ref_count--; if (tls_openssl_ref_count == 0) { +#if OPENSSL_VERSION_NUMBER < 0x10100000 ERR_remove_state(0); +#endif os_free(tls_global); tls_global = NULL; } @@ -1256,9 +1295,11 @@ static int tls_load_ca_der(void *_ssl_ctx, const char *ca_cert) { SSL_CTX *ssl_ctx = _ssl_ctx; X509_LOOKUP *lookup; + X509_STORE *cert_store; int ret = 0; - lookup = X509_STORE_add_lookup(ssl_ctx->cert_store, + cert_store = SSL_CTX_get_cert_store(ssl_ctx); + lookup = X509_STORE_add_lookup(cert_store, X509_LOOKUP_file()); if (lookup == NULL) { tls_show_errors(MSG_WARNING, __func__, @@ -1289,18 +1330,19 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn, size_t ca_cert_blob_len, const char *ca_path) { SSL_CTX *ssl_ctx = _ssl_ctx; + X509_STORE *cert_store; /* * Remove previously configured trusted CA certificates before adding * new ones. */ - X509_STORE_free(ssl_ctx->cert_store); - ssl_ctx->cert_store = X509_STORE_new(); - if (ssl_ctx->cert_store == NULL) { + cert_store = X509_STORE_new(); + if (cert_store == NULL) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new " "certificate store", __func__); return -1; } + SSL_CTX_set_cert_store(ssl_ctx, cert_store); SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); conn->ca_cert_verify = 1; @@ -1352,7 +1394,7 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn, return -1; } - if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { + if (!X509_STORE_add_cert(cert_store, cert)) { unsigned long err = ERR_peek_error(); tls_show_errors(MSG_WARNING, __func__, "Failed to add ca_cert_blob to " @@ -2202,21 +2244,36 @@ int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, struct tls_keys *keys) { SSL *ssl; + SSL_SESSION *session; if (conn == NULL || keys == NULL) return -1; ssl = conn->ssl; - if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL) + if (ssl == NULL) + return -1; + + session = SSL_get0_session(ssl); + if (!session) return -1; os_memset(keys, 0, sizeof(*keys)); - keys->master_key = ssl->session->master_key; - keys->master_key_len = ssl->session->master_key_length; - keys->client_random = ssl->s3->client_random; - keys->client_random_len = SSL3_RANDOM_SIZE; - keys->server_random = ssl->s3->server_random; - keys->server_random_len = SSL3_RANDOM_SIZE; + keys->master_key_len = SSL_SESSION_get_master_key(session, + keys->master_key, + SSL_MAX_MASTER_KEY_LENGTH); + + keys->client_random_len = SSL_get_client_random(ssl, + keys->client_random, + SSL3_RANDOM_SIZE); + + keys->server_random_len = SSL_get_server_random(ssl, + keys->server_random, + SSL3_RANDOM_SIZE); + if (!keys->master_key_len || !keys->client_random_len || + !keys->server_random_len) { + os_memset(keys, 0, sizeof(*keys)); + return -1; + } return 0; } @@ -2457,7 +2514,7 @@ struct wpabuf * tls_connection_decrypt(void *tls_ctx, int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) { - return conn ? conn->ssl->hit : 0; + return conn ? SSL_session_reused(conn->ssl) : 0; } @@ -2694,6 +2751,9 @@ int tls_global_set_params(void *tls_ctx, } +#if 0 +/* no users */ + int tls_connection_get_keyblock_size(void *tls_ctx, struct tls_connection *conn) { @@ -2706,6 +2766,7 @@ int tls_connection_get_keyblock_size(void *tls_ctx, conn->ssl->read_hash == NULL) return -1; + c = conn->ssl->enc_read_ctx->cipher; #if OPENSSL_VERSION_NUMBER >= 0x00909000L h = EVP_MD_CTX_md(conn->ssl->read_hash); @@ -2717,7 +2778,7 @@ int tls_connection_get_keyblock_size(void *tls_ctx, EVP_MD_size(h) + EVP_CIPHER_iv_length(c)); } - +#endif unsigned int tls_capabilities(void *tls_ctx) { diff --git a/libeap/src/eap_peer/eap_tls_common.c b/libeap/src/eap_peer/eap_tls_common.c index 8559c4d..cde4a39 100644 --- a/libeap/src/eap_peer/eap_tls_common.c +++ b/libeap/src/eap_peer/eap_tls_common.c @@ -300,10 +300,12 @@ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, keys.server_random_len, out, len)) goto fail; + os_memset(&keys, 0, sizeof(keys)); os_free(rnd); return out; fail: + os_memset(&keys, 0, sizeof(keys)); os_free(out); os_free(rnd); return NULL; diff --git a/libeap/src/eap_peer/eap_ttls.c b/libeap/src/eap_peer/eap_ttls.c index 37e6bf3..250ebe8 100644 --- a/libeap/src/eap_peer/eap_ttls.c +++ b/libeap/src/eap_peer/eap_ttls.c @@ -440,6 +440,7 @@ static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, " "client random, or server random to derive " "implicit challenge"); + os_memset(&keys, 0, sizeof(keys)); return NULL; } @@ -450,6 +451,7 @@ static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, "challenge derivation"); os_free(rnd); os_free(challenge); + os_memset(&keys, 0, sizeof(keys)); return NULL; } os_memcpy(rnd, keys.server_random, keys.server_random_len); @@ -464,10 +466,12 @@ static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, "challenge"); os_free(rnd); os_free(challenge); + os_memset(&keys, 0, sizeof(keys)); return NULL; } os_free(rnd); + os_memset(&keys, 0, sizeof(keys)); wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge", challenge, len); -- 2.10.1