📄 ossl_tls_funcs.c
字号:
return NULL;
}
debug_printf(DEBUG_TLS_CORE, "Using session key const of : %s\n",
sesskey);
retblock = (uint8_t *)Malloc(TLS_SESSION_KEY_SIZE);
if (!retblock)
{
ipc_events_malloc_failed(NULL);
return NULL;
}
if (first == TLS_FUNCS_CLIENT_FIRST)
{
memcpy(p, mytls_vars->ssl->s3->client_random, SSL3_RANDOM_SIZE);
p+= SSL3_RANDOM_SIZE;
memcpy(p, mytls_vars->ssl->s3->server_random, SSL3_RANDOM_SIZE);
}
else
{
memcpy(p, mytls_vars->ssl->s3->server_random, SSL3_RANDOM_SIZE);
p+= SSL3_RANDOM_SIZE;
memcpy(p, mytls_vars->ssl->s3->client_random, SSL3_RANDOM_SIZE);
}
ossl_tls_funcs_PRF(SSL_get_session(mytls_vars->ssl)->master_key,
SSL_get_session(mytls_vars->ssl)->master_key_length,
(uint8_t *) sesskey, sesskeylen, seed,
SSL3_RANDOM_SIZE * 2, retblock,
TLS_SESSION_KEY_SIZE);
debug_printf(DEBUG_TLS_CORE, "Keyblock (%d) :\n ", TLS_SESSION_KEY_SIZE);
debug_hex_dump(DEBUG_TLS_CORE, retblock, TLS_SESSION_KEY_SIZE);
return retblock;
}
/************************************************************************
*
* Buffer any data that will eventually need to be sent to OpenSSL.
*
************************************************************************/
int tls_funcs_buffer(struct tls_vars *mytls_vars, uint8_t *newfrag,
uint16_t fragsize)
{
uint32_t value32 = 0;
uint8_t *p = NULL;
TRACE
if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE))
return XEGENERROR;
if (!xsup_assert((newfrag != NULL), "newfrag != NULL", FALSE))
return XEGENERROR;
p = newfrag;
if ((newfrag[0] & EAPTLS_LENGTH_INCL) == EAPTLS_LENGTH_INCL)
{
// We have length data, which means this should be the first piece
// of a fragment. So, verify that there isn't anything already
// buffered.
if (mytls_vars->tlsinqueue != NULL)
{
if (config_get_friendly_warnings() == TRUE)
{
debug_printf(DEBUG_NORMAL, "This appears to be the first piece "
"of a data fragment. However, there is already "
"data in the fragment buffer. It "
"is likely that your authentication will fail!\n");
}
}
else
{
// This is the first packet, possibly in a sequence. So create our queue.
if (queue_create(&mytls_vars->tlsinqueue) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't create queue to store incoming fragments!\n");
return XEGENERROR;
}
}
p++; // Skip to the bytes that contain the value.
memcpy(&value32, p, 4);
value32 = ntohl(value32);
p+=3;
mytls_vars->expected_in = value32;
fragsize -= 4; // Skip the length value.
}
else
{
if (queue_create(&mytls_vars->tlsinqueue) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't create queue to store incoming message.\n");
return XEGENERROR;
}
}
p++; // Skip the ID byte.
fragsize--;
if (queue_get_size(&mytls_vars->tlsinqueue, &value32) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't determine the queue size! We won't be able to "
"continue!\n");
return XEGENERROR;
}
debug_printf(DEBUG_TLS_CORE, "Total expected data size should be %d. (0 means we don't know what to expect!) We currently"
" have %d byte(s) of data, and will be adding %d more.\n",
mytls_vars->expected_in, value32, fragsize);
if (queue_enqueue(&mytls_vars->tlsinqueue, p, fragsize) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't enqueue the data fragment!\n");
return XEGENERROR;
}
if (queue_get_size(&mytls_vars->tlsinqueue, &value32) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't determine new queue size!\n");
}
else
{
if (((newfrag[0] & EAPTLS_MORE_FRAGS) != EAPTLS_MORE_FRAGS) &&
(value32 < mytls_vars->expected_in))
{
debug_printf(DEBUG_NORMAL, "The server indicated that there are no "
"fragments remaining. However, we only have %d of %d "
"byte(s). It is likely your authentication will fail."
"\n", value32, mytls_vars->expected_in);
}
}
return XENONE;
}
/************************************************************************
*
* Do we have something that is ready to be decrypted?
*
************************************************************************/
int tls_funcs_decrypt_ready(struct tls_vars *mytls_vars)
{
uint32_t value32 = 0;
TRACE
if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE))
return -1;
// The buffer is full.
if (queue_get_size(&mytls_vars->tlsinqueue, &value32) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't determine the queue depth!\n");
return -1;
}
debug_printf(DEBUG_TLS_CORE, "Expected size : %d Current size : %d\n",
mytls_vars->expected_in, value32);
if (mytls_vars->expected_in == value32)
return value32;
if (value32 > mytls_vars->expected_in)
return value32;
// Otherwise, we aren't ready yet.
return 0;
}
/************************************************************************
*
* Decrypt data in our buffer.
*
* This function derived from the original Xsupplicant code written by
* Danielle Brevi.
*
************************************************************************/
int tls_funcs_decrypt(struct tls_vars *mytls_vars, uint8_t *indata,
uint16_t *insize)
{
int rc = 0;
uint8_t *toencrypt = NULL;
uint32_t value32 = 0;
uint32_t expected = 0;
TRACE
if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE))
return -1;
if (!xsup_assert((indata != NULL), "indata != NULL", FALSE))
return -1;
if (!xsup_assert((insize != NULL), "insize != NULL", FALSE))
return -1;
// Determine how much data we have to push in.
if (queue_get_size(&mytls_vars->tlsinqueue, &value32) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't determine queue depth!\n");
return -1;
}
// Remember how much data we expect to get back.
expected = value32;
// Then, dequeue it all.
if (queue_dequeue(&mytls_vars->tlsinqueue, &toencrypt, &value32) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't dequeue data!\n");
return -1;
}
// We are done with this queue. Destroy it.
if (queue_destroy(&mytls_vars->tlsinqueue) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't destroy queue! We will leak memory!\n");
FREE(toencrypt);
return -1;
}
if (expected != value32) // ACK! What happened!? -- This is probably a show-stopper.
{
debug_printf(DEBUG_NORMAL, "We didn't dequeue the amount of data we were expecting. Something "
"is *SERIOUSLY* wrong!\n");
FREE(toencrypt);
return -1;
}
rc = BIO_write(mytls_vars->ssl_in, toencrypt, value32);
if (rc < 0)
{
debug_printf(DEBUG_NORMAL, "Failed to send data to OpenSSL for "
"decryption.\n");
FREE(toencrypt);
return -1;
}
FREE(toencrypt);
memset(indata, 0x00, (*insize));
rc = SSL_read(mytls_vars->ssl, indata, (*insize));
if (rc < 0)
{
debug_printf(DEBUG_NORMAL, "Failed to get decyrpted data from OpenSSL."
"\n");
tls_funcs_process_error();
return XEMALLOC;
}
(*insize) = rc;
return XENONE;
}
/************************************************************************
*
* Encrypt data in our buffer.
*
************************************************************************/
int tls_funcs_encrypt(struct tls_vars *mytls_vars, uint8_t *inbuf,
uint16_t insize)
{
uint8_t *encrdata = NULL;
int rc = 0;
TRACE
if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE))
return -1;
if (!xsup_assert((inbuf != NULL), "inbuf != NULL", FALSE))
return -1;
encrdata = Malloc(1500);
if (encrdata == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store encrypted"
" data!\n");
ipc_events_malloc_failed(NULL);
return XEMALLOC;
}
BIO_reset(mytls_vars->ssl_in);
BIO_reset(mytls_vars->ssl_out);
debug_printf(DEBUG_TLS_CORE, "inbuf (%d) :\n", insize);
debug_hex_dump(DEBUG_TLS_CORE, inbuf, insize);
rc = SSL_write(mytls_vars->ssl, inbuf, insize);
if (rc <= 0)
{
debug_printf(DEBUG_NORMAL, "Error sending data to OpenSSL to be "
"encrypted.\n");
rc = SSL_get_error(mytls_vars->ssl, rc);
debug_printf(DEBUG_NORMAL, "Error was : ");
switch (rc)
{
case SSL_ERROR_ZERO_RETURN:
debug_printf_nl(DEBUG_NORMAL, "zero return\n");
break;
case SSL_ERROR_WANT_READ:
debug_printf_nl(DEBUG_NORMAL, "want read\n");
break;
case SSL_ERROR_WANT_WRITE:
debug_printf_nl(DEBUG_NORMAL, "want write\n");
break;
case SSL_ERROR_WANT_CONNECT:
case SSL_ERROR_WANT_ACCEPT:
debug_printf_nl(DEBUG_NORMAL, "want connect/accept.\n");
break;
case SSL_ERROR_WANT_X509_LOOKUP:
debug_printf_nl(DEBUG_NORMAL, "want x509 lookup.\n");
break;
case SSL_ERROR_SYSCALL:
debug_printf_nl(DEBUG_NORMAL, "error syscall.\n");
break;
}
tls_funcs_process_error();
FREE(encrdata);
return -1;
}
if (mytls_vars->tlsoutqueue == NULL)
{
// Need to build a queue.
debug_printf(DEBUG_TLS_CORE, "First packet in a possible chain. Building queue.\n");
if (queue_create(&mytls_vars->tlsoutqueue) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't create queue for outgoing data!!\n");
return -1;
}
}
rc = BIO_read(mytls_vars->ssl_out, encrdata, 1500);
if (rc <= 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't read encrypted data from OpenSSL!"
"\n");
tls_funcs_process_error();
FREE(encrdata);
return -1;
}
if (queue_enqueue(&mytls_vars->tlsoutqueue, encrdata, rc) != 0)
{
debug_printf(DEBUG_NORMAL, "Failed to enqueue %d byte(s)!\n", rc);
FREE(encrdata);
return -1;
}
FREE(encrdata);
return XENONE;
}
/************************************************************************
*
* Clean up any memory that we used during our TLS session.
*
************************************************************************/
void tls_funcs_deinit(struct tls_vars *mytls_vars)
{
if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE))
return;
queue_destroy(&mytls_vars->tlsinqueue);
queue_destroy(&mytls_vars->tlsoutqueue);
// BIOs are freed by the SSL_free call below. Do not try to free them any other
// way, or you will segfault!
if (mytls_vars->ssl != NULL)
{
SSL_free(mytls_vars->ssl);
mytls_vars->ssl = NULL;
}
if (mytls_vars->ctx != NULL)
{
SSL_CTX_free(mytls_vars->ctx);
mytls_vars->ctx = NULL;
}
}
int tls_funcs_get_keyblock_len(struct tls_vars *mytls_vars)
{
EVP_CIPHER *key_material;
EVP_MD *hash;
int len;
key_material = (EVP_CIPHER *)mytls_vars->ssl->enc_read_ctx->cipher;
hash = (EVP_MD *)mytls_vars->ssl->read_hash;
len = 0;
len = (EVP_CIPHER_key_length(key_material) * 2);
len += (EVP_MD_size(hash) * 2);
len += (EVP_CIPHER_iv_length(key_material) * 2);
debug_printf(DEBUG_TLS_CORE, "Key block length used is %d byte(s).\n",
len);
return len;
}
int tls_funcs_set_hello_extension(struct tls_vars *myvars, int type,
void *data, int len)
{
#ifdef EAP_FAST
return SSL_set_hello_extension(myvars->ssl, type, data, len);
#else
return -1;
#endif
}
uint8_t *tls_funcs_get_client_random(struct tls_vars *myvars)
{
uint8_t *temp;
temp = Malloc(SSL3_RANDOM_SIZE);
if (temp == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store a "
"temporary copy of the TLS client random!\n");
ipc_events_malloc_failed(NULL);
return NULL;
}
memcpy(temp, myvars->ssl->s3->client_random, SSL3_RANDOM_SIZE);
return temp;
}
#ifdef EAP_FAST
static int tls_funcs_set_secret_cb(SSL *s, void *secret, int *secret_len,
STACK_OF(SSL_CIPHER) *peer_ciphers,
SSL_CIPHER **cipher, void *arg)
{
struct tls_vars *mytls_vars;
mytls_vars = (struct tls_vars *)arg;
debug_printf(DEBUG_NORMAL, "Secret CB called!\n");
memcpy(secret, mytls_vars->derived_shared_secret,
mytls_vars->derived_shared_secret_len);
(*secret_len) = mytls_vars->derived_shared_secret_len;
debug_printf(DEBUG_TLS_CORE, "Shared secret : \n");
debug_hex_dump(DEBUG_TLS_CORE, secret, (*secret_len));
return 1;
}
int tls_funcs_set_master_secret(struct tls_vars *myvars, uint8_t *new_secret,
uint16_t length)
{
if (!xsup_assert((myvars != NULL), "myvars != NULL", FALSE))
return -1;
if (!xsup_assert((new_secret != NULL), "new_secret != NULL", FALSE))
return -1;
myvars->derived_shared_secret = Malloc(length);
if (myvars->derived_shared_secret == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store derived "
"shared secret!\n");
ipc_events_malloc_failed(NULL);
return -1;
}
debug_printf(DEBUG_TLS_CORE, "Shared secret : \n");
debug_hex_dump(DEBUG_TLS_CORE, new_secret, length);
memcpy(myvars->derived_shared_secret, new_secret, length);
myvars->derived_shared_secret_len = length;
if (SSL_set_session_secret_cb(myvars->ssl, tls_funcs_set_secret_cb, myvars) != 1)
{
debug_printf(DEBUG_NORMAL, "Couldn't set the derived secret callback "
"function!\n");
return -1;
}
return 0;
}
#endif // EAP_FAST
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -