mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
Upgrade openssl from 1.1.0e to 1.1.1b, with source code. 4.0.78
This commit is contained in:
parent
8f1c992379
commit
96dbd7bced
1476 changed files with 616554 additions and 4 deletions
505
trunk/3rdparty/openssl-1.1-fit/ssl/bio_ssl.c
vendored
Normal file
505
trunk/3rdparty/openssl-1.1-fit/ssl/bio_ssl.c
vendored
Normal file
|
@ -0,0 +1,505 @@
|
|||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include "internal/bio.h"
|
||||
#include <openssl/err.h>
|
||||
#include "ssl_locl.h"
|
||||
|
||||
static int ssl_write(BIO *h, const char *buf, size_t size, size_t *written);
|
||||
static int ssl_read(BIO *b, char *buf, size_t size, size_t *readbytes);
|
||||
static int ssl_puts(BIO *h, const char *str);
|
||||
static long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int ssl_new(BIO *h);
|
||||
static int ssl_free(BIO *data);
|
||||
static long ssl_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
|
||||
typedef struct bio_ssl_st {
|
||||
SSL *ssl; /* The ssl handle :-) */
|
||||
/* re-negotiate every time the total number of bytes is this size */
|
||||
int num_renegotiates;
|
||||
unsigned long renegotiate_count;
|
||||
size_t byte_count;
|
||||
unsigned long renegotiate_timeout;
|
||||
unsigned long last_time;
|
||||
} BIO_SSL;
|
||||
|
||||
static const BIO_METHOD methods_sslp = {
|
||||
BIO_TYPE_SSL,
|
||||
"ssl",
|
||||
ssl_write,
|
||||
NULL, /* ssl_write_old, */
|
||||
ssl_read,
|
||||
NULL, /* ssl_read_old, */
|
||||
ssl_puts,
|
||||
NULL, /* ssl_gets, */
|
||||
ssl_ctrl,
|
||||
ssl_new,
|
||||
ssl_free,
|
||||
ssl_callback_ctrl,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_f_ssl(void)
|
||||
{
|
||||
return &methods_sslp;
|
||||
}
|
||||
|
||||
static int ssl_new(BIO *bi)
|
||||
{
|
||||
BIO_SSL *bs = OPENSSL_zalloc(sizeof(*bs));
|
||||
|
||||
if (bs == NULL) {
|
||||
BIOerr(BIO_F_SSL_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
BIO_set_init(bi, 0);
|
||||
BIO_set_data(bi, bs);
|
||||
/* Clear all flags */
|
||||
BIO_clear_flags(bi, ~0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ssl_free(BIO *a)
|
||||
{
|
||||
BIO_SSL *bs;
|
||||
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
bs = BIO_get_data(a);
|
||||
if (bs->ssl != NULL)
|
||||
SSL_shutdown(bs->ssl);
|
||||
if (BIO_get_shutdown(a)) {
|
||||
if (BIO_get_init(a))
|
||||
SSL_free(bs->ssl);
|
||||
/* Clear all flags */
|
||||
BIO_clear_flags(a, ~0);
|
||||
BIO_set_init(a, 0);
|
||||
}
|
||||
OPENSSL_free(bs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ssl_read(BIO *b, char *buf, size_t size, size_t *readbytes)
|
||||
{
|
||||
int ret = 1;
|
||||
BIO_SSL *sb;
|
||||
SSL *ssl;
|
||||
int retry_reason = 0;
|
||||
int r = 0;
|
||||
|
||||
if (buf == NULL)
|
||||
return 0;
|
||||
sb = BIO_get_data(b);
|
||||
ssl = sb->ssl;
|
||||
|
||||
BIO_clear_retry_flags(b);
|
||||
|
||||
ret = ssl_read_internal(ssl, buf, size, readbytes);
|
||||
|
||||
switch (SSL_get_error(ssl, ret)) {
|
||||
case SSL_ERROR_NONE:
|
||||
if (sb->renegotiate_count > 0) {
|
||||
sb->byte_count += *readbytes;
|
||||
if (sb->byte_count > sb->renegotiate_count) {
|
||||
sb->byte_count = 0;
|
||||
sb->num_renegotiates++;
|
||||
SSL_renegotiate(ssl);
|
||||
r = 1;
|
||||
}
|
||||
}
|
||||
if ((sb->renegotiate_timeout > 0) && (!r)) {
|
||||
unsigned long tm;
|
||||
|
||||
tm = (unsigned long)time(NULL);
|
||||
if (tm > sb->last_time + sb->renegotiate_timeout) {
|
||||
sb->last_time = tm;
|
||||
sb->num_renegotiates++;
|
||||
SSL_renegotiate(ssl);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
BIO_set_retry_read(b);
|
||||
break;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
BIO_set_retry_write(b);
|
||||
break;
|
||||
case SSL_ERROR_WANT_X509_LOOKUP:
|
||||
BIO_set_retry_special(b);
|
||||
retry_reason = BIO_RR_SSL_X509_LOOKUP;
|
||||
break;
|
||||
case SSL_ERROR_WANT_ACCEPT:
|
||||
BIO_set_retry_special(b);
|
||||
retry_reason = BIO_RR_ACCEPT;
|
||||
break;
|
||||
case SSL_ERROR_WANT_CONNECT:
|
||||
BIO_set_retry_special(b);
|
||||
retry_reason = BIO_RR_CONNECT;
|
||||
break;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
case SSL_ERROR_SSL:
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
BIO_set_retry_reason(b, retry_reason);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ssl_write(BIO *b, const char *buf, size_t size, size_t *written)
|
||||
{
|
||||
int ret, r = 0;
|
||||
int retry_reason = 0;
|
||||
SSL *ssl;
|
||||
BIO_SSL *bs;
|
||||
|
||||
if (buf == NULL)
|
||||
return 0;
|
||||
bs = BIO_get_data(b);
|
||||
ssl = bs->ssl;
|
||||
|
||||
BIO_clear_retry_flags(b);
|
||||
|
||||
ret = ssl_write_internal(ssl, buf, size, written);
|
||||
|
||||
switch (SSL_get_error(ssl, ret)) {
|
||||
case SSL_ERROR_NONE:
|
||||
if (bs->renegotiate_count > 0) {
|
||||
bs->byte_count += *written;
|
||||
if (bs->byte_count > bs->renegotiate_count) {
|
||||
bs->byte_count = 0;
|
||||
bs->num_renegotiates++;
|
||||
SSL_renegotiate(ssl);
|
||||
r = 1;
|
||||
}
|
||||
}
|
||||
if ((bs->renegotiate_timeout > 0) && (!r)) {
|
||||
unsigned long tm;
|
||||
|
||||
tm = (unsigned long)time(NULL);
|
||||
if (tm > bs->last_time + bs->renegotiate_timeout) {
|
||||
bs->last_time = tm;
|
||||
bs->num_renegotiates++;
|
||||
SSL_renegotiate(ssl);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
BIO_set_retry_write(b);
|
||||
break;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
BIO_set_retry_read(b);
|
||||
break;
|
||||
case SSL_ERROR_WANT_X509_LOOKUP:
|
||||
BIO_set_retry_special(b);
|
||||
retry_reason = BIO_RR_SSL_X509_LOOKUP;
|
||||
break;
|
||||
case SSL_ERROR_WANT_CONNECT:
|
||||
BIO_set_retry_special(b);
|
||||
retry_reason = BIO_RR_CONNECT;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
case SSL_ERROR_SSL:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
BIO_set_retry_reason(b, retry_reason);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
SSL **sslp, *ssl;
|
||||
BIO_SSL *bs, *dbs;
|
||||
BIO *dbio, *bio;
|
||||
long ret = 1;
|
||||
BIO *next;
|
||||
|
||||
bs = BIO_get_data(b);
|
||||
next = BIO_next(b);
|
||||
ssl = bs->ssl;
|
||||
if ((ssl == NULL) && (cmd != BIO_C_SET_SSL))
|
||||
return 0;
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
SSL_shutdown(ssl);
|
||||
|
||||
if (ssl->handshake_func == ssl->method->ssl_connect)
|
||||
SSL_set_connect_state(ssl);
|
||||
else if (ssl->handshake_func == ssl->method->ssl_accept)
|
||||
SSL_set_accept_state(ssl);
|
||||
|
||||
if (!SSL_clear(ssl)) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (next != NULL)
|
||||
ret = BIO_ctrl(next, cmd, num, ptr);
|
||||
else if (ssl->rbio != NULL)
|
||||
ret = BIO_ctrl(ssl->rbio, cmd, num, ptr);
|
||||
else
|
||||
ret = 1;
|
||||
break;
|
||||
case BIO_CTRL_INFO:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_C_SSL_MODE:
|
||||
if (num) /* client mode */
|
||||
SSL_set_connect_state(ssl);
|
||||
else
|
||||
SSL_set_accept_state(ssl);
|
||||
break;
|
||||
case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT:
|
||||
ret = bs->renegotiate_timeout;
|
||||
if (num < 60)
|
||||
num = 5;
|
||||
bs->renegotiate_timeout = (unsigned long)num;
|
||||
bs->last_time = (unsigned long)time(NULL);
|
||||
break;
|
||||
case BIO_C_SET_SSL_RENEGOTIATE_BYTES:
|
||||
ret = bs->renegotiate_count;
|
||||
if ((long)num >= 512)
|
||||
bs->renegotiate_count = (unsigned long)num;
|
||||
break;
|
||||
case BIO_C_GET_SSL_NUM_RENEGOTIATES:
|
||||
ret = bs->num_renegotiates;
|
||||
break;
|
||||
case BIO_C_SET_SSL:
|
||||
if (ssl != NULL) {
|
||||
ssl_free(b);
|
||||
if (!ssl_new(b))
|
||||
return 0;
|
||||
}
|
||||
BIO_set_shutdown(b, num);
|
||||
ssl = (SSL *)ptr;
|
||||
bs->ssl = ssl;
|
||||
bio = SSL_get_rbio(ssl);
|
||||
if (bio != NULL) {
|
||||
if (next != NULL)
|
||||
BIO_push(bio, next);
|
||||
BIO_set_next(b, bio);
|
||||
BIO_up_ref(bio);
|
||||
}
|
||||
BIO_set_init(b, 1);
|
||||
break;
|
||||
case BIO_C_GET_SSL:
|
||||
if (ptr != NULL) {
|
||||
sslp = (SSL **)ptr;
|
||||
*sslp = ssl;
|
||||
} else
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = BIO_get_shutdown(b);
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
BIO_set_shutdown(b, (int)num);
|
||||
break;
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = BIO_ctrl(ssl->wbio, cmd, num, ptr);
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
ret = SSL_pending(ssl);
|
||||
if (ret == 0)
|
||||
ret = BIO_pending(ssl->rbio);
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
BIO_clear_retry_flags(b);
|
||||
ret = BIO_ctrl(ssl->wbio, cmd, num, ptr);
|
||||
BIO_copy_next_retry(b);
|
||||
break;
|
||||
case BIO_CTRL_PUSH:
|
||||
if ((next != NULL) && (next != ssl->rbio)) {
|
||||
/*
|
||||
* We are going to pass ownership of next to the SSL object...but
|
||||
* we don't own a reference to pass yet - so up ref
|
||||
*/
|
||||
BIO_up_ref(next);
|
||||
SSL_set_bio(ssl, next, next);
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_POP:
|
||||
/* Only detach if we are the BIO explicitly being popped */
|
||||
if (b == ptr) {
|
||||
/* This will clear the reference we obtained during push */
|
||||
SSL_set_bio(ssl, NULL, NULL);
|
||||
}
|
||||
break;
|
||||
case BIO_C_DO_STATE_MACHINE:
|
||||
BIO_clear_retry_flags(b);
|
||||
|
||||
BIO_set_retry_reason(b, 0);
|
||||
ret = (int)SSL_do_handshake(ssl);
|
||||
|
||||
switch (SSL_get_error(ssl, (int)ret)) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
BIO_set_flags(b, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
|
||||
break;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
BIO_set_flags(b, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
|
||||
break;
|
||||
case SSL_ERROR_WANT_CONNECT:
|
||||
BIO_set_flags(b, BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY);
|
||||
BIO_set_retry_reason(b, BIO_get_retry_reason(next));
|
||||
break;
|
||||
case SSL_ERROR_WANT_X509_LOOKUP:
|
||||
BIO_set_retry_special(b);
|
||||
BIO_set_retry_reason(b, BIO_RR_SSL_X509_LOOKUP);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
dbio = (BIO *)ptr;
|
||||
dbs = BIO_get_data(dbio);
|
||||
SSL_free(dbs->ssl);
|
||||
dbs->ssl = SSL_dup(ssl);
|
||||
dbs->num_renegotiates = bs->num_renegotiates;
|
||||
dbs->renegotiate_count = bs->renegotiate_count;
|
||||
dbs->byte_count = bs->byte_count;
|
||||
dbs->renegotiate_timeout = bs->renegotiate_timeout;
|
||||
dbs->last_time = bs->last_time;
|
||||
ret = (dbs->ssl != NULL);
|
||||
break;
|
||||
case BIO_C_GET_FD:
|
||||
ret = BIO_ctrl(ssl->rbio, cmd, num, ptr);
|
||||
break;
|
||||
case BIO_CTRL_SET_CALLBACK:
|
||||
ret = 0; /* use callback ctrl */
|
||||
break;
|
||||
default:
|
||||
ret = BIO_ctrl(ssl->rbio, cmd, num, ptr);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long ssl_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
|
||||
{
|
||||
SSL *ssl;
|
||||
BIO_SSL *bs;
|
||||
long ret = 1;
|
||||
|
||||
bs = BIO_get_data(b);
|
||||
ssl = bs->ssl;
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_SET_CALLBACK:
|
||||
ret = BIO_callback_ctrl(ssl->rbio, cmd, fp);
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ssl_puts(BIO *bp, const char *str)
|
||||
{
|
||||
int n, ret;
|
||||
|
||||
n = strlen(str);
|
||||
ret = BIO_write(bp, str, n);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx)
|
||||
{
|
||||
#ifndef OPENSSL_NO_SOCK
|
||||
BIO *ret = NULL, *buf = NULL, *ssl = NULL;
|
||||
|
||||
if ((buf = BIO_new(BIO_f_buffer())) == NULL)
|
||||
return NULL;
|
||||
if ((ssl = BIO_new_ssl_connect(ctx)) == NULL)
|
||||
goto err;
|
||||
if ((ret = BIO_push(buf, ssl)) == NULL)
|
||||
goto err;
|
||||
return ret;
|
||||
err:
|
||||
BIO_free(buf);
|
||||
BIO_free(ssl);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BIO *BIO_new_ssl_connect(SSL_CTX *ctx)
|
||||
{
|
||||
#ifndef OPENSSL_NO_SOCK
|
||||
BIO *ret = NULL, *con = NULL, *ssl = NULL;
|
||||
|
||||
if ((con = BIO_new(BIO_s_connect())) == NULL)
|
||||
return NULL;
|
||||
if ((ssl = BIO_new_ssl(ctx, 1)) == NULL)
|
||||
goto err;
|
||||
if ((ret = BIO_push(ssl, con)) == NULL)
|
||||
goto err;
|
||||
return ret;
|
||||
err:
|
||||
BIO_free(con);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BIO *BIO_new_ssl(SSL_CTX *ctx, int client)
|
||||
{
|
||||
BIO *ret;
|
||||
SSL *ssl;
|
||||
|
||||
if ((ret = BIO_new(BIO_f_ssl())) == NULL)
|
||||
return NULL;
|
||||
if ((ssl = SSL_new(ctx)) == NULL) {
|
||||
BIO_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
if (client)
|
||||
SSL_set_connect_state(ssl);
|
||||
else
|
||||
SSL_set_accept_state(ssl);
|
||||
|
||||
BIO_set_ssl(ret, ssl, BIO_CLOSE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_ssl_copy_session_id(BIO *t, BIO *f)
|
||||
{
|
||||
BIO_SSL *tdata, *fdata;
|
||||
t = BIO_find_type(t, BIO_TYPE_SSL);
|
||||
f = BIO_find_type(f, BIO_TYPE_SSL);
|
||||
if ((t == NULL) || (f == NULL))
|
||||
return 0;
|
||||
tdata = BIO_get_data(t);
|
||||
fdata = BIO_get_data(f);
|
||||
if ((tdata->ssl == NULL) || (fdata->ssl == NULL))
|
||||
return 0;
|
||||
if (!SSL_copy_session_id(tdata->ssl, (fdata->ssl)))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BIO_ssl_shutdown(BIO *b)
|
||||
{
|
||||
BIO_SSL *bdata;
|
||||
|
||||
for (; b != NULL; b = BIO_next(b)) {
|
||||
if (BIO_method_type(b) != BIO_TYPE_SSL)
|
||||
continue;
|
||||
bdata = BIO_get_data(b);
|
||||
if (bdata != NULL && bdata->ssl != NULL)
|
||||
SSL_shutdown(bdata->ssl);
|
||||
}
|
||||
}
|
15
trunk/3rdparty/openssl-1.1-fit/ssl/build.info
vendored
Normal file
15
trunk/3rdparty/openssl-1.1-fit/ssl/build.info
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
LIBS=../libssl
|
||||
SOURCE[../libssl]=\
|
||||
pqueue.c packet.c \
|
||||
statem/statem_srvr.c statem/statem_clnt.c s3_lib.c s3_enc.c record/rec_layer_s3.c \
|
||||
statem/statem_lib.c statem/extensions.c statem/extensions_srvr.c \
|
||||
statem/extensions_clnt.c statem/extensions_cust.c s3_cbc.c s3_msg.c \
|
||||
methods.c t1_lib.c t1_enc.c tls13_enc.c \
|
||||
d1_lib.c record/rec_layer_d1.c d1_msg.c \
|
||||
statem/statem_dtls.c d1_srtp.c \
|
||||
ssl_lib.c ssl_cert.c ssl_sess.c \
|
||||
ssl_ciph.c ssl_stat.c ssl_rsa.c \
|
||||
ssl_asn1.c ssl_txt.c ssl_init.c ssl_conf.c ssl_mcnf.c \
|
||||
bio_ssl.c ssl_err.c tls_srp.c t1_trce.c ssl_utst.c \
|
||||
record/ssl3_buffer.c record/ssl3_record.c record/dtls1_bitmap.c \
|
||||
statem/statem.c record/ssl3_record_tls13.c
|
972
trunk/3rdparty/openssl-1.1-fit/ssl/d1_lib.c
vendored
Normal file
972
trunk/3rdparty/openssl-1.1-fit/ssl/d1_lib.c
vendored
Normal file
|
@ -0,0 +1,972 @@
|
|||
/*
|
||||
* Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "e_os.h"
|
||||
#include <stdio.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/rand.h>
|
||||
#include "ssl_locl.h"
|
||||
|
||||
static void get_current_time(struct timeval *t);
|
||||
static int dtls1_handshake_write(SSL *s);
|
||||
static size_t dtls1_link_min_mtu(void);
|
||||
|
||||
/* XDTLS: figure out the right values */
|
||||
static const size_t g_probable_mtu[] = { 1500, 512, 256 };
|
||||
|
||||
const SSL3_ENC_METHOD DTLSv1_enc_data = {
|
||||
tls1_enc,
|
||||
tls1_mac,
|
||||
tls1_setup_key_block,
|
||||
tls1_generate_master_secret,
|
||||
tls1_change_cipher_state,
|
||||
tls1_final_finish_mac,
|
||||
TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
|
||||
TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
|
||||
tls1_alert_code,
|
||||
tls1_export_keying_material,
|
||||
SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV,
|
||||
dtls1_set_handshake_header,
|
||||
dtls1_close_construct_packet,
|
||||
dtls1_handshake_write
|
||||
};
|
||||
|
||||
const SSL3_ENC_METHOD DTLSv1_2_enc_data = {
|
||||
tls1_enc,
|
||||
tls1_mac,
|
||||
tls1_setup_key_block,
|
||||
tls1_generate_master_secret,
|
||||
tls1_change_cipher_state,
|
||||
tls1_final_finish_mac,
|
||||
TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
|
||||
TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
|
||||
tls1_alert_code,
|
||||
tls1_export_keying_material,
|
||||
SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS
|
||||
| SSL_ENC_FLAG_SHA256_PRF | SSL_ENC_FLAG_TLS1_2_CIPHERS,
|
||||
dtls1_set_handshake_header,
|
||||
dtls1_close_construct_packet,
|
||||
dtls1_handshake_write
|
||||
};
|
||||
|
||||
long dtls1_default_timeout(void)
|
||||
{
|
||||
/*
|
||||
* 2 hours, the 24 hours mentioned in the DTLSv1 spec is way too long for
|
||||
* http, the cache would over fill
|
||||
*/
|
||||
return (60 * 60 * 2);
|
||||
}
|
||||
|
||||
int dtls1_new(SSL *s)
|
||||
{
|
||||
DTLS1_STATE *d1;
|
||||
|
||||
if (!DTLS_RECORD_LAYER_new(&s->rlayer)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ssl3_new(s))
|
||||
return 0;
|
||||
if ((d1 = OPENSSL_zalloc(sizeof(*d1))) == NULL) {
|
||||
ssl3_free(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
d1->buffered_messages = pqueue_new();
|
||||
d1->sent_messages = pqueue_new();
|
||||
|
||||
if (s->server) {
|
||||
d1->cookie_len = sizeof(s->d1->cookie);
|
||||
}
|
||||
|
||||
d1->link_mtu = 0;
|
||||
d1->mtu = 0;
|
||||
|
||||
if (d1->buffered_messages == NULL || d1->sent_messages == NULL) {
|
||||
pqueue_free(d1->buffered_messages);
|
||||
pqueue_free(d1->sent_messages);
|
||||
OPENSSL_free(d1);
|
||||
ssl3_free(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->d1 = d1;
|
||||
|
||||
if (!s->method->ssl_clear(s))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void dtls1_clear_queues(SSL *s)
|
||||
{
|
||||
dtls1_clear_received_buffer(s);
|
||||
dtls1_clear_sent_buffer(s);
|
||||
}
|
||||
|
||||
void dtls1_clear_received_buffer(SSL *s)
|
||||
{
|
||||
pitem *item = NULL;
|
||||
hm_fragment *frag = NULL;
|
||||
|
||||
while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
|
||||
frag = (hm_fragment *)item->data;
|
||||
dtls1_hm_fragment_free(frag);
|
||||
pitem_free(item);
|
||||
}
|
||||
}
|
||||
|
||||
void dtls1_clear_sent_buffer(SSL *s)
|
||||
{
|
||||
pitem *item = NULL;
|
||||
hm_fragment *frag = NULL;
|
||||
|
||||
while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) {
|
||||
frag = (hm_fragment *)item->data;
|
||||
dtls1_hm_fragment_free(frag);
|
||||
pitem_free(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dtls1_free(SSL *s)
|
||||
{
|
||||
DTLS_RECORD_LAYER_free(&s->rlayer);
|
||||
|
||||
ssl3_free(s);
|
||||
|
||||
dtls1_clear_queues(s);
|
||||
|
||||
pqueue_free(s->d1->buffered_messages);
|
||||
pqueue_free(s->d1->sent_messages);
|
||||
|
||||
OPENSSL_free(s->d1);
|
||||
s->d1 = NULL;
|
||||
}
|
||||
|
||||
int dtls1_clear(SSL *s)
|
||||
{
|
||||
pqueue *buffered_messages;
|
||||
pqueue *sent_messages;
|
||||
size_t mtu;
|
||||
size_t link_mtu;
|
||||
|
||||
DTLS_RECORD_LAYER_clear(&s->rlayer);
|
||||
|
||||
if (s->d1) {
|
||||
DTLS_timer_cb timer_cb = s->d1->timer_cb;
|
||||
|
||||
buffered_messages = s->d1->buffered_messages;
|
||||
sent_messages = s->d1->sent_messages;
|
||||
mtu = s->d1->mtu;
|
||||
link_mtu = s->d1->link_mtu;
|
||||
|
||||
dtls1_clear_queues(s);
|
||||
|
||||
memset(s->d1, 0, sizeof(*s->d1));
|
||||
|
||||
/* Restore the timer callback from previous state */
|
||||
s->d1->timer_cb = timer_cb;
|
||||
|
||||
if (s->server) {
|
||||
s->d1->cookie_len = sizeof(s->d1->cookie);
|
||||
}
|
||||
|
||||
if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) {
|
||||
s->d1->mtu = mtu;
|
||||
s->d1->link_mtu = link_mtu;
|
||||
}
|
||||
|
||||
s->d1->buffered_messages = buffered_messages;
|
||||
s->d1->sent_messages = sent_messages;
|
||||
}
|
||||
|
||||
if (!ssl3_clear(s))
|
||||
return 0;
|
||||
|
||||
if (s->method->version == DTLS_ANY_VERSION)
|
||||
s->version = DTLS_MAX_VERSION;
|
||||
#ifndef OPENSSL_NO_DTLS1_METHOD
|
||||
else if (s->options & SSL_OP_CISCO_ANYCONNECT)
|
||||
s->client_version = s->version = DTLS1_BAD_VER;
|
||||
#endif
|
||||
else
|
||||
s->version = s->method->version;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case DTLS_CTRL_GET_TIMEOUT:
|
||||
if (dtls1_get_timeout(s, (struct timeval *)parg) != NULL) {
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
case DTLS_CTRL_HANDLE_TIMEOUT:
|
||||
ret = dtls1_handle_timeout(s);
|
||||
break;
|
||||
case DTLS_CTRL_SET_LINK_MTU:
|
||||
if (larg < (long)dtls1_link_min_mtu())
|
||||
return 0;
|
||||
s->d1->link_mtu = larg;
|
||||
return 1;
|
||||
case DTLS_CTRL_GET_LINK_MIN_MTU:
|
||||
return (long)dtls1_link_min_mtu();
|
||||
case SSL_CTRL_SET_MTU:
|
||||
/*
|
||||
* We may not have a BIO set yet so can't call dtls1_min_mtu()
|
||||
* We'll have to make do with dtls1_link_min_mtu() and max overhead
|
||||
*/
|
||||
if (larg < (long)dtls1_link_min_mtu() - DTLS1_MAX_MTU_OVERHEAD)
|
||||
return 0;
|
||||
s->d1->mtu = larg;
|
||||
return larg;
|
||||
default:
|
||||
ret = ssl3_ctrl(s, cmd, larg, parg);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dtls1_start_timer(SSL *s)
|
||||
{
|
||||
unsigned int sec, usec;
|
||||
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
/* Disable timer for SCTP */
|
||||
if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
|
||||
memset(&s->d1->next_timeout, 0, sizeof(s->d1->next_timeout));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If timer is not set, initialize duration with 1 second or
|
||||
* a user-specified value if the timer callback is installed.
|
||||
*/
|
||||
if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
|
||||
|
||||
if (s->d1->timer_cb != NULL)
|
||||
s->d1->timeout_duration_us = s->d1->timer_cb(s, 0);
|
||||
else
|
||||
s->d1->timeout_duration_us = 1000000;
|
||||
}
|
||||
|
||||
/* Set timeout to current time */
|
||||
get_current_time(&(s->d1->next_timeout));
|
||||
|
||||
/* Add duration to current time */
|
||||
|
||||
sec = s->d1->timeout_duration_us / 1000000;
|
||||
usec = s->d1->timeout_duration_us - (sec * 1000000);
|
||||
|
||||
s->d1->next_timeout.tv_sec += sec;
|
||||
s->d1->next_timeout.tv_usec += usec;
|
||||
|
||||
if (s->d1->next_timeout.tv_usec >= 1000000) {
|
||||
s->d1->next_timeout.tv_sec++;
|
||||
s->d1->next_timeout.tv_usec -= 1000000;
|
||||
}
|
||||
|
||||
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
|
||||
&(s->d1->next_timeout));
|
||||
}
|
||||
|
||||
struct timeval *dtls1_get_timeout(SSL *s, struct timeval *timeleft)
|
||||
{
|
||||
struct timeval timenow;
|
||||
|
||||
/* If no timeout is set, just return NULL */
|
||||
if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get current time */
|
||||
get_current_time(&timenow);
|
||||
|
||||
/* If timer already expired, set remaining time to 0 */
|
||||
if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
|
||||
(s->d1->next_timeout.tv_sec == timenow.tv_sec &&
|
||||
s->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
|
||||
memset(timeleft, 0, sizeof(*timeleft));
|
||||
return timeleft;
|
||||
}
|
||||
|
||||
/* Calculate time left until timer expires */
|
||||
memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
|
||||
timeleft->tv_sec -= timenow.tv_sec;
|
||||
timeleft->tv_usec -= timenow.tv_usec;
|
||||
if (timeleft->tv_usec < 0) {
|
||||
timeleft->tv_sec--;
|
||||
timeleft->tv_usec += 1000000;
|
||||
}
|
||||
|
||||
/*
|
||||
* If remaining time is less than 15 ms, set it to 0 to prevent issues
|
||||
* because of small divergences with socket timeouts.
|
||||
*/
|
||||
if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) {
|
||||
memset(timeleft, 0, sizeof(*timeleft));
|
||||
}
|
||||
|
||||
return timeleft;
|
||||
}
|
||||
|
||||
int dtls1_is_timer_expired(SSL *s)
|
||||
{
|
||||
struct timeval timeleft;
|
||||
|
||||
/* Get time left until timeout, return false if no timer running */
|
||||
if (dtls1_get_timeout(s, &timeleft) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return false if timer is not expired yet */
|
||||
if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Timer expired, so return true */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void dtls1_double_timeout(SSL *s)
|
||||
{
|
||||
s->d1->timeout_duration_us *= 2;
|
||||
if (s->d1->timeout_duration_us > 60000000)
|
||||
s->d1->timeout_duration_us = 60000000;
|
||||
dtls1_start_timer(s);
|
||||
}
|
||||
|
||||
void dtls1_stop_timer(SSL *s)
|
||||
{
|
||||
/* Reset everything */
|
||||
memset(&s->d1->timeout, 0, sizeof(s->d1->timeout));
|
||||
memset(&s->d1->next_timeout, 0, sizeof(s->d1->next_timeout));
|
||||
s->d1->timeout_duration_us = 1000000;
|
||||
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
|
||||
&(s->d1->next_timeout));
|
||||
/* Clear retransmission buffer */
|
||||
dtls1_clear_sent_buffer(s);
|
||||
}
|
||||
|
||||
int dtls1_check_timeout_num(SSL *s)
|
||||
{
|
||||
size_t mtu;
|
||||
|
||||
s->d1->timeout.num_alerts++;
|
||||
|
||||
/* Reduce MTU after 2 unsuccessful retransmissions */
|
||||
if (s->d1->timeout.num_alerts > 2
|
||||
&& !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
|
||||
mtu =
|
||||
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
|
||||
if (mtu < s->d1->mtu)
|
||||
s->d1->mtu = mtu;
|
||||
}
|
||||
|
||||
if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
|
||||
/* fail the connection, enough alerts have been sent */
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS1_CHECK_TIMEOUT_NUM,
|
||||
SSL_R_READ_TIMEOUT_EXPIRED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dtls1_handle_timeout(SSL *s)
|
||||
{
|
||||
/* if no timer is expired, don't do anything */
|
||||
if (!dtls1_is_timer_expired(s)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->d1->timer_cb != NULL)
|
||||
s->d1->timeout_duration_us = s->d1->timer_cb(s, s->d1->timeout_duration_us);
|
||||
else
|
||||
dtls1_double_timeout(s);
|
||||
|
||||
if (dtls1_check_timeout_num(s) < 0) {
|
||||
/* SSLfatal() already called */
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->d1->timeout.read_timeouts++;
|
||||
if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) {
|
||||
s->d1->timeout.read_timeouts = 1;
|
||||
}
|
||||
|
||||
dtls1_start_timer(s);
|
||||
/* Calls SSLfatal() if required */
|
||||
return dtls1_retransmit_buffered_messages(s);
|
||||
}
|
||||
|
||||
static void get_current_time(struct timeval *t)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
SYSTEMTIME st;
|
||||
union {
|
||||
unsigned __int64 ul;
|
||||
FILETIME ft;
|
||||
} now;
|
||||
|
||||
GetSystemTime(&st);
|
||||
SystemTimeToFileTime(&st, &now.ft);
|
||||
/* re-bias to 1/1/1970 */
|
||||
# ifdef __MINGW32__
|
||||
now.ul -= 116444736000000000ULL;
|
||||
# else
|
||||
/* *INDENT-OFF* */
|
||||
now.ul -= 116444736000000000UI64;
|
||||
/* *INDENT-ON* */
|
||||
# endif
|
||||
t->tv_sec = (long)(now.ul / 10000000);
|
||||
t->tv_usec = ((int)(now.ul % 10000000)) / 10;
|
||||
#else
|
||||
gettimeofday(t, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define LISTEN_SUCCESS 2
|
||||
#define LISTEN_SEND_VERIFY_REQUEST 1
|
||||
|
||||
#ifndef OPENSSL_NO_SOCK
|
||||
int DTLSv1_listen(SSL *s, BIO_ADDR *client)
|
||||
{
|
||||
int next, n, ret = 0;
|
||||
unsigned char cookie[DTLS1_COOKIE_LENGTH];
|
||||
unsigned char seq[SEQ_NUM_SIZE];
|
||||
const unsigned char *data;
|
||||
unsigned char *buf, *wbuf;
|
||||
size_t fragoff, fraglen, msglen, reclen, align = 0;
|
||||
unsigned int rectype, versmajor, msgseq, msgtype, clientvers, cookielen;
|
||||
BIO *rbio, *wbio;
|
||||
BIO_ADDR *tmpclient = NULL;
|
||||
PACKET pkt, msgpkt, msgpayload, session, cookiepkt;
|
||||
|
||||
if (s->handshake_func == NULL) {
|
||||
/* Not properly initialized yet */
|
||||
SSL_set_accept_state(s);
|
||||
}
|
||||
|
||||
/* Ensure there is no state left over from a previous invocation */
|
||||
if (!SSL_clear(s))
|
||||
return -1;
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
rbio = SSL_get_rbio(s);
|
||||
wbio = SSL_get_wbio(s);
|
||||
|
||||
if (!rbio || !wbio) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BIO_NOT_SET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: This check deliberately excludes DTLS1_BAD_VER because that version
|
||||
* requires the MAC to be calculated *including* the first ClientHello
|
||||
* (without the cookie). Since DTLSv1_listen is stateless that cannot be
|
||||
* supported. DTLS1_BAD_VER must use cookies in a stateful manner (e.g. via
|
||||
* SSL_accept)
|
||||
*/
|
||||
if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNSUPPORTED_SSL_VERSION);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ssl3_setup_buffers(s)) {
|
||||
/* SSLerr already called */
|
||||
return -1;
|
||||
}
|
||||
buf = RECORD_LAYER_get_rbuf(&s->rlayer)->buf;
|
||||
wbuf = RECORD_LAYER_get_wbuf(&s->rlayer)[0].buf;
|
||||
#if defined(SSL3_ALIGN_PAYLOAD)
|
||||
# if SSL3_ALIGN_PAYLOAD != 0
|
||||
/*
|
||||
* Using SSL3_RT_HEADER_LENGTH here instead of DTLS1_RT_HEADER_LENGTH for
|
||||
* consistency with ssl3_read_n. In practice it should make no difference
|
||||
* for sensible values of SSL3_ALIGN_PAYLOAD because the difference between
|
||||
* SSL3_RT_HEADER_LENGTH and DTLS1_RT_HEADER_LENGTH is exactly 8
|
||||
*/
|
||||
align = (size_t)buf + SSL3_RT_HEADER_LENGTH;
|
||||
align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD);
|
||||
# endif
|
||||
#endif
|
||||
buf += align;
|
||||
|
||||
do {
|
||||
/* Get a packet */
|
||||
|
||||
clear_sys_error();
|
||||
n = BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH
|
||||
+ DTLS1_RT_HEADER_LENGTH);
|
||||
if (n <= 0) {
|
||||
if (BIO_should_retry(rbio)) {
|
||||
/* Non-blocking IO */
|
||||
goto end;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!PACKET_buf_init(&pkt, buf, n)) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the received record. If there are any problems with it we just
|
||||
* dump it - with no alert. RFC6347 says this "Unlike TLS, DTLS is
|
||||
* resilient in the face of invalid records (e.g., invalid formatting,
|
||||
* length, MAC, etc.). In general, invalid records SHOULD be silently
|
||||
* discarded, thus preserving the association; however, an error MAY be
|
||||
* logged for diagnostic purposes."
|
||||
*/
|
||||
|
||||
/* this packet contained a partial record, dump it */
|
||||
if (n < DTLS1_RT_HEADER_LENGTH) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_RECORD_TOO_SMALL);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (s->msg_callback)
|
||||
s->msg_callback(0, 0, SSL3_RT_HEADER, buf,
|
||||
DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);
|
||||
|
||||
/* Get the record header */
|
||||
if (!PACKET_get_1(&pkt, &rectype)
|
||||
|| !PACKET_get_1(&pkt, &versmajor)) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (rectype != SSL3_RT_HANDSHAKE) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check record version number. We only check that the major version is
|
||||
* the same.
|
||||
*/
|
||||
if (versmajor != DTLS1_VERSION_MAJOR) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!PACKET_forward(&pkt, 1)
|
||||
/* Save the sequence number: 64 bits, with top 2 bytes = epoch */
|
||||
|| !PACKET_copy_bytes(&pkt, seq, SEQ_NUM_SIZE)
|
||||
|| !PACKET_get_length_prefixed_2(&pkt, &msgpkt)) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
|
||||
goto end;
|
||||
}
|
||||
reclen = PACKET_remaining(&msgpkt);
|
||||
/*
|
||||
* We allow data remaining at the end of the packet because there could
|
||||
* be a second record (but we ignore it)
|
||||
*/
|
||||
|
||||
/* This is an initial ClientHello so the epoch has to be 0 */
|
||||
if (seq[0] != 0 || seq[1] != 0) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Get a pointer to the raw message for the later callback */
|
||||
data = PACKET_data(&msgpkt);
|
||||
|
||||
/* Finished processing the record header, now process the message */
|
||||
if (!PACKET_get_1(&msgpkt, &msgtype)
|
||||
|| !PACKET_get_net_3_len(&msgpkt, &msglen)
|
||||
|| !PACKET_get_net_2(&msgpkt, &msgseq)
|
||||
|| !PACKET_get_net_3_len(&msgpkt, &fragoff)
|
||||
|| !PACKET_get_net_3_len(&msgpkt, &fraglen)
|
||||
|| !PACKET_get_sub_packet(&msgpkt, &msgpayload, fraglen)
|
||||
|| PACKET_remaining(&msgpkt) != 0) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (msgtype != SSL3_MT_CLIENT_HELLO) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Message sequence number can only be 0 or 1 */
|
||||
if (msgseq > 2) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_INVALID_SEQUENCE_NUMBER);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't support fragment reassembly for ClientHellos whilst
|
||||
* listening because that would require server side state (which is
|
||||
* against the whole point of the ClientHello/HelloVerifyRequest
|
||||
* mechanism). Instead we only look at the first ClientHello fragment
|
||||
* and require that the cookie must be contained within it.
|
||||
*/
|
||||
if (fragoff != 0 || fraglen > msglen) {
|
||||
/* Non initial ClientHello fragment (or bad fragment) */
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_FRAGMENTED_CLIENT_HELLO);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (s->msg_callback)
|
||||
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, data,
|
||||
fraglen + DTLS1_HM_HEADER_LENGTH, s,
|
||||
s->msg_callback_arg);
|
||||
|
||||
if (!PACKET_get_net_2(&msgpayload, &clientvers)) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify client version is supported
|
||||
*/
|
||||
if (DTLS_VERSION_LT(clientvers, (unsigned int)s->method->version) &&
|
||||
s->method->version != DTLS_ANY_VERSION) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_WRONG_VERSION_NUMBER);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!PACKET_forward(&msgpayload, SSL3_RANDOM_SIZE)
|
||||
|| !PACKET_get_length_prefixed_1(&msgpayload, &session)
|
||||
|| !PACKET_get_length_prefixed_1(&msgpayload, &cookiepkt)) {
|
||||
/*
|
||||
* Could be malformed or the cookie does not fit within the initial
|
||||
* ClientHello fragment. Either way we can't handle it.
|
||||
*/
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we have a cookie or not. If not we need to send a
|
||||
* HelloVerifyRequest.
|
||||
*/
|
||||
if (PACKET_remaining(&cookiepkt) == 0) {
|
||||
next = LISTEN_SEND_VERIFY_REQUEST;
|
||||
} else {
|
||||
/*
|
||||
* We have a cookie, so lets check it.
|
||||
*/
|
||||
if (s->ctx->app_verify_cookie_cb == NULL) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_NO_VERIFY_COOKIE_CALLBACK);
|
||||
/* This is fatal */
|
||||
return -1;
|
||||
}
|
||||
if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&cookiepkt),
|
||||
(unsigned int)PACKET_remaining(&cookiepkt)) == 0) {
|
||||
/*
|
||||
* We treat invalid cookies in the same was as no cookie as
|
||||
* per RFC6347
|
||||
*/
|
||||
next = LISTEN_SEND_VERIFY_REQUEST;
|
||||
} else {
|
||||
/* Cookie verification succeeded */
|
||||
next = LISTEN_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (next == LISTEN_SEND_VERIFY_REQUEST) {
|
||||
WPACKET wpkt;
|
||||
unsigned int version;
|
||||
size_t wreclen;
|
||||
|
||||
/*
|
||||
* There was no cookie in the ClientHello so we need to send a
|
||||
* HelloVerifyRequest. If this fails we do not worry about trying
|
||||
* to resend, we just drop it.
|
||||
*/
|
||||
|
||||
/* Generate the cookie */
|
||||
if (s->ctx->app_gen_cookie_cb == NULL ||
|
||||
s->ctx->app_gen_cookie_cb(s, cookie, &cookielen) == 0 ||
|
||||
cookielen > 255) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
|
||||
/* This is fatal */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special case: for hello verify request, client version 1.0 and we
|
||||
* haven't decided which version to use yet send back using version
|
||||
* 1.0 header: otherwise some clients will ignore it.
|
||||
*/
|
||||
version = (s->method->version == DTLS_ANY_VERSION) ? DTLS1_VERSION
|
||||
: s->version;
|
||||
|
||||
/* Construct the record and message headers */
|
||||
if (!WPACKET_init_static_len(&wpkt,
|
||||
wbuf,
|
||||
ssl_get_max_send_fragment(s)
|
||||
+ DTLS1_RT_HEADER_LENGTH,
|
||||
0)
|
||||
|| !WPACKET_put_bytes_u8(&wpkt, SSL3_RT_HANDSHAKE)
|
||||
|| !WPACKET_put_bytes_u16(&wpkt, version)
|
||||
/*
|
||||
* Record sequence number is always the same as in the
|
||||
* received ClientHello
|
||||
*/
|
||||
|| !WPACKET_memcpy(&wpkt, seq, SEQ_NUM_SIZE)
|
||||
/* End of record, start sub packet for message */
|
||||
|| !WPACKET_start_sub_packet_u16(&wpkt)
|
||||
/* Message type */
|
||||
|| !WPACKET_put_bytes_u8(&wpkt,
|
||||
DTLS1_MT_HELLO_VERIFY_REQUEST)
|
||||
/*
|
||||
* Message length - doesn't follow normal TLS convention:
|
||||
* the length isn't the last thing in the message header.
|
||||
* We'll need to fill this in later when we know the
|
||||
* length. Set it to zero for now
|
||||
*/
|
||||
|| !WPACKET_put_bytes_u24(&wpkt, 0)
|
||||
/*
|
||||
* Message sequence number is always 0 for a
|
||||
* HelloVerifyRequest
|
||||
*/
|
||||
|| !WPACKET_put_bytes_u16(&wpkt, 0)
|
||||
/*
|
||||
* We never fragment a HelloVerifyRequest, so fragment
|
||||
* offset is 0
|
||||
*/
|
||||
|| !WPACKET_put_bytes_u24(&wpkt, 0)
|
||||
/*
|
||||
* Fragment length is the same as message length, but
|
||||
* this *is* the last thing in the message header so we
|
||||
* can just start a sub-packet. No need to come back
|
||||
* later for this one.
|
||||
*/
|
||||
|| !WPACKET_start_sub_packet_u24(&wpkt)
|
||||
/* Create the actual HelloVerifyRequest body */
|
||||
|| !dtls_raw_hello_verify_request(&wpkt, cookie, cookielen)
|
||||
/* Close message body */
|
||||
|| !WPACKET_close(&wpkt)
|
||||
/* Close record body */
|
||||
|| !WPACKET_close(&wpkt)
|
||||
|| !WPACKET_get_total_written(&wpkt, &wreclen)
|
||||
|| !WPACKET_finish(&wpkt)) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
|
||||
WPACKET_cleanup(&wpkt);
|
||||
/* This is fatal */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix up the message len in the message header. Its the same as the
|
||||
* fragment len which has been filled in by WPACKET, so just copy
|
||||
* that. Destination for the message len is after the record header
|
||||
* plus one byte for the message content type. The source is the
|
||||
* last 3 bytes of the message header
|
||||
*/
|
||||
memcpy(&wbuf[DTLS1_RT_HEADER_LENGTH + 1],
|
||||
&wbuf[DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH - 3],
|
||||
3);
|
||||
|
||||
if (s->msg_callback)
|
||||
s->msg_callback(1, 0, SSL3_RT_HEADER, buf,
|
||||
DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);
|
||||
|
||||
if ((tmpclient = BIO_ADDR_new()) == NULL) {
|
||||
SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is unnecessary if rbio and wbio are one and the same - but
|
||||
* maybe they're not. We ignore errors here - some BIOs do not
|
||||
* support this.
|
||||
*/
|
||||
if (BIO_dgram_get_peer(rbio, tmpclient) > 0) {
|
||||
(void)BIO_dgram_set_peer(wbio, tmpclient);
|
||||
}
|
||||
BIO_ADDR_free(tmpclient);
|
||||
tmpclient = NULL;
|
||||
|
||||
/* TODO(size_t): convert this call */
|
||||
if (BIO_write(wbio, wbuf, wreclen) < (int)wreclen) {
|
||||
if (BIO_should_retry(wbio)) {
|
||||
/*
|
||||
* Non-blocking IO...but we're stateless, so we're just
|
||||
* going to drop this packet.
|
||||
*/
|
||||
goto end;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (BIO_flush(wbio) <= 0) {
|
||||
if (BIO_should_retry(wbio)) {
|
||||
/*
|
||||
* Non-blocking IO...but we're stateless, so we're just
|
||||
* going to drop this packet.
|
||||
*/
|
||||
goto end;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} while (next != LISTEN_SUCCESS);
|
||||
|
||||
/*
|
||||
* Set expected sequence numbers to continue the handshake.
|
||||
*/
|
||||
s->d1->handshake_read_seq = 1;
|
||||
s->d1->handshake_write_seq = 1;
|
||||
s->d1->next_handshake_write_seq = 1;
|
||||
DTLS_RECORD_LAYER_set_write_sequence(&s->rlayer, seq);
|
||||
|
||||
/*
|
||||
* We are doing cookie exchange, so make sure we set that option in the
|
||||
* SSL object
|
||||
*/
|
||||
SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
|
||||
|
||||
/*
|
||||
* Tell the state machine that we've done the initial hello verify
|
||||
* exchange
|
||||
*/
|
||||
ossl_statem_set_hello_verify_done(s);
|
||||
|
||||
/*
|
||||
* Some BIOs may not support this. If we fail we clear the client address
|
||||
*/
|
||||
if (BIO_dgram_get_peer(rbio, client) <= 0)
|
||||
BIO_ADDR_clear(client);
|
||||
|
||||
/* Buffer the record in the processed_rcds queue */
|
||||
if (!dtls_buffer_listen_record(s, reclen, seq, align))
|
||||
return -1;
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
BIO_ADDR_free(tmpclient);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dtls1_handshake_write(SSL *s)
|
||||
{
|
||||
return dtls1_do_write(s, SSL3_RT_HANDSHAKE);
|
||||
}
|
||||
|
||||
int dtls1_shutdown(SSL *s)
|
||||
{
|
||||
int ret;
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
BIO *wbio;
|
||||
|
||||
wbio = SSL_get_wbio(s);
|
||||
if (wbio != NULL && BIO_dgram_is_sctp(wbio) &&
|
||||
!(s->shutdown & SSL_SENT_SHUTDOWN)) {
|
||||
ret = BIO_dgram_sctp_wait_for_dry(wbio);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
if (ret == 0)
|
||||
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 1,
|
||||
NULL);
|
||||
}
|
||||
#endif
|
||||
ret = ssl3_shutdown(s);
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 0, NULL);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dtls1_query_mtu(SSL *s)
|
||||
{
|
||||
if (s->d1->link_mtu) {
|
||||
s->d1->mtu =
|
||||
s->d1->link_mtu - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
|
||||
s->d1->link_mtu = 0;
|
||||
}
|
||||
|
||||
/* AHA! Figure out the MTU, and stick to the right size */
|
||||
if (s->d1->mtu < dtls1_min_mtu(s)) {
|
||||
if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
|
||||
s->d1->mtu =
|
||||
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
|
||||
|
||||
/*
|
||||
* I've seen the kernel return bogus numbers when it doesn't know
|
||||
* (initial write), so just make sure we have a reasonable number
|
||||
*/
|
||||
if (s->d1->mtu < dtls1_min_mtu(s)) {
|
||||
/* Set to min mtu */
|
||||
s->d1->mtu = dtls1_min_mtu(s);
|
||||
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU,
|
||||
(long)s->d1->mtu, NULL);
|
||||
}
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t dtls1_link_min_mtu(void)
|
||||
{
|
||||
return (g_probable_mtu[(sizeof(g_probable_mtu) /
|
||||
sizeof(g_probable_mtu[0])) - 1]);
|
||||
}
|
||||
|
||||
size_t dtls1_min_mtu(SSL *s)
|
||||
{
|
||||
return dtls1_link_min_mtu() - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
|
||||
}
|
||||
|
||||
size_t DTLS_get_data_mtu(const SSL *s)
|
||||
{
|
||||
size_t mac_overhead, int_overhead, blocksize, ext_overhead;
|
||||
const SSL_CIPHER *ciph = SSL_get_current_cipher(s);
|
||||
size_t mtu = s->d1->mtu;
|
||||
|
||||
if (ciph == NULL)
|
||||
return 0;
|
||||
|
||||
if (!ssl_cipher_get_overhead(ciph, &mac_overhead, &int_overhead,
|
||||
&blocksize, &ext_overhead))
|
||||
return 0;
|
||||
|
||||
if (SSL_READ_ETM(s))
|
||||
ext_overhead += mac_overhead;
|
||||
else
|
||||
int_overhead += mac_overhead;
|
||||
|
||||
/* Subtract external overhead (e.g. IV/nonce, separate MAC) */
|
||||
if (ext_overhead + DTLS1_RT_HEADER_LENGTH >= mtu)
|
||||
return 0;
|
||||
mtu -= ext_overhead + DTLS1_RT_HEADER_LENGTH;
|
||||
|
||||
/* Round encrypted payload down to cipher block size (for CBC etc.)
|
||||
* No check for overflow since 'mtu % blocksize' cannot exceed mtu. */
|
||||
if (blocksize)
|
||||
mtu -= (mtu % blocksize);
|
||||
|
||||
/* Subtract internal overhead (e.g. CBC padding len byte) */
|
||||
if (int_overhead >= mtu)
|
||||
return 0;
|
||||
mtu -= int_overhead;
|
||||
|
||||
return mtu;
|
||||
}
|
||||
|
||||
void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb)
|
||||
{
|
||||
s->d1->timer_cb = cb;
|
||||
}
|
73
trunk/3rdparty/openssl-1.1-fit/ssl/d1_msg.c
vendored
Normal file
73
trunk/3rdparty/openssl-1.1-fit/ssl/d1_msg.c
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "ssl_locl.h"
|
||||
|
||||
int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, size_t len,
|
||||
size_t *written)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (SSL_in_init(s) && !ossl_statem_get_in_handshake(s)) {
|
||||
i = s->handshake_func(s);
|
||||
if (i < 0)
|
||||
return i;
|
||||
if (i == 0) {
|
||||
SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES,
|
||||
SSL_R_SSL_HANDSHAKE_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
|
||||
SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES, SSL_R_DTLS_MESSAGE_TOO_BIG);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dtls1_write_bytes(s, type, buf_, len, written);
|
||||
}
|
||||
|
||||
int dtls1_dispatch_alert(SSL *s)
|
||||
{
|
||||
int i, j;
|
||||
void (*cb) (const SSL *ssl, int type, int val) = NULL;
|
||||
unsigned char buf[DTLS1_AL_HEADER_LENGTH];
|
||||
unsigned char *ptr = &buf[0];
|
||||
size_t written;
|
||||
|
||||
s->s3->alert_dispatch = 0;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
*ptr++ = s->s3->send_alert[0];
|
||||
*ptr++ = s->s3->send_alert[1];
|
||||
|
||||
i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf), 0, &written);
|
||||
if (i <= 0) {
|
||||
s->s3->alert_dispatch = 1;
|
||||
/* fprintf( stderr, "not done with alert\n" ); */
|
||||
} else {
|
||||
if (s->s3->send_alert[0] == SSL3_AL_FATAL)
|
||||
(void)BIO_flush(s->wbio);
|
||||
|
||||
if (s->msg_callback)
|
||||
s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,
|
||||
2, s, s->msg_callback_arg);
|
||||
|
||||
if (s->info_callback != NULL)
|
||||
cb = s->info_callback;
|
||||
else if (s->ctx->info_callback != NULL)
|
||||
cb = s->ctx->info_callback;
|
||||
|
||||
if (cb != NULL) {
|
||||
j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
|
||||
cb(s, SSL_CB_WRITE_ALERT, j);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
139
trunk/3rdparty/openssl-1.1-fit/ssl/d1_srtp.c
vendored
Normal file
139
trunk/3rdparty/openssl-1.1-fit/ssl/d1_srtp.c
vendored
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* DTLS code by Eric Rescorla <ekr@rtfm.com>
|
||||
*
|
||||
* Copyright (C) 2006, Network Resonance, Inc. Copyright (C) 2011, RTFM, Inc.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/objects.h>
|
||||
#include "ssl_locl.h"
|
||||
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
|
||||
static SRTP_PROTECTION_PROFILE srtp_known_profiles[] = {
|
||||
{
|
||||
"SRTP_AES128_CM_SHA1_80",
|
||||
SRTP_AES128_CM_SHA1_80,
|
||||
},
|
||||
{
|
||||
"SRTP_AES128_CM_SHA1_32",
|
||||
SRTP_AES128_CM_SHA1_32,
|
||||
},
|
||||
{
|
||||
"SRTP_AEAD_AES_128_GCM",
|
||||
SRTP_AEAD_AES_128_GCM,
|
||||
},
|
||||
{
|
||||
"SRTP_AEAD_AES_256_GCM",
|
||||
SRTP_AEAD_AES_256_GCM,
|
||||
},
|
||||
{0}
|
||||
};
|
||||
|
||||
static int find_profile_by_name(char *profile_name,
|
||||
SRTP_PROTECTION_PROFILE **pptr, size_t len)
|
||||
{
|
||||
SRTP_PROTECTION_PROFILE *p;
|
||||
|
||||
p = srtp_known_profiles;
|
||||
while (p->name) {
|
||||
if ((len == strlen(p->name))
|
||||
&& strncmp(p->name, profile_name, len) == 0) {
|
||||
*pptr = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ssl_ctx_make_profiles(const char *profiles_string,
|
||||
STACK_OF(SRTP_PROTECTION_PROFILE) **out)
|
||||
{
|
||||
STACK_OF(SRTP_PROTECTION_PROFILE) *profiles;
|
||||
|
||||
char *col;
|
||||
char *ptr = (char *)profiles_string;
|
||||
SRTP_PROTECTION_PROFILE *p;
|
||||
|
||||
if ((profiles = sk_SRTP_PROTECTION_PROFILE_new_null()) == NULL) {
|
||||
SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
|
||||
SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES);
|
||||
return 1;
|
||||
}
|
||||
|
||||
do {
|
||||
col = strchr(ptr, ':');
|
||||
|
||||
if (!find_profile_by_name(ptr, &p, col ? (size_t)(col - ptr)
|
||||
: strlen(ptr))) {
|
||||
if (sk_SRTP_PROTECTION_PROFILE_find(profiles, p) >= 0) {
|
||||
SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
|
||||
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!sk_SRTP_PROTECTION_PROFILE_push(profiles, p)) {
|
||||
SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
|
||||
SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
|
||||
SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (col)
|
||||
ptr = col + 1;
|
||||
} while (col);
|
||||
|
||||
sk_SRTP_PROTECTION_PROFILE_free(*out);
|
||||
|
||||
*out = profiles;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
sk_SRTP_PROTECTION_PROFILE_free(profiles);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles)
|
||||
{
|
||||
return ssl_ctx_make_profiles(profiles, &ctx->srtp_profiles);
|
||||
}
|
||||
|
||||
int SSL_set_tlsext_use_srtp(SSL *s, const char *profiles)
|
||||
{
|
||||
return ssl_ctx_make_profiles(profiles, &s->srtp_profiles);
|
||||
}
|
||||
|
||||
STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *s)
|
||||
{
|
||||
if (s != NULL) {
|
||||
if (s->srtp_profiles != NULL) {
|
||||
return s->srtp_profiles;
|
||||
} else if ((s->ctx != NULL) && (s->ctx->srtp_profiles != NULL)) {
|
||||
return s->ctx->srtp_profiles;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s)
|
||||
{
|
||||
return s->srtp_profile;
|
||||
}
|
||||
#endif
|
278
trunk/3rdparty/openssl-1.1-fit/ssl/methods.c
vendored
Normal file
278
trunk/3rdparty/openssl-1.1-fit/ssl/methods.c
vendored
Normal file
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/objects.h>
|
||||
#include "ssl_locl.h"
|
||||
|
||||
/*-
|
||||
* TLS/SSLv3 methods
|
||||
*/
|
||||
|
||||
IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0,
|
||||
TLS_method,
|
||||
ossl_statem_accept,
|
||||
ossl_statem_connect, TLSv1_2_enc_data)
|
||||
IMPLEMENT_tls_meth_func(TLS1_3_VERSION, 0, SSL_OP_NO_TLSv1_3,
|
||||
tlsv1_3_method,
|
||||
ossl_statem_accept,
|
||||
ossl_statem_connect, TLSv1_3_enc_data)
|
||||
#ifndef OPENSSL_NO_TLS1_2_METHOD
|
||||
IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2,
|
||||
tlsv1_2_method,
|
||||
ossl_statem_accept,
|
||||
ossl_statem_connect, TLSv1_2_enc_data)
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_TLS1_1_METHOD
|
||||
IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1,
|
||||
tlsv1_1_method,
|
||||
ossl_statem_accept,
|
||||
ossl_statem_connect, TLSv1_1_enc_data)
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_TLS1_METHOD
|
||||
IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1,
|
||||
tlsv1_method,
|
||||
ossl_statem_accept, ossl_statem_connect, TLSv1_enc_data)
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SSL3_METHOD
|
||||
IMPLEMENT_ssl3_meth_func(sslv3_method, ossl_statem_accept, ossl_statem_connect)
|
||||
#endif
|
||||
/*-
|
||||
* TLS/SSLv3 server methods
|
||||
*/
|
||||
IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0,
|
||||
TLS_server_method,
|
||||
ossl_statem_accept,
|
||||
ssl_undefined_function, TLSv1_2_enc_data)
|
||||
IMPLEMENT_tls_meth_func(TLS1_3_VERSION, 0, SSL_OP_NO_TLSv1_3,
|
||||
tlsv1_3_server_method,
|
||||
ossl_statem_accept,
|
||||
ssl_undefined_function, TLSv1_3_enc_data)
|
||||
#ifndef OPENSSL_NO_TLS1_2_METHOD
|
||||
IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2,
|
||||
tlsv1_2_server_method,
|
||||
ossl_statem_accept,
|
||||
ssl_undefined_function, TLSv1_2_enc_data)
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_TLS1_1_METHOD
|
||||
IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1,
|
||||
tlsv1_1_server_method,
|
||||
ossl_statem_accept,
|
||||
ssl_undefined_function, TLSv1_1_enc_data)
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_TLS1_METHOD
|
||||
IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1,
|
||||
tlsv1_server_method,
|
||||
ossl_statem_accept,
|
||||
ssl_undefined_function, TLSv1_enc_data)
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SSL3_METHOD
|
||||
IMPLEMENT_ssl3_meth_func(sslv3_server_method,
|
||||
ossl_statem_accept, ssl_undefined_function)
|
||||
#endif
|
||||
/*-
|
||||
* TLS/SSLv3 client methods
|
||||
*/
|
||||
IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0,
|
||||
TLS_client_method,
|
||||
ssl_undefined_function,
|
||||
ossl_statem_connect, TLSv1_2_enc_data)
|
||||
IMPLEMENT_tls_meth_func(TLS1_3_VERSION, 0, SSL_OP_NO_TLSv1_3,
|
||||
tlsv1_3_client_method,
|
||||
ssl_undefined_function,
|
||||
ossl_statem_connect, TLSv1_3_enc_data)
|
||||
#ifndef OPENSSL_NO_TLS1_2_METHOD
|
||||
IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2,
|
||||
tlsv1_2_client_method,
|
||||
ssl_undefined_function,
|
||||
ossl_statem_connect, TLSv1_2_enc_data)
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_TLS1_1_METHOD
|
||||
IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1,
|
||||
tlsv1_1_client_method,
|
||||
ssl_undefined_function,
|
||||
ossl_statem_connect, TLSv1_1_enc_data)
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_TLS1_METHOD
|
||||
IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1,
|
||||
tlsv1_client_method,
|
||||
ssl_undefined_function,
|
||||
ossl_statem_connect, TLSv1_enc_data)
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SSL3_METHOD
|
||||
IMPLEMENT_ssl3_meth_func(sslv3_client_method,
|
||||
ssl_undefined_function, ossl_statem_connect)
|
||||
#endif
|
||||
/*-
|
||||
* DTLS methods
|
||||
*/
|
||||
#ifndef OPENSSL_NO_DTLS1_METHOD
|
||||
IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1,
|
||||
dtlsv1_method,
|
||||
ossl_statem_accept,
|
||||
ossl_statem_connect, DTLSv1_enc_data)
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DTLS1_2_METHOD
|
||||
IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2,
|
||||
dtlsv1_2_method,
|
||||
ossl_statem_accept,
|
||||
ossl_statem_connect, DTLSv1_2_enc_data)
|
||||
#endif
|
||||
IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0,
|
||||
DTLS_method,
|
||||
ossl_statem_accept,
|
||||
ossl_statem_connect, DTLSv1_2_enc_data)
|
||||
|
||||
/*-
|
||||
* DTLS server methods
|
||||
*/
|
||||
#ifndef OPENSSL_NO_DTLS1_METHOD
|
||||
IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1,
|
||||
dtlsv1_server_method,
|
||||
ossl_statem_accept,
|
||||
ssl_undefined_function, DTLSv1_enc_data)
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DTLS1_2_METHOD
|
||||
IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2,
|
||||
dtlsv1_2_server_method,
|
||||
ossl_statem_accept,
|
||||
ssl_undefined_function, DTLSv1_2_enc_data)
|
||||
#endif
|
||||
IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0,
|
||||
DTLS_server_method,
|
||||
ossl_statem_accept,
|
||||
ssl_undefined_function, DTLSv1_2_enc_data)
|
||||
|
||||
/*-
|
||||
* DTLS client methods
|
||||
*/
|
||||
#ifndef OPENSSL_NO_DTLS1_METHOD
|
||||
IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1,
|
||||
dtlsv1_client_method,
|
||||
ssl_undefined_function,
|
||||
ossl_statem_connect, DTLSv1_enc_data)
|
||||
IMPLEMENT_dtls1_meth_func(DTLS1_BAD_VER, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1,
|
||||
dtls_bad_ver_client_method,
|
||||
ssl_undefined_function,
|
||||
ossl_statem_connect, DTLSv1_enc_data)
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DTLS1_2_METHOD
|
||||
IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2,
|
||||
dtlsv1_2_client_method,
|
||||
ssl_undefined_function,
|
||||
ossl_statem_connect, DTLSv1_2_enc_data)
|
||||
#endif
|
||||
IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0,
|
||||
DTLS_client_method,
|
||||
ssl_undefined_function,
|
||||
ossl_statem_connect, DTLSv1_2_enc_data)
|
||||
#if OPENSSL_API_COMPAT < 0x10100000L
|
||||
# ifndef OPENSSL_NO_TLS1_2_METHOD
|
||||
const SSL_METHOD *TLSv1_2_method(void)
|
||||
{
|
||||
return tlsv1_2_method();
|
||||
}
|
||||
|
||||
const SSL_METHOD *TLSv1_2_server_method(void)
|
||||
{
|
||||
return tlsv1_2_server_method();
|
||||
}
|
||||
|
||||
const SSL_METHOD *TLSv1_2_client_method(void)
|
||||
{
|
||||
return tlsv1_2_client_method();
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifndef OPENSSL_NO_TLS1_1_METHOD
|
||||
const SSL_METHOD *TLSv1_1_method(void)
|
||||
{
|
||||
return tlsv1_1_method();
|
||||
}
|
||||
|
||||
const SSL_METHOD *TLSv1_1_server_method(void)
|
||||
{
|
||||
return tlsv1_1_server_method();
|
||||
}
|
||||
|
||||
const SSL_METHOD *TLSv1_1_client_method(void)
|
||||
{
|
||||
return tlsv1_1_client_method();
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifndef OPENSSL_NO_TLS1_METHOD
|
||||
const SSL_METHOD *TLSv1_method(void)
|
||||
{
|
||||
return tlsv1_method();
|
||||
}
|
||||
|
||||
const SSL_METHOD *TLSv1_server_method(void)
|
||||
{
|
||||
return tlsv1_server_method();
|
||||
}
|
||||
|
||||
const SSL_METHOD *TLSv1_client_method(void)
|
||||
{
|
||||
return tlsv1_client_method();
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifndef OPENSSL_NO_SSL3_METHOD
|
||||
const SSL_METHOD *SSLv3_method(void)
|
||||
{
|
||||
return sslv3_method();
|
||||
}
|
||||
|
||||
const SSL_METHOD *SSLv3_server_method(void)
|
||||
{
|
||||
return sslv3_server_method();
|
||||
}
|
||||
|
||||
const SSL_METHOD *SSLv3_client_method(void)
|
||||
{
|
||||
return sslv3_client_method();
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifndef OPENSSL_NO_DTLS1_2_METHOD
|
||||
const SSL_METHOD *DTLSv1_2_method(void)
|
||||
{
|
||||
return dtlsv1_2_method();
|
||||
}
|
||||
|
||||
const SSL_METHOD *DTLSv1_2_server_method(void)
|
||||
{
|
||||
return dtlsv1_2_server_method();
|
||||
}
|
||||
|
||||
const SSL_METHOD *DTLSv1_2_client_method(void)
|
||||
{
|
||||
return dtlsv1_2_client_method();
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifndef OPENSSL_NO_DTLS1_METHOD
|
||||
const SSL_METHOD *DTLSv1_method(void)
|
||||
{
|
||||
return dtlsv1_method();
|
||||
}
|
||||
|
||||
const SSL_METHOD *DTLSv1_server_method(void)
|
||||
{
|
||||
return dtlsv1_server_method();
|
||||
}
|
||||
|
||||
const SSL_METHOD *DTLSv1_client_method(void)
|
||||
{
|
||||
return dtlsv1_client_method();
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
424
trunk/3rdparty/openssl-1.1-fit/ssl/packet.c
vendored
Normal file
424
trunk/3rdparty/openssl-1.1-fit/ssl/packet.c
vendored
Normal file
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "internal/cryptlib.h"
|
||||
#include "packet_locl.h"
|
||||
#include <openssl/sslerr.h>
|
||||
|
||||
#define DEFAULT_BUF_SIZE 256
|
||||
|
||||
int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
|
||||
{
|
||||
if (!WPACKET_reserve_bytes(pkt, len, allocbytes))
|
||||
return 0;
|
||||
|
||||
pkt->written += len;
|
||||
pkt->curr += len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
|
||||
unsigned char **allocbytes, size_t lenbytes)
|
||||
{
|
||||
if (!WPACKET_start_sub_packet_len__(pkt, lenbytes)
|
||||
|| !WPACKET_allocate_bytes(pkt, len, allocbytes)
|
||||
|| !WPACKET_close(pkt))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define GETBUF(p) (((p)->staticbuf != NULL) \
|
||||
? (p)->staticbuf : (unsigned char *)(p)->buf->data)
|
||||
|
||||
int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
|
||||
{
|
||||
/* Internal API, so should not fail */
|
||||
if (!ossl_assert(pkt->subs != NULL && len != 0))
|
||||
return 0;
|
||||
|
||||
if (pkt->maxsize - pkt->written < len)
|
||||
return 0;
|
||||
|
||||
if (pkt->staticbuf == NULL && (pkt->buf->length - pkt->written < len)) {
|
||||
size_t newlen;
|
||||
size_t reflen;
|
||||
|
||||
reflen = (len > pkt->buf->length) ? len : pkt->buf->length;
|
||||
|
||||
if (reflen > SIZE_MAX / 2) {
|
||||
newlen = SIZE_MAX;
|
||||
} else {
|
||||
newlen = reflen * 2;
|
||||
if (newlen < DEFAULT_BUF_SIZE)
|
||||
newlen = DEFAULT_BUF_SIZE;
|
||||
}
|
||||
if (BUF_MEM_grow(pkt->buf, newlen) == 0)
|
||||
return 0;
|
||||
}
|
||||
if (allocbytes != NULL)
|
||||
*allocbytes = WPACKET_get_curr(pkt);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len,
|
||||
unsigned char **allocbytes, size_t lenbytes)
|
||||
{
|
||||
if (!WPACKET_reserve_bytes(pkt, lenbytes + len, allocbytes))
|
||||
return 0;
|
||||
|
||||
*allocbytes += lenbytes;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t maxmaxsize(size_t lenbytes)
|
||||
{
|
||||
if (lenbytes >= sizeof(size_t) || lenbytes == 0)
|
||||
return SIZE_MAX;
|
||||
|
||||
return ((size_t)1 << (lenbytes * 8)) - 1 + lenbytes;
|
||||
}
|
||||
|
||||
static int wpacket_intern_init_len(WPACKET *pkt, size_t lenbytes)
|
||||
{
|
||||
unsigned char *lenchars;
|
||||
|
||||
pkt->curr = 0;
|
||||
pkt->written = 0;
|
||||
|
||||
if ((pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs))) == NULL) {
|
||||
SSLerr(SSL_F_WPACKET_INTERN_INIT_LEN, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lenbytes == 0)
|
||||
return 1;
|
||||
|
||||
pkt->subs->pwritten = lenbytes;
|
||||
pkt->subs->lenbytes = lenbytes;
|
||||
|
||||
if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars)) {
|
||||
OPENSSL_free(pkt->subs);
|
||||
pkt->subs = NULL;
|
||||
return 0;
|
||||
}
|
||||
pkt->subs->packet_len = lenchars - GETBUF(pkt);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len,
|
||||
size_t lenbytes)
|
||||
{
|
||||
size_t max = maxmaxsize(lenbytes);
|
||||
|
||||
/* Internal API, so should not fail */
|
||||
if (!ossl_assert(buf != NULL && len > 0))
|
||||
return 0;
|
||||
|
||||
pkt->staticbuf = buf;
|
||||
pkt->buf = NULL;
|
||||
pkt->maxsize = (max < len) ? max : len;
|
||||
|
||||
return wpacket_intern_init_len(pkt, lenbytes);
|
||||
}
|
||||
|
||||
int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes)
|
||||
{
|
||||
/* Internal API, so should not fail */
|
||||
if (!ossl_assert(buf != NULL))
|
||||
return 0;
|
||||
|
||||
pkt->staticbuf = NULL;
|
||||
pkt->buf = buf;
|
||||
pkt->maxsize = maxmaxsize(lenbytes);
|
||||
|
||||
return wpacket_intern_init_len(pkt, lenbytes);
|
||||
}
|
||||
|
||||
int WPACKET_init(WPACKET *pkt, BUF_MEM *buf)
|
||||
{
|
||||
return WPACKET_init_len(pkt, buf, 0);
|
||||
}
|
||||
|
||||
int WPACKET_set_flags(WPACKET *pkt, unsigned int flags)
|
||||
{
|
||||
/* Internal API, so should not fail */
|
||||
if (!ossl_assert(pkt->subs != NULL))
|
||||
return 0;
|
||||
|
||||
pkt->subs->flags = flags;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Store the |value| of length |len| at location |data| */
|
||||
static int put_value(unsigned char *data, size_t value, size_t len)
|
||||
{
|
||||
for (data += len - 1; len > 0; len--) {
|
||||
*data = (unsigned char)(value & 0xff);
|
||||
data--;
|
||||
value >>= 8;
|
||||
}
|
||||
|
||||
/* Check whether we could fit the value in the assigned number of bytes */
|
||||
if (value > 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Internal helper function used by WPACKET_close(), WPACKET_finish() and
|
||||
* WPACKET_fill_lengths() to close a sub-packet and write out its length if
|
||||
* necessary. If |doclose| is 0 then it goes through the motions of closing
|
||||
* (i.e. it fills in all the lengths), but doesn't actually close anything.
|
||||
*/
|
||||
static int wpacket_intern_close(WPACKET *pkt, WPACKET_SUB *sub, int doclose)
|
||||
{
|
||||
size_t packlen = pkt->written - sub->pwritten;
|
||||
|
||||
if (packlen == 0
|
||||
&& (sub->flags & WPACKET_FLAGS_NON_ZERO_LENGTH) != 0)
|
||||
return 0;
|
||||
|
||||
if (packlen == 0
|
||||
&& sub->flags & WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH) {
|
||||
/* We can't handle this case. Return an error */
|
||||
if (!doclose)
|
||||
return 0;
|
||||
|
||||
/* Deallocate any bytes allocated for the length of the WPACKET */
|
||||
if ((pkt->curr - sub->lenbytes) == sub->packet_len) {
|
||||
pkt->written -= sub->lenbytes;
|
||||
pkt->curr -= sub->lenbytes;
|
||||
}
|
||||
|
||||
/* Don't write out the packet length */
|
||||
sub->packet_len = 0;
|
||||
sub->lenbytes = 0;
|
||||
}
|
||||
|
||||
/* Write out the WPACKET length if needed */
|
||||
if (sub->lenbytes > 0
|
||||
&& !put_value(&GETBUF(pkt)[sub->packet_len], packlen,
|
||||
sub->lenbytes))
|
||||
return 0;
|
||||
|
||||
if (doclose) {
|
||||
pkt->subs = sub->parent;
|
||||
OPENSSL_free(sub);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WPACKET_fill_lengths(WPACKET *pkt)
|
||||
{
|
||||
WPACKET_SUB *sub;
|
||||
|
||||
if (!ossl_assert(pkt->subs != NULL))
|
||||
return 0;
|
||||
|
||||
for (sub = pkt->subs; sub != NULL; sub = sub->parent) {
|
||||
if (!wpacket_intern_close(pkt, sub, 0))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WPACKET_close(WPACKET *pkt)
|
||||
{
|
||||
/*
|
||||
* Internal API, so should not fail - but we do negative testing of this
|
||||
* so no assert (otherwise the tests fail)
|
||||
*/
|
||||
if (pkt->subs == NULL || pkt->subs->parent == NULL)
|
||||
return 0;
|
||||
|
||||
return wpacket_intern_close(pkt, pkt->subs, 1);
|
||||
}
|
||||
|
||||
int WPACKET_finish(WPACKET *pkt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Internal API, so should not fail - but we do negative testing of this
|
||||
* so no assert (otherwise the tests fail)
|
||||
*/
|
||||
if (pkt->subs == NULL || pkt->subs->parent != NULL)
|
||||
return 0;
|
||||
|
||||
ret = wpacket_intern_close(pkt, pkt->subs, 1);
|
||||
if (ret) {
|
||||
OPENSSL_free(pkt->subs);
|
||||
pkt->subs = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes)
|
||||
{
|
||||
WPACKET_SUB *sub;
|
||||
unsigned char *lenchars;
|
||||
|
||||
/* Internal API, so should not fail */
|
||||
if (!ossl_assert(pkt->subs != NULL))
|
||||
return 0;
|
||||
|
||||
if ((sub = OPENSSL_zalloc(sizeof(*sub))) == NULL) {
|
||||
SSLerr(SSL_F_WPACKET_START_SUB_PACKET_LEN__, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub->parent = pkt->subs;
|
||||
pkt->subs = sub;
|
||||
sub->pwritten = pkt->written + lenbytes;
|
||||
sub->lenbytes = lenbytes;
|
||||
|
||||
if (lenbytes == 0) {
|
||||
sub->packet_len = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars))
|
||||
return 0;
|
||||
/* Convert to an offset in case the underlying BUF_MEM gets realloc'd */
|
||||
sub->packet_len = lenchars - GETBUF(pkt);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WPACKET_start_sub_packet(WPACKET *pkt)
|
||||
{
|
||||
return WPACKET_start_sub_packet_len__(pkt, 0);
|
||||
}
|
||||
|
||||
int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t size)
|
||||
{
|
||||
unsigned char *data;
|
||||
|
||||
/* Internal API, so should not fail */
|
||||
if (!ossl_assert(size <= sizeof(unsigned int))
|
||||
|| !WPACKET_allocate_bytes(pkt, size, &data)
|
||||
|| !put_value(data, val, size))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize)
|
||||
{
|
||||
WPACKET_SUB *sub;
|
||||
size_t lenbytes;
|
||||
|
||||
/* Internal API, so should not fail */
|
||||
if (!ossl_assert(pkt->subs != NULL))
|
||||
return 0;
|
||||
|
||||
/* Find the WPACKET_SUB for the top level */
|
||||
for (sub = pkt->subs; sub->parent != NULL; sub = sub->parent)
|
||||
continue;
|
||||
|
||||
lenbytes = sub->lenbytes;
|
||||
if (lenbytes == 0)
|
||||
lenbytes = sizeof(pkt->maxsize);
|
||||
|
||||
if (maxmaxsize(lenbytes) < maxsize || maxsize < pkt->written)
|
||||
return 0;
|
||||
|
||||
pkt->maxsize = maxsize;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WPACKET_memset(WPACKET *pkt, int ch, size_t len)
|
||||
{
|
||||
unsigned char *dest;
|
||||
|
||||
if (len == 0)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_allocate_bytes(pkt, len, &dest))
|
||||
return 0;
|
||||
|
||||
memset(dest, ch, len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len)
|
||||
{
|
||||
unsigned char *dest;
|
||||
|
||||
if (len == 0)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_allocate_bytes(pkt, len, &dest))
|
||||
return 0;
|
||||
|
||||
memcpy(dest, src, len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len,
|
||||
size_t lenbytes)
|
||||
{
|
||||
if (!WPACKET_start_sub_packet_len__(pkt, lenbytes)
|
||||
|| !WPACKET_memcpy(pkt, src, len)
|
||||
|| !WPACKET_close(pkt))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WPACKET_get_total_written(WPACKET *pkt, size_t *written)
|
||||
{
|
||||
/* Internal API, so should not fail */
|
||||
if (!ossl_assert(written != NULL))
|
||||
return 0;
|
||||
|
||||
*written = pkt->written;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WPACKET_get_length(WPACKET *pkt, size_t *len)
|
||||
{
|
||||
/* Internal API, so should not fail */
|
||||
if (!ossl_assert(pkt->subs != NULL && len != NULL))
|
||||
return 0;
|
||||
|
||||
*len = pkt->written - pkt->subs->pwritten;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char *WPACKET_get_curr(WPACKET *pkt)
|
||||
{
|
||||
return GETBUF(pkt) + pkt->curr;
|
||||
}
|
||||
|
||||
void WPACKET_cleanup(WPACKET *pkt)
|
||||
{
|
||||
WPACKET_SUB *sub, *parent;
|
||||
|
||||
for (sub = pkt->subs; sub != NULL; sub = parent) {
|
||||
parent = sub->parent;
|
||||
OPENSSL_free(sub);
|
||||
}
|
||||
pkt->subs = NULL;
|
||||
}
|
874
trunk/3rdparty/openssl-1.1-fit/ssl/packet_locl.h
vendored
Normal file
874
trunk/3rdparty/openssl-1.1-fit/ssl/packet_locl.h
vendored
Normal file
|
@ -0,0 +1,874 @@
|
|||
/*
|
||||
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef HEADER_PACKET_LOCL_H
|
||||
# define HEADER_PACKET_LOCL_H
|
||||
|
||||
# include <string.h>
|
||||
# include <openssl/bn.h>
|
||||
# include <openssl/buffer.h>
|
||||
# include <openssl/crypto.h>
|
||||
# include <openssl/e_os2.h>
|
||||
|
||||
# include "internal/numbers.h"
|
||||
|
||||
typedef struct {
|
||||
/* Pointer to where we are currently reading from */
|
||||
const unsigned char *curr;
|
||||
/* Number of bytes remaining */
|
||||
size_t remaining;
|
||||
} PACKET;
|
||||
|
||||
/* Internal unchecked shorthand; don't use outside this file. */
|
||||
static ossl_inline void packet_forward(PACKET *pkt, size_t len)
|
||||
{
|
||||
pkt->curr += len;
|
||||
pkt->remaining -= len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the number of bytes remaining to be read in the PACKET
|
||||
*/
|
||||
static ossl_inline size_t PACKET_remaining(const PACKET *pkt)
|
||||
{
|
||||
return pkt->remaining;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a pointer to the first byte after the packet data.
|
||||
* Useful for integrating with non-PACKET parsing code.
|
||||
* Specifically, we use PACKET_end() to verify that a d2i_... call
|
||||
* has consumed the entire packet contents.
|
||||
*/
|
||||
static ossl_inline const unsigned char *PACKET_end(const PACKET *pkt)
|
||||
{
|
||||
return pkt->curr + pkt->remaining;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a pointer to the PACKET's current position.
|
||||
* For use in non-PACKETized APIs.
|
||||
*/
|
||||
static ossl_inline const unsigned char *PACKET_data(const PACKET *pkt)
|
||||
{
|
||||
return pkt->curr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise a PACKET with |len| bytes held in |buf|. This does not make a
|
||||
* copy of the data so |buf| must be present for the whole time that the PACKET
|
||||
* is being used.
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_buf_init(PACKET *pkt,
|
||||
const unsigned char *buf,
|
||||
size_t len)
|
||||
{
|
||||
/* Sanity check for negative values. */
|
||||
if (len > (size_t)(SIZE_MAX / 2))
|
||||
return 0;
|
||||
|
||||
pkt->curr = buf;
|
||||
pkt->remaining = len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize a PACKET to hold zero bytes. */
|
||||
static ossl_inline void PACKET_null_init(PACKET *pkt)
|
||||
{
|
||||
pkt->curr = NULL;
|
||||
pkt->remaining = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if the packet has length |num| and its contents equal the |num|
|
||||
* bytes read from |ptr|. Returns 0 otherwise (lengths or contents not equal).
|
||||
* If lengths are equal, performs the comparison in constant time.
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_equal(const PACKET *pkt, const void *ptr,
|
||||
size_t num)
|
||||
{
|
||||
if (PACKET_remaining(pkt) != num)
|
||||
return 0;
|
||||
return CRYPTO_memcmp(pkt->curr, ptr, num) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Peek ahead and initialize |subpkt| with the next |len| bytes read from |pkt|.
|
||||
* Data is not copied: the |subpkt| packet will share its underlying buffer with
|
||||
* the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_peek_sub_packet(const PACKET *pkt,
|
||||
PACKET *subpkt, size_t len)
|
||||
{
|
||||
if (PACKET_remaining(pkt) < len)
|
||||
return 0;
|
||||
|
||||
return PACKET_buf_init(subpkt, pkt->curr, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize |subpkt| with the next |len| bytes read from |pkt|. Data is not
|
||||
* copied: the |subpkt| packet will share its underlying buffer with the
|
||||
* original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_get_sub_packet(PACKET *pkt,
|
||||
PACKET *subpkt, size_t len)
|
||||
{
|
||||
if (!PACKET_peek_sub_packet(pkt, subpkt, len))
|
||||
return 0;
|
||||
|
||||
packet_forward(pkt, len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Peek ahead at 2 bytes in network order from |pkt| and store the value in
|
||||
* |*data|
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_peek_net_2(const PACKET *pkt,
|
||||
unsigned int *data)
|
||||
{
|
||||
if (PACKET_remaining(pkt) < 2)
|
||||
return 0;
|
||||
|
||||
*data = ((unsigned int)(*pkt->curr)) << 8;
|
||||
*data |= *(pkt->curr + 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Equivalent of n2s */
|
||||
/* Get 2 bytes in network order from |pkt| and store the value in |*data| */
|
||||
__owur static ossl_inline int PACKET_get_net_2(PACKET *pkt, unsigned int *data)
|
||||
{
|
||||
if (!PACKET_peek_net_2(pkt, data))
|
||||
return 0;
|
||||
|
||||
packet_forward(pkt, 2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Same as PACKET_get_net_2() but for a size_t */
|
||||
__owur static ossl_inline int PACKET_get_net_2_len(PACKET *pkt, size_t *data)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret = PACKET_get_net_2(pkt, &i);
|
||||
|
||||
if (ret)
|
||||
*data = (size_t)i;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Peek ahead at 3 bytes in network order from |pkt| and store the value in
|
||||
* |*data|
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_peek_net_3(const PACKET *pkt,
|
||||
unsigned long *data)
|
||||
{
|
||||
if (PACKET_remaining(pkt) < 3)
|
||||
return 0;
|
||||
|
||||
*data = ((unsigned long)(*pkt->curr)) << 16;
|
||||
*data |= ((unsigned long)(*(pkt->curr + 1))) << 8;
|
||||
*data |= *(pkt->curr + 2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Equivalent of n2l3 */
|
||||
/* Get 3 bytes in network order from |pkt| and store the value in |*data| */
|
||||
__owur static ossl_inline int PACKET_get_net_3(PACKET *pkt, unsigned long *data)
|
||||
{
|
||||
if (!PACKET_peek_net_3(pkt, data))
|
||||
return 0;
|
||||
|
||||
packet_forward(pkt, 3);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Same as PACKET_get_net_3() but for a size_t */
|
||||
__owur static ossl_inline int PACKET_get_net_3_len(PACKET *pkt, size_t *data)
|
||||
{
|
||||
unsigned long i;
|
||||
int ret = PACKET_get_net_3(pkt, &i);
|
||||
|
||||
if (ret)
|
||||
*data = (size_t)i;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Peek ahead at 4 bytes in network order from |pkt| and store the value in
|
||||
* |*data|
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_peek_net_4(const PACKET *pkt,
|
||||
unsigned long *data)
|
||||
{
|
||||
if (PACKET_remaining(pkt) < 4)
|
||||
return 0;
|
||||
|
||||
*data = ((unsigned long)(*pkt->curr)) << 24;
|
||||
*data |= ((unsigned long)(*(pkt->curr + 1))) << 16;
|
||||
*data |= ((unsigned long)(*(pkt->curr + 2))) << 8;
|
||||
*data |= *(pkt->curr + 3);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Equivalent of n2l */
|
||||
/* Get 4 bytes in network order from |pkt| and store the value in |*data| */
|
||||
__owur static ossl_inline int PACKET_get_net_4(PACKET *pkt, unsigned long *data)
|
||||
{
|
||||
if (!PACKET_peek_net_4(pkt, data))
|
||||
return 0;
|
||||
|
||||
packet_forward(pkt, 4);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Same as PACKET_get_net_4() but for a size_t */
|
||||
__owur static ossl_inline int PACKET_get_net_4_len(PACKET *pkt, size_t *data)
|
||||
{
|
||||
unsigned long i;
|
||||
int ret = PACKET_get_net_4(pkt, &i);
|
||||
|
||||
if (ret)
|
||||
*data = (size_t)i;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Peek ahead at 1 byte from |pkt| and store the value in |*data| */
|
||||
__owur static ossl_inline int PACKET_peek_1(const PACKET *pkt,
|
||||
unsigned int *data)
|
||||
{
|
||||
if (!PACKET_remaining(pkt))
|
||||
return 0;
|
||||
|
||||
*data = *pkt->curr;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get 1 byte from |pkt| and store the value in |*data| */
|
||||
__owur static ossl_inline int PACKET_get_1(PACKET *pkt, unsigned int *data)
|
||||
{
|
||||
if (!PACKET_peek_1(pkt, data))
|
||||
return 0;
|
||||
|
||||
packet_forward(pkt, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Same as PACKET_get_1() but for a size_t */
|
||||
__owur static ossl_inline int PACKET_get_1_len(PACKET *pkt, size_t *data)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret = PACKET_get_1(pkt, &i);
|
||||
|
||||
if (ret)
|
||||
*data = (size_t)i;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Peek ahead at 4 bytes in reverse network order from |pkt| and store the value
|
||||
* in |*data|
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_peek_4(const PACKET *pkt,
|
||||
unsigned long *data)
|
||||
{
|
||||
if (PACKET_remaining(pkt) < 4)
|
||||
return 0;
|
||||
|
||||
*data = *pkt->curr;
|
||||
*data |= ((unsigned long)(*(pkt->curr + 1))) << 8;
|
||||
*data |= ((unsigned long)(*(pkt->curr + 2))) << 16;
|
||||
*data |= ((unsigned long)(*(pkt->curr + 3))) << 24;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Equivalent of c2l */
|
||||
/*
|
||||
* Get 4 bytes in reverse network order from |pkt| and store the value in
|
||||
* |*data|
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_get_4(PACKET *pkt, unsigned long *data)
|
||||
{
|
||||
if (!PACKET_peek_4(pkt, data))
|
||||
return 0;
|
||||
|
||||
packet_forward(pkt, 4);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Peek ahead at |len| bytes from the |pkt| and store a pointer to them in
|
||||
* |*data|. This just points at the underlying buffer that |pkt| is using. The
|
||||
* caller should not free this data directly (it will be freed when the
|
||||
* underlying buffer gets freed
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_peek_bytes(const PACKET *pkt,
|
||||
const unsigned char **data,
|
||||
size_t len)
|
||||
{
|
||||
if (PACKET_remaining(pkt) < len)
|
||||
return 0;
|
||||
|
||||
*data = pkt->curr;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read |len| bytes from the |pkt| and store a pointer to them in |*data|. This
|
||||
* just points at the underlying buffer that |pkt| is using. The caller should
|
||||
* not free this data directly (it will be freed when the underlying buffer gets
|
||||
* freed
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_get_bytes(PACKET *pkt,
|
||||
const unsigned char **data,
|
||||
size_t len)
|
||||
{
|
||||
if (!PACKET_peek_bytes(pkt, data, len))
|
||||
return 0;
|
||||
|
||||
packet_forward(pkt, len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Peek ahead at |len| bytes from |pkt| and copy them to |data| */
|
||||
__owur static ossl_inline int PACKET_peek_copy_bytes(const PACKET *pkt,
|
||||
unsigned char *data,
|
||||
size_t len)
|
||||
{
|
||||
if (PACKET_remaining(pkt) < len)
|
||||
return 0;
|
||||
|
||||
memcpy(data, pkt->curr, len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read |len| bytes from |pkt| and copy them to |data|.
|
||||
* The caller is responsible for ensuring that |data| can hold |len| bytes.
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_copy_bytes(PACKET *pkt,
|
||||
unsigned char *data, size_t len)
|
||||
{
|
||||
if (!PACKET_peek_copy_bytes(pkt, data, len))
|
||||
return 0;
|
||||
|
||||
packet_forward(pkt, len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy packet data to |dest|, and set |len| to the number of copied bytes.
|
||||
* If the packet has more than |dest_len| bytes, nothing is copied.
|
||||
* Returns 1 if the packet data fits in |dest_len| bytes, 0 otherwise.
|
||||
* Does not forward PACKET position (because it is typically the last thing
|
||||
* done with a given PACKET).
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_copy_all(const PACKET *pkt,
|
||||
unsigned char *dest,
|
||||
size_t dest_len, size_t *len)
|
||||
{
|
||||
if (PACKET_remaining(pkt) > dest_len) {
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
*len = pkt->remaining;
|
||||
memcpy(dest, pkt->curr, pkt->remaining);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy |pkt| bytes to a newly allocated buffer and store a pointer to the
|
||||
* result in |*data|, and the length in |len|.
|
||||
* If |*data| is not NULL, the old data is OPENSSL_free'd.
|
||||
* If the packet is empty, or malloc fails, |*data| will be set to NULL.
|
||||
* Returns 1 if the malloc succeeds and 0 otherwise.
|
||||
* Does not forward PACKET position (because it is typically the last thing
|
||||
* done with a given PACKET).
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_memdup(const PACKET *pkt,
|
||||
unsigned char **data, size_t *len)
|
||||
{
|
||||
size_t length;
|
||||
|
||||
OPENSSL_free(*data);
|
||||
*data = NULL;
|
||||
*len = 0;
|
||||
|
||||
length = PACKET_remaining(pkt);
|
||||
|
||||
if (length == 0)
|
||||
return 1;
|
||||
|
||||
*data = OPENSSL_memdup(pkt->curr, length);
|
||||
if (*data == NULL)
|
||||
return 0;
|
||||
|
||||
*len = length;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a C string from |pkt| and copy to a newly allocated, NUL-terminated
|
||||
* buffer. Store a pointer to the result in |*data|.
|
||||
* If |*data| is not NULL, the old data is OPENSSL_free'd.
|
||||
* If the data in |pkt| does not contain a NUL-byte, the entire data is
|
||||
* copied and NUL-terminated.
|
||||
* Returns 1 if the malloc succeeds and 0 otherwise.
|
||||
* Does not forward PACKET position (because it is typically the last thing done
|
||||
* with a given PACKET).
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_strndup(const PACKET *pkt, char **data)
|
||||
{
|
||||
OPENSSL_free(*data);
|
||||
|
||||
/* This will succeed on an empty packet, unless pkt->curr == NULL. */
|
||||
*data = OPENSSL_strndup((const char *)pkt->curr, PACKET_remaining(pkt));
|
||||
return (*data != NULL);
|
||||
}
|
||||
|
||||
/* Returns 1 if |pkt| contains at least one 0-byte, 0 otherwise. */
|
||||
static ossl_inline int PACKET_contains_zero_byte(const PACKET *pkt)
|
||||
{
|
||||
return memchr(pkt->curr, 0, pkt->remaining) != NULL;
|
||||
}
|
||||
|
||||
/* Move the current reading position forward |len| bytes */
|
||||
__owur static ossl_inline int PACKET_forward(PACKET *pkt, size_t len)
|
||||
{
|
||||
if (PACKET_remaining(pkt) < len)
|
||||
return 0;
|
||||
|
||||
packet_forward(pkt, len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads a variable-length vector prefixed with a one-byte length, and stores
|
||||
* the contents in |subpkt|. |pkt| can equal |subpkt|.
|
||||
* Data is not copied: the |subpkt| packet will share its underlying buffer with
|
||||
* the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
|
||||
* Upon failure, the original |pkt| and |subpkt| are not modified.
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_get_length_prefixed_1(PACKET *pkt,
|
||||
PACKET *subpkt)
|
||||
{
|
||||
unsigned int length;
|
||||
const unsigned char *data;
|
||||
PACKET tmp = *pkt;
|
||||
if (!PACKET_get_1(&tmp, &length) ||
|
||||
!PACKET_get_bytes(&tmp, &data, (size_t)length)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pkt = tmp;
|
||||
subpkt->curr = data;
|
||||
subpkt->remaining = length;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Like PACKET_get_length_prefixed_1, but additionally, fails when there are
|
||||
* leftover bytes in |pkt|.
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_as_length_prefixed_1(PACKET *pkt,
|
||||
PACKET *subpkt)
|
||||
{
|
||||
unsigned int length;
|
||||
const unsigned char *data;
|
||||
PACKET tmp = *pkt;
|
||||
if (!PACKET_get_1(&tmp, &length) ||
|
||||
!PACKET_get_bytes(&tmp, &data, (size_t)length) ||
|
||||
PACKET_remaining(&tmp) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pkt = tmp;
|
||||
subpkt->curr = data;
|
||||
subpkt->remaining = length;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads a variable-length vector prefixed with a two-byte length, and stores
|
||||
* the contents in |subpkt|. |pkt| can equal |subpkt|.
|
||||
* Data is not copied: the |subpkt| packet will share its underlying buffer with
|
||||
* the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
|
||||
* Upon failure, the original |pkt| and |subpkt| are not modified.
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_get_length_prefixed_2(PACKET *pkt,
|
||||
PACKET *subpkt)
|
||||
{
|
||||
unsigned int length;
|
||||
const unsigned char *data;
|
||||
PACKET tmp = *pkt;
|
||||
|
||||
if (!PACKET_get_net_2(&tmp, &length) ||
|
||||
!PACKET_get_bytes(&tmp, &data, (size_t)length)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pkt = tmp;
|
||||
subpkt->curr = data;
|
||||
subpkt->remaining = length;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Like PACKET_get_length_prefixed_2, but additionally, fails when there are
|
||||
* leftover bytes in |pkt|.
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_as_length_prefixed_2(PACKET *pkt,
|
||||
PACKET *subpkt)
|
||||
{
|
||||
unsigned int length;
|
||||
const unsigned char *data;
|
||||
PACKET tmp = *pkt;
|
||||
|
||||
if (!PACKET_get_net_2(&tmp, &length) ||
|
||||
!PACKET_get_bytes(&tmp, &data, (size_t)length) ||
|
||||
PACKET_remaining(&tmp) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pkt = tmp;
|
||||
subpkt->curr = data;
|
||||
subpkt->remaining = length;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads a variable-length vector prefixed with a three-byte length, and stores
|
||||
* the contents in |subpkt|. |pkt| can equal |subpkt|.
|
||||
* Data is not copied: the |subpkt| packet will share its underlying buffer with
|
||||
* the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
|
||||
* Upon failure, the original |pkt| and |subpkt| are not modified.
|
||||
*/
|
||||
__owur static ossl_inline int PACKET_get_length_prefixed_3(PACKET *pkt,
|
||||
PACKET *subpkt)
|
||||
{
|
||||
unsigned long length;
|
||||
const unsigned char *data;
|
||||
PACKET tmp = *pkt;
|
||||
if (!PACKET_get_net_3(&tmp, &length) ||
|
||||
!PACKET_get_bytes(&tmp, &data, (size_t)length)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pkt = tmp;
|
||||
subpkt->curr = data;
|
||||
subpkt->remaining = length;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Writeable packets */
|
||||
|
||||
typedef struct wpacket_sub WPACKET_SUB;
|
||||
struct wpacket_sub {
|
||||
/* The parent WPACKET_SUB if we have one or NULL otherwise */
|
||||
WPACKET_SUB *parent;
|
||||
|
||||
/*
|
||||
* Offset into the buffer where the length of this WPACKET goes. We use an
|
||||
* offset in case the buffer grows and gets reallocated.
|
||||
*/
|
||||
size_t packet_len;
|
||||
|
||||
/* Number of bytes in the packet_len or 0 if we don't write the length */
|
||||
size_t lenbytes;
|
||||
|
||||
/* Number of bytes written to the buf prior to this packet starting */
|
||||
size_t pwritten;
|
||||
|
||||
/* Flags for this sub-packet */
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
typedef struct wpacket_st WPACKET;
|
||||
struct wpacket_st {
|
||||
/* The buffer where we store the output data */
|
||||
BUF_MEM *buf;
|
||||
|
||||
/* Fixed sized buffer which can be used as an alternative to buf */
|
||||
unsigned char *staticbuf;
|
||||
|
||||
/*
|
||||
* Offset into the buffer where we are currently writing. We use an offset
|
||||
* in case the buffer grows and gets reallocated.
|
||||
*/
|
||||
size_t curr;
|
||||
|
||||
/* Number of bytes written so far */
|
||||
size_t written;
|
||||
|
||||
/* Maximum number of bytes we will allow to be written to this WPACKET */
|
||||
size_t maxsize;
|
||||
|
||||
/* Our sub-packets (always at least one if not finished) */
|
||||
WPACKET_SUB *subs;
|
||||
};
|
||||
|
||||
/* Flags */
|
||||
|
||||
/* Default */
|
||||
#define WPACKET_FLAGS_NONE 0
|
||||
|
||||
/* Error on WPACKET_close() if no data written to the WPACKET */
|
||||
#define WPACKET_FLAGS_NON_ZERO_LENGTH 1
|
||||
|
||||
/*
|
||||
* Abandon all changes on WPACKET_close() if no data written to the WPACKET,
|
||||
* i.e. this does not write out a zero packet length
|
||||
*/
|
||||
#define WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH 2
|
||||
|
||||
|
||||
/*
|
||||
* Initialise a WPACKET with the buffer in |buf|. The buffer must exist
|
||||
* for the whole time that the WPACKET is being used. Additionally |lenbytes| of
|
||||
* data is preallocated at the start of the buffer to store the length of the
|
||||
* WPACKET once we know it.
|
||||
*/
|
||||
int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes);
|
||||
|
||||
/*
|
||||
* Same as WPACKET_init_len except there is no preallocation of the WPACKET
|
||||
* length.
|
||||
*/
|
||||
int WPACKET_init(WPACKET *pkt, BUF_MEM *buf);
|
||||
|
||||
/*
|
||||
* Same as WPACKET_init_len except we do not use a growable BUF_MEM structure.
|
||||
* A fixed buffer of memory |buf| of size |len| is used instead. A failure will
|
||||
* occur if you attempt to write beyond the end of the buffer
|
||||
*/
|
||||
int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len,
|
||||
size_t lenbytes);
|
||||
/*
|
||||
* Set the flags to be applied to the current sub-packet
|
||||
*/
|
||||
int WPACKET_set_flags(WPACKET *pkt, unsigned int flags);
|
||||
|
||||
/*
|
||||
* Closes the most recent sub-packet. It also writes out the length of the
|
||||
* packet to the required location (normally the start of the WPACKET) if
|
||||
* appropriate. The top level WPACKET should be closed using WPACKET_finish()
|
||||
* instead of this function.
|
||||
*/
|
||||
int WPACKET_close(WPACKET *pkt);
|
||||
|
||||
/*
|
||||
* The same as WPACKET_close() but only for the top most WPACKET. Additionally
|
||||
* frees memory resources for this WPACKET.
|
||||
*/
|
||||
int WPACKET_finish(WPACKET *pkt);
|
||||
|
||||
/*
|
||||
* Iterate through all the sub-packets and write out their lengths as if they
|
||||
* were being closed. The lengths will be overwritten with the final lengths
|
||||
* when the sub-packets are eventually closed (which may be different if more
|
||||
* data is added to the WPACKET). This function fails if a sub-packet is of 0
|
||||
* length and WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH is set.
|
||||
*/
|
||||
int WPACKET_fill_lengths(WPACKET *pkt);
|
||||
|
||||
/*
|
||||
* Initialise a new sub-packet. Additionally |lenbytes| of data is preallocated
|
||||
* at the start of the sub-packet to store its length once we know it. Don't
|
||||
* call this directly. Use the convenience macros below instead.
|
||||
*/
|
||||
int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes);
|
||||
|
||||
/*
|
||||
* Convenience macros for calling WPACKET_start_sub_packet_len with different
|
||||
* lengths
|
||||
*/
|
||||
#define WPACKET_start_sub_packet_u8(pkt) \
|
||||
WPACKET_start_sub_packet_len__((pkt), 1)
|
||||
#define WPACKET_start_sub_packet_u16(pkt) \
|
||||
WPACKET_start_sub_packet_len__((pkt), 2)
|
||||
#define WPACKET_start_sub_packet_u24(pkt) \
|
||||
WPACKET_start_sub_packet_len__((pkt), 3)
|
||||
#define WPACKET_start_sub_packet_u32(pkt) \
|
||||
WPACKET_start_sub_packet_len__((pkt), 4)
|
||||
|
||||
/*
|
||||
* Same as WPACKET_start_sub_packet_len__() except no bytes are pre-allocated
|
||||
* for the sub-packet length.
|
||||
*/
|
||||
int WPACKET_start_sub_packet(WPACKET *pkt);
|
||||
|
||||
/*
|
||||
* Allocate bytes in the WPACKET for the output. This reserves the bytes
|
||||
* and counts them as "written", but doesn't actually do the writing. A pointer
|
||||
* to the allocated bytes is stored in |*allocbytes|. |allocbytes| may be NULL.
|
||||
* WARNING: the allocated bytes must be filled in immediately, without further
|
||||
* WPACKET_* calls. If not then the underlying buffer may be realloc'd and
|
||||
* change its location.
|
||||
*/
|
||||
int WPACKET_allocate_bytes(WPACKET *pkt, size_t len,
|
||||
unsigned char **allocbytes);
|
||||
|
||||
/*
|
||||
* The same as WPACKET_allocate_bytes() except additionally a new sub-packet is
|
||||
* started for the allocated bytes, and then closed immediately afterwards. The
|
||||
* number of length bytes for the sub-packet is in |lenbytes|. Don't call this
|
||||
* directly. Use the convenience macros below instead.
|
||||
*/
|
||||
int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
|
||||
unsigned char **allocbytes, size_t lenbytes);
|
||||
|
||||
/*
|
||||
* Convenience macros for calling WPACKET_sub_allocate_bytes with different
|
||||
* lengths
|
||||
*/
|
||||
#define WPACKET_sub_allocate_bytes_u8(pkt, len, bytes) \
|
||||
WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 1)
|
||||
#define WPACKET_sub_allocate_bytes_u16(pkt, len, bytes) \
|
||||
WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 2)
|
||||
#define WPACKET_sub_allocate_bytes_u24(pkt, len, bytes) \
|
||||
WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 3)
|
||||
#define WPACKET_sub_allocate_bytes_u32(pkt, len, bytes) \
|
||||
WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 4)
|
||||
|
||||
/*
|
||||
* The same as WPACKET_allocate_bytes() except the reserved bytes are not
|
||||
* actually counted as written. Typically this will be for when we don't know
|
||||
* how big arbitrary data is going to be up front, but we do know what the
|
||||
* maximum size will be. If this function is used, then it should be immediately
|
||||
* followed by a WPACKET_allocate_bytes() call before any other WPACKET
|
||||
* functions are called (unless the write to the allocated bytes is abandoned).
|
||||
*
|
||||
* For example: If we are generating a signature, then the size of that
|
||||
* signature may not be known in advance. We can use WPACKET_reserve_bytes() to
|
||||
* handle this:
|
||||
*
|
||||
* if (!WPACKET_sub_reserve_bytes_u16(&pkt, EVP_PKEY_size(pkey), &sigbytes1)
|
||||
* || EVP_SignFinal(md_ctx, sigbytes1, &siglen, pkey) <= 0
|
||||
* || !WPACKET_sub_allocate_bytes_u16(&pkt, siglen, &sigbytes2)
|
||||
* || sigbytes1 != sigbytes2)
|
||||
* goto err;
|
||||
*/
|
||||
int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes);
|
||||
|
||||
/*
|
||||
* The "reserve_bytes" equivalent of WPACKET_sub_allocate_bytes__()
|
||||
*/
|
||||
int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len,
|
||||
unsigned char **allocbytes, size_t lenbytes);
|
||||
|
||||
/*
|
||||
* Convenience macros for WPACKET_sub_reserve_bytes with different lengths
|
||||
*/
|
||||
#define WPACKET_sub_reserve_bytes_u8(pkt, len, bytes) \
|
||||
WPACKET_reserve_bytes__((pkt), (len), (bytes), 1)
|
||||
#define WPACKET_sub_reserve_bytes_u16(pkt, len, bytes) \
|
||||
WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 2)
|
||||
#define WPACKET_sub_reserve_bytes_u24(pkt, len, bytes) \
|
||||
WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 3)
|
||||
#define WPACKET_sub_reserve_bytes_u32(pkt, len, bytes) \
|
||||
WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 4)
|
||||
|
||||
/*
|
||||
* Write the value stored in |val| into the WPACKET. The value will consume
|
||||
* |bytes| amount of storage. An error will occur if |val| cannot be
|
||||
* accommodated in |bytes| storage, e.g. attempting to write the value 256 into
|
||||
* 1 byte will fail. Don't call this directly. Use the convenience macros below
|
||||
* instead.
|
||||
*/
|
||||
int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t bytes);
|
||||
|
||||
/*
|
||||
* Convenience macros for calling WPACKET_put_bytes with different
|
||||
* lengths
|
||||
*/
|
||||
#define WPACKET_put_bytes_u8(pkt, val) \
|
||||
WPACKET_put_bytes__((pkt), (val), 1)
|
||||
#define WPACKET_put_bytes_u16(pkt, val) \
|
||||
WPACKET_put_bytes__((pkt), (val), 2)
|
||||
#define WPACKET_put_bytes_u24(pkt, val) \
|
||||
WPACKET_put_bytes__((pkt), (val), 3)
|
||||
#define WPACKET_put_bytes_u32(pkt, val) \
|
||||
WPACKET_put_bytes__((pkt), (val), 4)
|
||||
|
||||
/* Set a maximum size that we will not allow the WPACKET to grow beyond */
|
||||
int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize);
|
||||
|
||||
/* Copy |len| bytes of data from |*src| into the WPACKET. */
|
||||
int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len);
|
||||
|
||||
/* Set |len| bytes of data to |ch| into the WPACKET. */
|
||||
int WPACKET_memset(WPACKET *pkt, int ch, size_t len);
|
||||
|
||||
/*
|
||||
* Copy |len| bytes of data from |*src| into the WPACKET and prefix with its
|
||||
* length (consuming |lenbytes| of data for the length). Don't call this
|
||||
* directly. Use the convenience macros below instead.
|
||||
*/
|
||||
int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len,
|
||||
size_t lenbytes);
|
||||
|
||||
/* Convenience macros for calling WPACKET_sub_memcpy with different lengths */
|
||||
#define WPACKET_sub_memcpy_u8(pkt, src, len) \
|
||||
WPACKET_sub_memcpy__((pkt), (src), (len), 1)
|
||||
#define WPACKET_sub_memcpy_u16(pkt, src, len) \
|
||||
WPACKET_sub_memcpy__((pkt), (src), (len), 2)
|
||||
#define WPACKET_sub_memcpy_u24(pkt, src, len) \
|
||||
WPACKET_sub_memcpy__((pkt), (src), (len), 3)
|
||||
#define WPACKET_sub_memcpy_u32(pkt, src, len) \
|
||||
WPACKET_sub_memcpy__((pkt), (src), (len), 4)
|
||||
|
||||
/*
|
||||
* Return the total number of bytes written so far to the underlying buffer
|
||||
* including any storage allocated for length bytes
|
||||
*/
|
||||
int WPACKET_get_total_written(WPACKET *pkt, size_t *written);
|
||||
|
||||
/*
|
||||
* Returns the length of the current sub-packet. This excludes any bytes
|
||||
* allocated for the length itself.
|
||||
*/
|
||||
int WPACKET_get_length(WPACKET *pkt, size_t *len);
|
||||
|
||||
/*
|
||||
* Returns a pointer to the current write location, but does not allocate any
|
||||
* bytes.
|
||||
*/
|
||||
unsigned char *WPACKET_get_curr(WPACKET *pkt);
|
||||
|
||||
/* Release resources in a WPACKET if a failure has occurred. */
|
||||
void WPACKET_cleanup(WPACKET *pkt);
|
||||
|
||||
#endif /* HEADER_PACKET_LOCL_H */
|
158
trunk/3rdparty/openssl-1.1-fit/ssl/pqueue.c
vendored
Normal file
158
trunk/3rdparty/openssl-1.1-fit/ssl/pqueue.c
vendored
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "ssl_locl.h"
|
||||
#include <openssl/bn.h>
|
||||
|
||||
struct pqueue_st {
|
||||
pitem *items;
|
||||
int count;
|
||||
};
|
||||
|
||||
pitem *pitem_new(unsigned char *prio64be, void *data)
|
||||
{
|
||||
pitem *item = OPENSSL_malloc(sizeof(*item));
|
||||
|
||||
if (item == NULL) {
|
||||
SSLerr(SSL_F_PITEM_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(item->priority, prio64be, sizeof(item->priority));
|
||||
item->data = data;
|
||||
item->next = NULL;
|
||||
return item;
|
||||
}
|
||||
|
||||
void pitem_free(pitem *item)
|
||||
{
|
||||
OPENSSL_free(item);
|
||||
}
|
||||
|
||||
pqueue *pqueue_new(void)
|
||||
{
|
||||
pqueue *pq = OPENSSL_zalloc(sizeof(*pq));
|
||||
|
||||
if (pq == NULL)
|
||||
SSLerr(SSL_F_PQUEUE_NEW, ERR_R_MALLOC_FAILURE);
|
||||
|
||||
return pq;
|
||||
}
|
||||
|
||||
void pqueue_free(pqueue *pq)
|
||||
{
|
||||
OPENSSL_free(pq);
|
||||
}
|
||||
|
||||
pitem *pqueue_insert(pqueue *pq, pitem *item)
|
||||
{
|
||||
pitem *curr, *next;
|
||||
|
||||
if (pq->items == NULL) {
|
||||
pq->items = item;
|
||||
return item;
|
||||
}
|
||||
|
||||
for (curr = NULL, next = pq->items;
|
||||
next != NULL; curr = next, next = next->next) {
|
||||
/*
|
||||
* we can compare 64-bit value in big-endian encoding with memcmp:-)
|
||||
*/
|
||||
int cmp = memcmp(next->priority, item->priority, 8);
|
||||
if (cmp > 0) { /* next > item */
|
||||
item->next = next;
|
||||
|
||||
if (curr == NULL)
|
||||
pq->items = item;
|
||||
else
|
||||
curr->next = item;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
else if (cmp == 0) /* duplicates not allowed */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
item->next = NULL;
|
||||
curr->next = item;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
pitem *pqueue_peek(pqueue *pq)
|
||||
{
|
||||
return pq->items;
|
||||
}
|
||||
|
||||
pitem *pqueue_pop(pqueue *pq)
|
||||
{
|
||||
pitem *item = pq->items;
|
||||
|
||||
if (pq->items != NULL)
|
||||
pq->items = pq->items->next;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
pitem *pqueue_find(pqueue *pq, unsigned char *prio64be)
|
||||
{
|
||||
pitem *next;
|
||||
pitem *found = NULL;
|
||||
|
||||
if (pq->items == NULL)
|
||||
return NULL;
|
||||
|
||||
for (next = pq->items; next->next != NULL; next = next->next) {
|
||||
if (memcmp(next->priority, prio64be, 8) == 0) {
|
||||
found = next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* check the one last node */
|
||||
if (memcmp(next->priority, prio64be, 8) == 0)
|
||||
found = next;
|
||||
|
||||
if (!found)
|
||||
return NULL;
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
pitem *pqueue_iterator(pqueue *pq)
|
||||
{
|
||||
return pqueue_peek(pq);
|
||||
}
|
||||
|
||||
pitem *pqueue_next(piterator *item)
|
||||
{
|
||||
pitem *ret;
|
||||
|
||||
if (item == NULL || *item == NULL)
|
||||
return NULL;
|
||||
|
||||
/* *item != NULL */
|
||||
ret = *item;
|
||||
*item = (*item)->next;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t pqueue_size(pqueue *pq)
|
||||
{
|
||||
pitem *item = pq->items;
|
||||
size_t count = 0;
|
||||
|
||||
while (item != NULL) {
|
||||
count++;
|
||||
item = item->next;
|
||||
}
|
||||
return count;
|
||||
}
|
74
trunk/3rdparty/openssl-1.1-fit/ssl/record/README
vendored
Normal file
74
trunk/3rdparty/openssl-1.1-fit/ssl/record/README
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
Record Layer Design
|
||||
===================
|
||||
|
||||
This file provides some guidance on the thinking behind the design of the
|
||||
record layer code to aid future maintenance.
|
||||
|
||||
The record layer is divided into a number of components. At the time of writing
|
||||
there are four: SSL3_RECORD, SSL3_BUFFER, DLTS1_BITMAP and RECORD_LAYER. Each
|
||||
of these components is defined by:
|
||||
1) A struct definition of the same name as the component
|
||||
2) A set of source files that define the functions for that component
|
||||
3) A set of accessor macros
|
||||
|
||||
All struct definitions are in record.h. The functions and macros are either
|
||||
defined in record.h or record_locl.h dependent on whether they are intended to
|
||||
be private to the record layer, or whether they form part of the API to the rest
|
||||
of libssl.
|
||||
|
||||
The source files map to components as follows:
|
||||
|
||||
dtls1_bitmap.c -> DTLS1_BITMAP component
|
||||
ssl3_buffer.c -> SSL3_BUFFER component
|
||||
ssl3_record.c -> SSL3_RECORD component
|
||||
rec_layer_s3.c, rec_layer_d1.c -> RECORD_LAYER component
|
||||
|
||||
The RECORD_LAYER component is a facade pattern, i.e. it provides a simplified
|
||||
interface to the record layer for the rest of libssl. The other 3 components are
|
||||
entirely private to the record layer and therefore should never be accessed
|
||||
directly by libssl.
|
||||
|
||||
Any component can directly access its own members - they are private to that
|
||||
component, e.g. ssl3_buffer.c can access members of the SSL3_BUFFER struct
|
||||
without using a macro. No component can directly access the members of another
|
||||
component, e.g. ssl3_buffer cannot reach inside the RECORD_LAYER component to
|
||||
directly access its members. Instead components use accessor macros, so if code
|
||||
in ssl3_buffer.c wants to access the members of the RECORD_LAYER it uses the
|
||||
RECORD_LAYER_* macros.
|
||||
|
||||
Conceptually it looks like this:
|
||||
|
||||
libssl
|
||||
|
|
||||
---------------------------|-----record.h--------------------------------------
|
||||
|
|
||||
_______V______________
|
||||
| |
|
||||
| RECORD_LAYER |
|
||||
| |
|
||||
| rec_layer_s3.c |
|
||||
| ^ |
|
||||
| _________|__________ |
|
||||
|| ||
|
||||
|| DTLS1_RECORD_LAYER ||
|
||||
|| ||
|
||||
|| rec_layer_d1.c ||
|
||||
||____________________||
|
||||
|______________________|
|
||||
record_locl.h ^ ^ ^
|
||||
_________________| | |_________________
|
||||
| | |
|
||||
_____V_________ ______V________ _______V________
|
||||
| | | | | |
|
||||
| SSL3_BUFFER | | SSL3_RECORD | | DTLS1_BITMAP |
|
||||
| |--->| | | |
|
||||
| ssl3_buffer.c | | ssl3_record.c | | dtls1_bitmap.c |
|
||||
|_______________| |_______________| |________________|
|
||||
|
||||
|
||||
The two RECORD_LAYER source files build on each other, i.e.
|
||||
the main one is rec_layer_s3.c which provides the core SSL/TLS layer. The second
|
||||
one is rec_layer_d1.c which builds off of the SSL/TLS code to provide DTLS
|
||||
specific capabilities. It uses some DTLS specific RECORD_LAYER component members
|
||||
which should only be accessed from rec_layer_d1.c. These are held in the
|
||||
DTLS1_RECORD_LAYER struct.
|
78
trunk/3rdparty/openssl-1.1-fit/ssl/record/dtls1_bitmap.c
vendored
Normal file
78
trunk/3rdparty/openssl-1.1-fit/ssl/record/dtls1_bitmap.c
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "../ssl_locl.h"
|
||||
#include "record_locl.h"
|
||||
|
||||
/* mod 128 saturating subtract of two 64-bit values in big-endian order */
|
||||
static int satsub64be(const unsigned char *v1, const unsigned char *v2)
|
||||
{
|
||||
int64_t ret;
|
||||
uint64_t l1, l2;
|
||||
|
||||
n2l8(v1, l1);
|
||||
n2l8(v2, l2);
|
||||
|
||||
ret = l1 - l2;
|
||||
|
||||
/* We do not permit wrap-around */
|
||||
if (l1 > l2 && ret < 0)
|
||||
return 128;
|
||||
else if (l2 > l1 && ret > 0)
|
||||
return -128;
|
||||
|
||||
if (ret > 128)
|
||||
return 128;
|
||||
else if (ret < -128)
|
||||
return -128;
|
||||
else
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap)
|
||||
{
|
||||
int cmp;
|
||||
unsigned int shift;
|
||||
const unsigned char *seq = s->rlayer.read_sequence;
|
||||
|
||||
cmp = satsub64be(seq, bitmap->max_seq_num);
|
||||
if (cmp > 0) {
|
||||
SSL3_RECORD_set_seq_num(RECORD_LAYER_get_rrec(&s->rlayer), seq);
|
||||
return 1; /* this record in new */
|
||||
}
|
||||
shift = -cmp;
|
||||
if (shift >= sizeof(bitmap->map) * 8)
|
||||
return 0; /* stale, outside the window */
|
||||
else if (bitmap->map & (1UL << shift))
|
||||
return 0; /* record previously received */
|
||||
|
||||
SSL3_RECORD_set_seq_num(RECORD_LAYER_get_rrec(&s->rlayer), seq);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap)
|
||||
{
|
||||
int cmp;
|
||||
unsigned int shift;
|
||||
const unsigned char *seq = RECORD_LAYER_get_read_sequence(&s->rlayer);
|
||||
|
||||
cmp = satsub64be(seq, bitmap->max_seq_num);
|
||||
if (cmp > 0) {
|
||||
shift = cmp;
|
||||
if (shift < sizeof(bitmap->map) * 8)
|
||||
bitmap->map <<= shift, bitmap->map |= 1UL;
|
||||
else
|
||||
bitmap->map = 1UL;
|
||||
memcpy(bitmap->max_seq_num, seq, SEQ_NUM_SIZE);
|
||||
} else {
|
||||
shift = -cmp;
|
||||
if (shift < sizeof(bitmap->map) * 8)
|
||||
bitmap->map |= 1UL << shift;
|
||||
}
|
||||
}
|
1059
trunk/3rdparty/openssl-1.1-fit/ssl/record/rec_layer_d1.c
vendored
Normal file
1059
trunk/3rdparty/openssl-1.1-fit/ssl/record/rec_layer_d1.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
1771
trunk/3rdparty/openssl-1.1-fit/ssl/record/rec_layer_s3.c
vendored
Normal file
1771
trunk/3rdparty/openssl-1.1-fit/ssl/record/rec_layer_s3.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
236
trunk/3rdparty/openssl-1.1-fit/ssl/record/record.h
vendored
Normal file
236
trunk/3rdparty/openssl-1.1-fit/ssl/record/record.h
vendored
Normal file
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* These structures should be considered PRIVATE to the record layer. No *
|
||||
* non-record layer code should be using these structures in any way. *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct ssl3_buffer_st {
|
||||
/* at least SSL3_RT_MAX_PACKET_SIZE bytes, see ssl3_setup_buffers() */
|
||||
unsigned char *buf;
|
||||
/* default buffer size (or 0 if no default set) */
|
||||
size_t default_len;
|
||||
/* buffer size */
|
||||
size_t len;
|
||||
/* where to 'copy from' */
|
||||
size_t offset;
|
||||
/* how many bytes left */
|
||||
size_t left;
|
||||
} SSL3_BUFFER;
|
||||
|
||||
#define SEQ_NUM_SIZE 8
|
||||
|
||||
typedef struct ssl3_record_st {
|
||||
/* Record layer version */
|
||||
/* r */
|
||||
int rec_version;
|
||||
/* type of record */
|
||||
/* r */
|
||||
int type;
|
||||
/* How many bytes available */
|
||||
/* rw */
|
||||
size_t length;
|
||||
/*
|
||||
* How many bytes were available before padding was removed? This is used
|
||||
* to implement the MAC check in constant time for CBC records.
|
||||
*/
|
||||
/* rw */
|
||||
size_t orig_len;
|
||||
/* read/write offset into 'buf' */
|
||||
/* r */
|
||||
size_t off;
|
||||
/* pointer to the record data */
|
||||
/* rw */
|
||||
unsigned char *data;
|
||||
/* where the decode bytes are */
|
||||
/* rw */
|
||||
unsigned char *input;
|
||||
/* only used with decompression - malloc()ed */
|
||||
/* r */
|
||||
unsigned char *comp;
|
||||
/* Whether the data from this record has already been read or not */
|
||||
/* r */
|
||||
unsigned int read;
|
||||
/* epoch number, needed by DTLS1 */
|
||||
/* r */
|
||||
unsigned long epoch;
|
||||
/* sequence number, needed by DTLS1 */
|
||||
/* r */
|
||||
unsigned char seq_num[SEQ_NUM_SIZE];
|
||||
} SSL3_RECORD;
|
||||
|
||||
typedef struct dtls1_bitmap_st {
|
||||
/* Track 32 packets on 32-bit systems and 64 - on 64-bit systems */
|
||||
unsigned long map;
|
||||
/* Max record number seen so far, 64-bit value in big-endian encoding */
|
||||
unsigned char max_seq_num[SEQ_NUM_SIZE];
|
||||
} DTLS1_BITMAP;
|
||||
|
||||
typedef struct record_pqueue_st {
|
||||
unsigned short epoch;
|
||||
struct pqueue_st *q;
|
||||
} record_pqueue;
|
||||
|
||||
typedef struct dtls1_record_data_st {
|
||||
unsigned char *packet;
|
||||
size_t packet_length;
|
||||
SSL3_BUFFER rbuf;
|
||||
SSL3_RECORD rrec;
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
struct bio_dgram_sctp_rcvinfo recordinfo;
|
||||
#endif
|
||||
} DTLS1_RECORD_DATA;
|
||||
|
||||
typedef struct dtls_record_layer_st {
|
||||
/*
|
||||
* The current data and handshake epoch. This is initially
|
||||
* undefined, and starts at zero once the initial handshake is
|
||||
* completed
|
||||
*/
|
||||
unsigned short r_epoch;
|
||||
unsigned short w_epoch;
|
||||
/* records being received in the current epoch */
|
||||
DTLS1_BITMAP bitmap;
|
||||
/* renegotiation starts a new set of sequence numbers */
|
||||
DTLS1_BITMAP next_bitmap;
|
||||
/* Received handshake records (processed and unprocessed) */
|
||||
record_pqueue unprocessed_rcds;
|
||||
record_pqueue processed_rcds;
|
||||
/*
|
||||
* Buffered application records. Only for records between CCS and
|
||||
* Finished to prevent either protocol violation or unnecessary message
|
||||
* loss.
|
||||
*/
|
||||
record_pqueue buffered_app_data;
|
||||
/* save last and current sequence numbers for retransmissions */
|
||||
unsigned char last_write_sequence[8];
|
||||
unsigned char curr_write_sequence[8];
|
||||
} DTLS_RECORD_LAYER;
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* This structure should be considered "opaque" to anything outside of the *
|
||||
* record layer. No non-record layer code should be accessing the members of *
|
||||
* this structure. *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct record_layer_st {
|
||||
/* The parent SSL structure */
|
||||
SSL *s;
|
||||
/*
|
||||
* Read as many input bytes as possible (for
|
||||
* non-blocking reads)
|
||||
*/
|
||||
int read_ahead;
|
||||
/* where we are when reading */
|
||||
int rstate;
|
||||
/* How many pipelines can be used to read data */
|
||||
size_t numrpipes;
|
||||
/* How many pipelines can be used to write data */
|
||||
size_t numwpipes;
|
||||
/* read IO goes into here */
|
||||
SSL3_BUFFER rbuf;
|
||||
/* write IO goes into here */
|
||||
SSL3_BUFFER wbuf[SSL_MAX_PIPELINES];
|
||||
/* each decoded record goes in here */
|
||||
SSL3_RECORD rrec[SSL_MAX_PIPELINES];
|
||||
/* used internally to point at a raw packet */
|
||||
unsigned char *packet;
|
||||
size_t packet_length;
|
||||
/* number of bytes sent so far */
|
||||
size_t wnum;
|
||||
unsigned char handshake_fragment[4];
|
||||
size_t handshake_fragment_len;
|
||||
/* The number of consecutive empty records we have received */
|
||||
size_t empty_record_count;
|
||||
/* partial write - check the numbers match */
|
||||
/* number bytes written */
|
||||
size_t wpend_tot;
|
||||
int wpend_type;
|
||||
/* number of bytes submitted */
|
||||
size_t wpend_ret;
|
||||
const unsigned char *wpend_buf;
|
||||
unsigned char read_sequence[SEQ_NUM_SIZE];
|
||||
unsigned char write_sequence[SEQ_NUM_SIZE];
|
||||
/* Set to true if this is the first record in a connection */
|
||||
unsigned int is_first_record;
|
||||
/* Count of the number of consecutive warning alerts received */
|
||||
unsigned int alert_count;
|
||||
DTLS_RECORD_LAYER *d;
|
||||
} RECORD_LAYER;
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* The following macros/functions represent the libssl internal API to the *
|
||||
* record layer. Any libssl code may call these functions/macros *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
#define MIN_SSL2_RECORD_LEN 9
|
||||
|
||||
#define RECORD_LAYER_set_read_ahead(rl, ra) ((rl)->read_ahead = (ra))
|
||||
#define RECORD_LAYER_get_read_ahead(rl) ((rl)->read_ahead)
|
||||
#define RECORD_LAYER_get_packet(rl) ((rl)->packet)
|
||||
#define RECORD_LAYER_get_packet_length(rl) ((rl)->packet_length)
|
||||
#define RECORD_LAYER_add_packet_length(rl, inc) ((rl)->packet_length += (inc))
|
||||
#define DTLS_RECORD_LAYER_get_w_epoch(rl) ((rl)->d->w_epoch)
|
||||
#define DTLS_RECORD_LAYER_get_processed_rcds(rl) \
|
||||
((rl)->d->processed_rcds)
|
||||
#define DTLS_RECORD_LAYER_get_unprocessed_rcds(rl) \
|
||||
((rl)->d->unprocessed_rcds)
|
||||
#define RECORD_LAYER_get_rbuf(rl) (&(rl)->rbuf)
|
||||
#define RECORD_LAYER_get_wbuf(rl) ((rl)->wbuf)
|
||||
|
||||
void RECORD_LAYER_init(RECORD_LAYER *rl, SSL *s);
|
||||
void RECORD_LAYER_clear(RECORD_LAYER *rl);
|
||||
void RECORD_LAYER_release(RECORD_LAYER *rl);
|
||||
int RECORD_LAYER_read_pending(const RECORD_LAYER *rl);
|
||||
int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl);
|
||||
int RECORD_LAYER_write_pending(const RECORD_LAYER *rl);
|
||||
void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl);
|
||||
void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl);
|
||||
int RECORD_LAYER_is_sslv2_record(RECORD_LAYER *rl);
|
||||
size_t RECORD_LAYER_get_rrec_length(RECORD_LAYER *rl);
|
||||
__owur size_t ssl3_pending(const SSL *s);
|
||||
__owur int ssl3_write_bytes(SSL *s, int type, const void *buf, size_t len,
|
||||
size_t *written);
|
||||
int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
||||
size_t *pipelens, size_t numpipes,
|
||||
int create_empty_fragment, size_t *written);
|
||||
__owur int ssl3_read_bytes(SSL *s, int type, int *recvd_type,
|
||||
unsigned char *buf, size_t len, int peek,
|
||||
size_t *readbytes);
|
||||
__owur int ssl3_setup_buffers(SSL *s);
|
||||
__owur int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int send);
|
||||
__owur int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send);
|
||||
__owur int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len,
|
||||
size_t *written);
|
||||
__owur int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send);
|
||||
__owur int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send);
|
||||
__owur int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send);
|
||||
int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl);
|
||||
void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl);
|
||||
void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl);
|
||||
void DTLS_RECORD_LAYER_set_saved_w_epoch(RECORD_LAYER *rl, unsigned short e);
|
||||
void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl);
|
||||
void DTLS_RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, unsigned char *seq);
|
||||
__owur int dtls1_read_bytes(SSL *s, int type, int *recvd_type,
|
||||
unsigned char *buf, size_t len, int peek,
|
||||
size_t *readbytes);
|
||||
__owur int dtls1_write_bytes(SSL *s, int type, const void *buf, size_t len,
|
||||
size_t *written);
|
||||
int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
|
||||
size_t len, int create_empty_fragment, size_t *written);
|
||||
void dtls1_reset_seq_numbers(SSL *s, int rw);
|
||||
int dtls_buffer_listen_record(SSL *s, size_t len, unsigned char *seq,
|
||||
size_t off);
|
116
trunk/3rdparty/openssl-1.1-fit/ssl/record/record_locl.h
vendored
Normal file
116
trunk/3rdparty/openssl-1.1-fit/ssl/record/record_locl.h
vendored
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* The following macros/functions are PRIVATE to the record layer. They *
|
||||
* should NOT be used outside of the record layer. *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
#define MAX_WARN_ALERT_COUNT 5
|
||||
|
||||
/* Functions/macros provided by the RECORD_LAYER component */
|
||||
|
||||
#define RECORD_LAYER_get_rrec(rl) ((rl)->rrec)
|
||||
#define RECORD_LAYER_set_packet(rl, p) ((rl)->packet = (p))
|
||||
#define RECORD_LAYER_reset_packet_length(rl) ((rl)->packet_length = 0)
|
||||
#define RECORD_LAYER_get_rstate(rl) ((rl)->rstate)
|
||||
#define RECORD_LAYER_set_rstate(rl, st) ((rl)->rstate = (st))
|
||||
#define RECORD_LAYER_get_read_sequence(rl) ((rl)->read_sequence)
|
||||
#define RECORD_LAYER_get_write_sequence(rl) ((rl)->write_sequence)
|
||||
#define RECORD_LAYER_get_numrpipes(rl) ((rl)->numrpipes)
|
||||
#define RECORD_LAYER_set_numrpipes(rl, n) ((rl)->numrpipes = (n))
|
||||
#define RECORD_LAYER_inc_empty_record_count(rl) ((rl)->empty_record_count++)
|
||||
#define RECORD_LAYER_reset_empty_record_count(rl) \
|
||||
((rl)->empty_record_count = 0)
|
||||
#define RECORD_LAYER_get_empty_record_count(rl) ((rl)->empty_record_count)
|
||||
#define RECORD_LAYER_is_first_record(rl) ((rl)->is_first_record)
|
||||
#define RECORD_LAYER_set_first_record(rl) ((rl)->is_first_record = 1)
|
||||
#define RECORD_LAYER_clear_first_record(rl) ((rl)->is_first_record = 0)
|
||||
#define DTLS_RECORD_LAYER_get_r_epoch(rl) ((rl)->d->r_epoch)
|
||||
|
||||
__owur int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold,
|
||||
size_t *readbytes);
|
||||
|
||||
DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
|
||||
unsigned int *is_next_epoch);
|
||||
int dtls1_process_buffered_records(SSL *s);
|
||||
int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue);
|
||||
int dtls1_buffer_record(SSL *s, record_pqueue *q, unsigned char *priority);
|
||||
void ssl3_record_sequence_update(unsigned char *seq);
|
||||
|
||||
/* Functions provided by the DTLS1_BITMAP component */
|
||||
|
||||
int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap);
|
||||
void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap);
|
||||
|
||||
/* Macros/functions provided by the SSL3_BUFFER component */
|
||||
|
||||
#define SSL3_BUFFER_get_buf(b) ((b)->buf)
|
||||
#define SSL3_BUFFER_set_buf(b, n) ((b)->buf = (n))
|
||||
#define SSL3_BUFFER_get_len(b) ((b)->len)
|
||||
#define SSL3_BUFFER_set_len(b, l) ((b)->len = (l))
|
||||
#define SSL3_BUFFER_get_left(b) ((b)->left)
|
||||
#define SSL3_BUFFER_set_left(b, l) ((b)->left = (l))
|
||||
#define SSL3_BUFFER_sub_left(b, l) ((b)->left -= (l))
|
||||
#define SSL3_BUFFER_get_offset(b) ((b)->offset)
|
||||
#define SSL3_BUFFER_set_offset(b, o) ((b)->offset = (o))
|
||||
#define SSL3_BUFFER_add_offset(b, o) ((b)->offset += (o))
|
||||
#define SSL3_BUFFER_is_initialised(b) ((b)->buf != NULL)
|
||||
#define SSL3_BUFFER_set_default_len(b, l) ((b)->default_len = (l))
|
||||
|
||||
void SSL3_BUFFER_clear(SSL3_BUFFER *b);
|
||||
void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, size_t n);
|
||||
void SSL3_BUFFER_release(SSL3_BUFFER *b);
|
||||
__owur int ssl3_setup_read_buffer(SSL *s);
|
||||
__owur int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len);
|
||||
int ssl3_release_read_buffer(SSL *s);
|
||||
int ssl3_release_write_buffer(SSL *s);
|
||||
|
||||
/* Macros/functions provided by the SSL3_RECORD component */
|
||||
|
||||
#define SSL3_RECORD_get_type(r) ((r)->type)
|
||||
#define SSL3_RECORD_set_type(r, t) ((r)->type = (t))
|
||||
#define SSL3_RECORD_set_rec_version(r, v) ((r)->rec_version = (v))
|
||||
#define SSL3_RECORD_get_length(r) ((r)->length)
|
||||
#define SSL3_RECORD_set_length(r, l) ((r)->length = (l))
|
||||
#define SSL3_RECORD_add_length(r, l) ((r)->length += (l))
|
||||
#define SSL3_RECORD_sub_length(r, l) ((r)->length -= (l))
|
||||
#define SSL3_RECORD_get_data(r) ((r)->data)
|
||||
#define SSL3_RECORD_set_data(r, d) ((r)->data = (d))
|
||||
#define SSL3_RECORD_get_input(r) ((r)->input)
|
||||
#define SSL3_RECORD_set_input(r, i) ((r)->input = (i))
|
||||
#define SSL3_RECORD_reset_input(r) ((r)->input = (r)->data)
|
||||
#define SSL3_RECORD_get_seq_num(r) ((r)->seq_num)
|
||||
#define SSL3_RECORD_get_off(r) ((r)->off)
|
||||
#define SSL3_RECORD_set_off(r, o) ((r)->off = (o))
|
||||
#define SSL3_RECORD_add_off(r, o) ((r)->off += (o))
|
||||
#define SSL3_RECORD_get_epoch(r) ((r)->epoch)
|
||||
#define SSL3_RECORD_is_sslv2_record(r) \
|
||||
((r)->rec_version == SSL2_VERSION)
|
||||
#define SSL3_RECORD_is_read(r) ((r)->read)
|
||||
#define SSL3_RECORD_set_read(r) ((r)->read = 1)
|
||||
|
||||
void SSL3_RECORD_clear(SSL3_RECORD *r, size_t);
|
||||
void SSL3_RECORD_release(SSL3_RECORD *r, size_t num_recs);
|
||||
void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num);
|
||||
int ssl3_get_record(SSL *s);
|
||||
__owur int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr);
|
||||
__owur int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr);
|
||||
int ssl3_cbc_copy_mac(unsigned char *out,
|
||||
const SSL3_RECORD *rec, size_t md_size);
|
||||
__owur int ssl3_cbc_remove_padding(SSL3_RECORD *rec,
|
||||
size_t block_size, size_t mac_size);
|
||||
__owur int tls1_cbc_remove_padding(const SSL *s,
|
||||
SSL3_RECORD *rec,
|
||||
size_t block_size, size_t mac_size);
|
||||
int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap);
|
||||
__owur int dtls1_get_record(SSL *s);
|
||||
int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send);
|
179
trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_buffer.c
vendored
Normal file
179
trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_buffer.c
vendored
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "../ssl_locl.h"
|
||||
#include "record_locl.h"
|
||||
|
||||
void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, size_t n)
|
||||
{
|
||||
if (d != NULL)
|
||||
memcpy(b->buf, d, n);
|
||||
b->left = n;
|
||||
b->offset = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the contents of an SSL3_BUFFER but retain any memory allocated. Also
|
||||
* retains the default_len setting
|
||||
*/
|
||||
void SSL3_BUFFER_clear(SSL3_BUFFER *b)
|
||||
{
|
||||
b->offset = 0;
|
||||
b->left = 0;
|
||||
}
|
||||
|
||||
void SSL3_BUFFER_release(SSL3_BUFFER *b)
|
||||
{
|
||||
OPENSSL_free(b->buf);
|
||||
b->buf = NULL;
|
||||
}
|
||||
|
||||
int ssl3_setup_read_buffer(SSL *s)
|
||||
{
|
||||
unsigned char *p;
|
||||
size_t len, align = 0, headerlen;
|
||||
SSL3_BUFFER *b;
|
||||
|
||||
b = RECORD_LAYER_get_rbuf(&s->rlayer);
|
||||
|
||||
if (SSL_IS_DTLS(s))
|
||||
headerlen = DTLS1_RT_HEADER_LENGTH;
|
||||
else
|
||||
headerlen = SSL3_RT_HEADER_LENGTH;
|
||||
|
||||
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
|
||||
align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1);
|
||||
#endif
|
||||
|
||||
if (b->buf == NULL) {
|
||||
len = SSL3_RT_MAX_PLAIN_LENGTH
|
||||
+ SSL3_RT_MAX_ENCRYPTED_OVERHEAD + headerlen + align;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
if (ssl_allow_compression(s))
|
||||
len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
|
||||
#endif
|
||||
if (b->default_len > len)
|
||||
len = b->default_len;
|
||||
if ((p = OPENSSL_malloc(len)) == NULL) {
|
||||
/*
|
||||
* We've got a malloc failure, and we're still initialising buffers.
|
||||
* We assume we're so doomed that we won't even be able to send an
|
||||
* alert.
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_SETUP_READ_BUFFER,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
b->buf = p;
|
||||
b->len = len;
|
||||
}
|
||||
|
||||
RECORD_LAYER_set_packet(&s->rlayer, &(b->buf[0]));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len)
|
||||
{
|
||||
unsigned char *p;
|
||||
size_t align = 0, headerlen;
|
||||
SSL3_BUFFER *wb;
|
||||
size_t currpipe;
|
||||
|
||||
s->rlayer.numwpipes = numwpipes;
|
||||
|
||||
if (len == 0) {
|
||||
if (SSL_IS_DTLS(s))
|
||||
headerlen = DTLS1_RT_HEADER_LENGTH + 1;
|
||||
else
|
||||
headerlen = SSL3_RT_HEADER_LENGTH;
|
||||
|
||||
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
|
||||
align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1);
|
||||
#endif
|
||||
|
||||
len = ssl_get_max_send_fragment(s)
|
||||
+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
if (ssl_allow_compression(s))
|
||||
len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
|
||||
#endif
|
||||
if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
|
||||
len += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD;
|
||||
}
|
||||
|
||||
wb = RECORD_LAYER_get_wbuf(&s->rlayer);
|
||||
for (currpipe = 0; currpipe < numwpipes; currpipe++) {
|
||||
SSL3_BUFFER *thiswb = &wb[currpipe];
|
||||
|
||||
if (thiswb->buf != NULL && thiswb->len != len) {
|
||||
OPENSSL_free(thiswb->buf);
|
||||
thiswb->buf = NULL; /* force reallocation */
|
||||
}
|
||||
|
||||
if (thiswb->buf == NULL) {
|
||||
p = OPENSSL_malloc(len);
|
||||
if (p == NULL) {
|
||||
s->rlayer.numwpipes = currpipe;
|
||||
/*
|
||||
* We've got a malloc failure, and we're still initialising
|
||||
* buffers. We assume we're so doomed that we won't even be able
|
||||
* to send an alert.
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_NO_ALERT,
|
||||
SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
memset(thiswb, 0, sizeof(SSL3_BUFFER));
|
||||
thiswb->buf = p;
|
||||
thiswb->len = len;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ssl3_setup_buffers(SSL *s)
|
||||
{
|
||||
if (!ssl3_setup_read_buffer(s)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
if (!ssl3_setup_write_buffer(s, 1, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ssl3_release_write_buffer(SSL *s)
|
||||
{
|
||||
SSL3_BUFFER *wb;
|
||||
size_t pipes;
|
||||
|
||||
pipes = s->rlayer.numwpipes;
|
||||
while (pipes > 0) {
|
||||
wb = &RECORD_LAYER_get_wbuf(&s->rlayer)[pipes - 1];
|
||||
|
||||
OPENSSL_free(wb->buf);
|
||||
wb->buf = NULL;
|
||||
pipes--;
|
||||
}
|
||||
s->rlayer.numwpipes = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ssl3_release_read_buffer(SSL *s)
|
||||
{
|
||||
SSL3_BUFFER *b;
|
||||
|
||||
b = RECORD_LAYER_get_rbuf(&s->rlayer);
|
||||
OPENSSL_free(b->buf);
|
||||
b->buf = NULL;
|
||||
return 1;
|
||||
}
|
2057
trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_record.c
vendored
Normal file
2057
trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_record.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
196
trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_record_tls13.c
vendored
Normal file
196
trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_record_tls13.c
vendored
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "../ssl_locl.h"
|
||||
#include "record_locl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
/*-
|
||||
* tls13_enc encrypts/decrypts |n_recs| in |recs|. Will call SSLfatal() for
|
||||
* internal errors, but not otherwise.
|
||||
*
|
||||
* Returns:
|
||||
* 0: (in non-constant time) if the record is publically invalid (i.e. too
|
||||
* short etc).
|
||||
* 1: if the record encryption was successful.
|
||||
* -1: if the record's AEAD-authenticator is invalid or, if sending,
|
||||
* an internal error occurred.
|
||||
*/
|
||||
int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
unsigned char iv[EVP_MAX_IV_LENGTH], recheader[SSL3_RT_HEADER_LENGTH];
|
||||
size_t ivlen, taglen, offset, loop, hdrlen;
|
||||
unsigned char *staticiv;
|
||||
unsigned char *seq;
|
||||
int lenu, lenf;
|
||||
SSL3_RECORD *rec = &recs[0];
|
||||
uint32_t alg_enc;
|
||||
WPACKET wpkt;
|
||||
|
||||
if (n_recs != 1) {
|
||||
/* Should not happen */
|
||||
/* TODO(TLS1.3): Support pipelining */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sending) {
|
||||
ctx = s->enc_write_ctx;
|
||||
staticiv = s->write_iv;
|
||||
seq = RECORD_LAYER_get_write_sequence(&s->rlayer);
|
||||
} else {
|
||||
ctx = s->enc_read_ctx;
|
||||
staticiv = s->read_iv;
|
||||
seq = RECORD_LAYER_get_read_sequence(&s->rlayer);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're sending an alert and ctx != NULL then we must be forcing
|
||||
* plaintext alerts. If we're reading and ctx != NULL then we allow
|
||||
* plaintext alerts at certain points in the handshake. If we've got this
|
||||
* far then we have already validated that a plaintext alert is ok here.
|
||||
*/
|
||||
if (ctx == NULL || rec->type == SSL3_RT_ALERT) {
|
||||
memmove(rec->data, rec->input, rec->length);
|
||||
rec->input = rec->data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ivlen = EVP_CIPHER_CTX_iv_length(ctx);
|
||||
|
||||
if (s->early_data_state == SSL_EARLY_DATA_WRITING
|
||||
|| s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
|
||||
if (s->session != NULL && s->session->ext.max_early_data > 0) {
|
||||
alg_enc = s->session->cipher->algorithm_enc;
|
||||
} else {
|
||||
if (!ossl_assert(s->psksession != NULL
|
||||
&& s->psksession->ext.max_early_data > 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
alg_enc = s->psksession->cipher->algorithm_enc;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* To get here we must have selected a ciphersuite - otherwise ctx would
|
||||
* be NULL
|
||||
*/
|
||||
if (!ossl_assert(s->s3->tmp.new_cipher != NULL)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
alg_enc = s->s3->tmp.new_cipher->algorithm_enc;
|
||||
}
|
||||
|
||||
if (alg_enc & SSL_AESCCM) {
|
||||
if (alg_enc & (SSL_AES128CCM8 | SSL_AES256CCM8))
|
||||
taglen = EVP_CCM8_TLS_TAG_LEN;
|
||||
else
|
||||
taglen = EVP_CCM_TLS_TAG_LEN;
|
||||
if (sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen,
|
||||
NULL) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
} else if (alg_enc & SSL_AESGCM) {
|
||||
taglen = EVP_GCM_TLS_TAG_LEN;
|
||||
} else if (alg_enc & SSL_CHACHA20) {
|
||||
taglen = EVP_CHACHAPOLY_TLS_TAG_LEN;
|
||||
} else {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!sending) {
|
||||
/*
|
||||
* Take off tag. There must be at least one byte of content type as
|
||||
* well as the tag
|
||||
*/
|
||||
if (rec->length < taglen + 1)
|
||||
return 0;
|
||||
rec->length -= taglen;
|
||||
}
|
||||
|
||||
/* Set up IV */
|
||||
if (ivlen < SEQ_NUM_SIZE) {
|
||||
/* Should not happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
offset = ivlen - SEQ_NUM_SIZE;
|
||||
memcpy(iv, staticiv, offset);
|
||||
for (loop = 0; loop < SEQ_NUM_SIZE; loop++)
|
||||
iv[offset + loop] = staticiv[offset + loop] ^ seq[loop];
|
||||
|
||||
/* Increment the sequence counter */
|
||||
for (loop = SEQ_NUM_SIZE; loop > 0; loop--) {
|
||||
++seq[loop - 1];
|
||||
if (seq[loop - 1] != 0)
|
||||
break;
|
||||
}
|
||||
if (loop == 0) {
|
||||
/* Sequence has wrapped */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO(size_t): lenu/lenf should be a size_t but EVP doesn't support it */
|
||||
if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, sending) <= 0
|
||||
|| (!sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
|
||||
taglen,
|
||||
rec->data + rec->length) <= 0)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set up the AAD */
|
||||
if (!WPACKET_init_static_len(&wpkt, recheader, sizeof(recheader), 0)
|
||||
|| !WPACKET_put_bytes_u8(&wpkt, rec->type)
|
||||
|| !WPACKET_put_bytes_u16(&wpkt, rec->rec_version)
|
||||
|| !WPACKET_put_bytes_u16(&wpkt, rec->length + taglen)
|
||||
|| !WPACKET_get_total_written(&wpkt, &hdrlen)
|
||||
|| hdrlen != SSL3_RT_HEADER_LENGTH
|
||||
|| !WPACKET_finish(&wpkt)) {
|
||||
WPACKET_cleanup(&wpkt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* For CCM we must explicitly set the total plaintext length before we add
|
||||
* any AAD.
|
||||
*/
|
||||
if (((alg_enc & SSL_AESCCM) != 0
|
||||
&& EVP_CipherUpdate(ctx, NULL, &lenu, NULL,
|
||||
(unsigned int)rec->length) <= 0)
|
||||
|| EVP_CipherUpdate(ctx, NULL, &lenu, recheader,
|
||||
sizeof(recheader)) <= 0
|
||||
|| EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input,
|
||||
(unsigned int)rec->length) <= 0
|
||||
|| EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0
|
||||
|| (size_t)(lenu + lenf) != rec->length) {
|
||||
return -1;
|
||||
}
|
||||
if (sending) {
|
||||
/* Add the tag */
|
||||
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen,
|
||||
rec->data + rec->length) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
rec->length += taglen;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
487
trunk/3rdparty/openssl-1.1-fit/ssl/s3_cbc.c
vendored
Normal file
487
trunk/3rdparty/openssl-1.1-fit/ssl/s3_cbc.c
vendored
Normal file
|
@ -0,0 +1,487 @@
|
|||
/*
|
||||
* Copyright 2012-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "internal/constant_time_locl.h"
|
||||
#include "ssl_locl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
/*
|
||||
* MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's
|
||||
* length field. (SHA-384/512 have 128-bit length.)
|
||||
*/
|
||||
#define MAX_HASH_BIT_COUNT_BYTES 16
|
||||
|
||||
/*
|
||||
* MAX_HASH_BLOCK_SIZE is the maximum hash block size that we'll support.
|
||||
* Currently SHA-384/512 has a 128-byte block size and that's the largest
|
||||
* supported by TLS.)
|
||||
*/
|
||||
#define MAX_HASH_BLOCK_SIZE 128
|
||||
|
||||
/*
|
||||
* u32toLE serialises an unsigned, 32-bit number (n) as four bytes at (p) in
|
||||
* little-endian order. The value of p is advanced by four.
|
||||
*/
|
||||
#define u32toLE(n, p) \
|
||||
(*((p)++)=(unsigned char)(n), \
|
||||
*((p)++)=(unsigned char)(n>>8), \
|
||||
*((p)++)=(unsigned char)(n>>16), \
|
||||
*((p)++)=(unsigned char)(n>>24))
|
||||
|
||||
/*
|
||||
* These functions serialize the state of a hash and thus perform the
|
||||
* standard "final" operation without adding the padding and length that such
|
||||
* a function typically does.
|
||||
*/
|
||||
static void tls1_md5_final_raw(void *ctx, unsigned char *md_out)
|
||||
{
|
||||
MD5_CTX *md5 = ctx;
|
||||
u32toLE(md5->A, md_out);
|
||||
u32toLE(md5->B, md_out);
|
||||
u32toLE(md5->C, md_out);
|
||||
u32toLE(md5->D, md_out);
|
||||
}
|
||||
|
||||
static void tls1_sha1_final_raw(void *ctx, unsigned char *md_out)
|
||||
{
|
||||
SHA_CTX *sha1 = ctx;
|
||||
l2n(sha1->h0, md_out);
|
||||
l2n(sha1->h1, md_out);
|
||||
l2n(sha1->h2, md_out);
|
||||
l2n(sha1->h3, md_out);
|
||||
l2n(sha1->h4, md_out);
|
||||
}
|
||||
|
||||
static void tls1_sha256_final_raw(void *ctx, unsigned char *md_out)
|
||||
{
|
||||
SHA256_CTX *sha256 = ctx;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
l2n(sha256->h[i], md_out);
|
||||
}
|
||||
}
|
||||
|
||||
static void tls1_sha512_final_raw(void *ctx, unsigned char *md_out)
|
||||
{
|
||||
SHA512_CTX *sha512 = ctx;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
l2n8(sha512->h[i], md_out);
|
||||
}
|
||||
}
|
||||
|
||||
#undef LARGEST_DIGEST_CTX
|
||||
#define LARGEST_DIGEST_CTX SHA512_CTX
|
||||
|
||||
/*
|
||||
* ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function
|
||||
* which ssl3_cbc_digest_record supports.
|
||||
*/
|
||||
char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
|
||||
{
|
||||
switch (EVP_MD_CTX_type(ctx)) {
|
||||
case NID_md5:
|
||||
case NID_sha1:
|
||||
case NID_sha224:
|
||||
case NID_sha256:
|
||||
case NID_sha384:
|
||||
case NID_sha512:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
* ssl3_cbc_digest_record computes the MAC of a decrypted, padded SSLv3/TLS
|
||||
* record.
|
||||
*
|
||||
* ctx: the EVP_MD_CTX from which we take the hash function.
|
||||
* ssl3_cbc_record_digest_supported must return true for this EVP_MD_CTX.
|
||||
* md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written.
|
||||
* md_out_size: if non-NULL, the number of output bytes is written here.
|
||||
* header: the 13-byte, TLS record header.
|
||||
* data: the record data itself, less any preceding explicit IV.
|
||||
* data_plus_mac_size: the secret, reported length of the data and MAC
|
||||
* once the padding has been removed.
|
||||
* data_plus_mac_plus_padding_size: the public length of the whole
|
||||
* record, including padding.
|
||||
* is_sslv3: non-zero if we are to use SSLv3. Otherwise, TLS.
|
||||
*
|
||||
* On entry: by virtue of having been through one of the remove_padding
|
||||
* functions, above, we know that data_plus_mac_size is large enough to contain
|
||||
* a padding byte and MAC. (If the padding was invalid, it might contain the
|
||||
* padding too. )
|
||||
* Returns 1 on success or 0 on error
|
||||
*/
|
||||
int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
|
||||
unsigned char *md_out,
|
||||
size_t *md_out_size,
|
||||
const unsigned char header[13],
|
||||
const unsigned char *data,
|
||||
size_t data_plus_mac_size,
|
||||
size_t data_plus_mac_plus_padding_size,
|
||||
const unsigned char *mac_secret,
|
||||
size_t mac_secret_length, char is_sslv3)
|
||||
{
|
||||
union {
|
||||
double align;
|
||||
unsigned char c[sizeof(LARGEST_DIGEST_CTX)];
|
||||
} md_state;
|
||||
void (*md_final_raw) (void *ctx, unsigned char *md_out);
|
||||
void (*md_transform) (void *ctx, const unsigned char *block);
|
||||
size_t md_size, md_block_size = 64;
|
||||
size_t sslv3_pad_length = 40, header_length, variance_blocks,
|
||||
len, max_mac_bytes, num_blocks,
|
||||
num_starting_blocks, k, mac_end_offset, c, index_a, index_b;
|
||||
size_t bits; /* at most 18 bits */
|
||||
unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES];
|
||||
/* hmac_pad is the masked HMAC key. */
|
||||
unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE];
|
||||
unsigned char first_block[MAX_HASH_BLOCK_SIZE];
|
||||
unsigned char mac_out[EVP_MAX_MD_SIZE];
|
||||
size_t i, j;
|
||||
unsigned md_out_size_u;
|
||||
EVP_MD_CTX *md_ctx = NULL;
|
||||
/*
|
||||
* mdLengthSize is the number of bytes in the length field that
|
||||
* terminates * the hash.
|
||||
*/
|
||||
size_t md_length_size = 8;
|
||||
char length_is_big_endian = 1;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* This is a, hopefully redundant, check that allows us to forget about
|
||||
* many possible overflows later in this function.
|
||||
*/
|
||||
if (!ossl_assert(data_plus_mac_plus_padding_size < 1024 * 1024))
|
||||
return 0;
|
||||
|
||||
switch (EVP_MD_CTX_type(ctx)) {
|
||||
case NID_md5:
|
||||
if (MD5_Init((MD5_CTX *)md_state.c) <= 0)
|
||||
return 0;
|
||||
md_final_raw = tls1_md5_final_raw;
|
||||
md_transform =
|
||||
(void (*)(void *ctx, const unsigned char *block))MD5_Transform;
|
||||
md_size = 16;
|
||||
sslv3_pad_length = 48;
|
||||
length_is_big_endian = 0;
|
||||
break;
|
||||
case NID_sha1:
|
||||
if (SHA1_Init((SHA_CTX *)md_state.c) <= 0)
|
||||
return 0;
|
||||
md_final_raw = tls1_sha1_final_raw;
|
||||
md_transform =
|
||||
(void (*)(void *ctx, const unsigned char *block))SHA1_Transform;
|
||||
md_size = 20;
|
||||
break;
|
||||
case NID_sha224:
|
||||
if (SHA224_Init((SHA256_CTX *)md_state.c) <= 0)
|
||||
return 0;
|
||||
md_final_raw = tls1_sha256_final_raw;
|
||||
md_transform =
|
||||
(void (*)(void *ctx, const unsigned char *block))SHA256_Transform;
|
||||
md_size = 224 / 8;
|
||||
break;
|
||||
case NID_sha256:
|
||||
if (SHA256_Init((SHA256_CTX *)md_state.c) <= 0)
|
||||
return 0;
|
||||
md_final_raw = tls1_sha256_final_raw;
|
||||
md_transform =
|
||||
(void (*)(void *ctx, const unsigned char *block))SHA256_Transform;
|
||||
md_size = 32;
|
||||
break;
|
||||
case NID_sha384:
|
||||
if (SHA384_Init((SHA512_CTX *)md_state.c) <= 0)
|
||||
return 0;
|
||||
md_final_raw = tls1_sha512_final_raw;
|
||||
md_transform =
|
||||
(void (*)(void *ctx, const unsigned char *block))SHA512_Transform;
|
||||
md_size = 384 / 8;
|
||||
md_block_size = 128;
|
||||
md_length_size = 16;
|
||||
break;
|
||||
case NID_sha512:
|
||||
if (SHA512_Init((SHA512_CTX *)md_state.c) <= 0)
|
||||
return 0;
|
||||
md_final_raw = tls1_sha512_final_raw;
|
||||
md_transform =
|
||||
(void (*)(void *ctx, const unsigned char *block))SHA512_Transform;
|
||||
md_size = 64;
|
||||
md_block_size = 128;
|
||||
md_length_size = 16;
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* ssl3_cbc_record_digest_supported should have been called first to
|
||||
* check that the hash function is supported.
|
||||
*/
|
||||
if (md_out_size != NULL)
|
||||
*md_out_size = 0;
|
||||
return ossl_assert(0);
|
||||
}
|
||||
|
||||
if (!ossl_assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES)
|
||||
|| !ossl_assert(md_block_size <= MAX_HASH_BLOCK_SIZE)
|
||||
|| !ossl_assert(md_size <= EVP_MAX_MD_SIZE))
|
||||
return 0;
|
||||
|
||||
header_length = 13;
|
||||
if (is_sslv3) {
|
||||
header_length = mac_secret_length + sslv3_pad_length + 8 /* sequence
|
||||
* number */ +
|
||||
1 /* record type */ +
|
||||
2 /* record length */ ;
|
||||
}
|
||||
|
||||
/*
|
||||
* variance_blocks is the number of blocks of the hash that we have to
|
||||
* calculate in constant time because they could be altered by the
|
||||
* padding value. In SSLv3, the padding must be minimal so the end of
|
||||
* the plaintext varies by, at most, 15+20 = 35 bytes. (We conservatively
|
||||
* assume that the MAC size varies from 0..20 bytes.) In case the 9 bytes
|
||||
* of hash termination (0x80 + 64-bit length) don't fit in the final
|
||||
* block, we say that the final two blocks can vary based on the padding.
|
||||
* TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
|
||||
* required to be minimal. Therefore we say that the final |variance_blocks|
|
||||
* blocks can
|
||||
* vary based on the padding. Later in the function, if the message is
|
||||
* short and there obviously cannot be this many blocks then
|
||||
* variance_blocks can be reduced.
|
||||
*/
|
||||
variance_blocks = is_sslv3 ? 2 : ( ((255 + 1 + md_size + md_block_size - 1) / md_block_size) + 1);
|
||||
/*
|
||||
* From now on we're dealing with the MAC, which conceptually has 13
|
||||
* bytes of `header' before the start of the data (TLS) or 71/75 bytes
|
||||
* (SSLv3)
|
||||
*/
|
||||
len = data_plus_mac_plus_padding_size + header_length;
|
||||
/*
|
||||
* max_mac_bytes contains the maximum bytes of bytes in the MAC,
|
||||
* including * |header|, assuming that there's no padding.
|
||||
*/
|
||||
max_mac_bytes = len - md_size - 1;
|
||||
/* num_blocks is the maximum number of hash blocks. */
|
||||
num_blocks =
|
||||
(max_mac_bytes + 1 + md_length_size + md_block_size -
|
||||
1) / md_block_size;
|
||||
/*
|
||||
* In order to calculate the MAC in constant time we have to handle the
|
||||
* final blocks specially because the padding value could cause the end
|
||||
* to appear somewhere in the final |variance_blocks| blocks and we can't
|
||||
* leak where. However, |num_starting_blocks| worth of data can be hashed
|
||||
* right away because no padding value can affect whether they are
|
||||
* plaintext.
|
||||
*/
|
||||
num_starting_blocks = 0;
|
||||
/*
|
||||
* k is the starting byte offset into the conceptual header||data where
|
||||
* we start processing.
|
||||
*/
|
||||
k = 0;
|
||||
/*
|
||||
* mac_end_offset is the index just past the end of the data to be MACed.
|
||||
*/
|
||||
mac_end_offset = data_plus_mac_size + header_length - md_size;
|
||||
/*
|
||||
* c is the index of the 0x80 byte in the final hash block that contains
|
||||
* application data.
|
||||
*/
|
||||
c = mac_end_offset % md_block_size;
|
||||
/*
|
||||
* index_a is the hash block number that contains the 0x80 terminating
|
||||
* value.
|
||||
*/
|
||||
index_a = mac_end_offset / md_block_size;
|
||||
/*
|
||||
* index_b is the hash block number that contains the 64-bit hash length,
|
||||
* in bits.
|
||||
*/
|
||||
index_b = (mac_end_offset + md_length_size) / md_block_size;
|
||||
/*
|
||||
* bits is the hash-length in bits. It includes the additional hash block
|
||||
* for the masked HMAC key, or whole of |header| in the case of SSLv3.
|
||||
*/
|
||||
|
||||
/*
|
||||
* For SSLv3, if we're going to have any starting blocks then we need at
|
||||
* least two because the header is larger than a single block.
|
||||
*/
|
||||
if (num_blocks > variance_blocks + (is_sslv3 ? 1 : 0)) {
|
||||
num_starting_blocks = num_blocks - variance_blocks;
|
||||
k = md_block_size * num_starting_blocks;
|
||||
}
|
||||
|
||||
bits = 8 * mac_end_offset;
|
||||
if (!is_sslv3) {
|
||||
/*
|
||||
* Compute the initial HMAC block. For SSLv3, the padding and secret
|
||||
* bytes are included in |header| because they take more than a
|
||||
* single block.
|
||||
*/
|
||||
bits += 8 * md_block_size;
|
||||
memset(hmac_pad, 0, md_block_size);
|
||||
if (!ossl_assert(mac_secret_length <= sizeof(hmac_pad)))
|
||||
return 0;
|
||||
memcpy(hmac_pad, mac_secret, mac_secret_length);
|
||||
for (i = 0; i < md_block_size; i++)
|
||||
hmac_pad[i] ^= 0x36;
|
||||
|
||||
md_transform(md_state.c, hmac_pad);
|
||||
}
|
||||
|
||||
if (length_is_big_endian) {
|
||||
memset(length_bytes, 0, md_length_size - 4);
|
||||
length_bytes[md_length_size - 4] = (unsigned char)(bits >> 24);
|
||||
length_bytes[md_length_size - 3] = (unsigned char)(bits >> 16);
|
||||
length_bytes[md_length_size - 2] = (unsigned char)(bits >> 8);
|
||||
length_bytes[md_length_size - 1] = (unsigned char)bits;
|
||||
} else {
|
||||
memset(length_bytes, 0, md_length_size);
|
||||
length_bytes[md_length_size - 5] = (unsigned char)(bits >> 24);
|
||||
length_bytes[md_length_size - 6] = (unsigned char)(bits >> 16);
|
||||
length_bytes[md_length_size - 7] = (unsigned char)(bits >> 8);
|
||||
length_bytes[md_length_size - 8] = (unsigned char)bits;
|
||||
}
|
||||
|
||||
if (k > 0) {
|
||||
if (is_sslv3) {
|
||||
size_t overhang;
|
||||
|
||||
/*
|
||||
* The SSLv3 header is larger than a single block. overhang is
|
||||
* the number of bytes beyond a single block that the header
|
||||
* consumes: either 7 bytes (SHA1) or 11 bytes (MD5). There are no
|
||||
* ciphersuites in SSLv3 that are not SHA1 or MD5 based and
|
||||
* therefore we can be confident that the header_length will be
|
||||
* greater than |md_block_size|. However we add a sanity check just
|
||||
* in case
|
||||
*/
|
||||
if (header_length <= md_block_size) {
|
||||
/* Should never happen */
|
||||
return 0;
|
||||
}
|
||||
overhang = header_length - md_block_size;
|
||||
md_transform(md_state.c, header);
|
||||
memcpy(first_block, header + md_block_size, overhang);
|
||||
memcpy(first_block + overhang, data, md_block_size - overhang);
|
||||
md_transform(md_state.c, first_block);
|
||||
for (i = 1; i < k / md_block_size - 1; i++)
|
||||
md_transform(md_state.c, data + md_block_size * i - overhang);
|
||||
} else {
|
||||
/* k is a multiple of md_block_size. */
|
||||
memcpy(first_block, header, 13);
|
||||
memcpy(first_block + 13, data, md_block_size - 13);
|
||||
md_transform(md_state.c, first_block);
|
||||
for (i = 1; i < k / md_block_size; i++)
|
||||
md_transform(md_state.c, data + md_block_size * i - 13);
|
||||
}
|
||||
}
|
||||
|
||||
memset(mac_out, 0, sizeof(mac_out));
|
||||
|
||||
/*
|
||||
* We now process the final hash blocks. For each block, we construct it
|
||||
* in constant time. If the |i==index_a| then we'll include the 0x80
|
||||
* bytes and zero pad etc. For each block we selectively copy it, in
|
||||
* constant time, to |mac_out|.
|
||||
*/
|
||||
for (i = num_starting_blocks; i <= num_starting_blocks + variance_blocks;
|
||||
i++) {
|
||||
unsigned char block[MAX_HASH_BLOCK_SIZE];
|
||||
unsigned char is_block_a = constant_time_eq_8_s(i, index_a);
|
||||
unsigned char is_block_b = constant_time_eq_8_s(i, index_b);
|
||||
for (j = 0; j < md_block_size; j++) {
|
||||
unsigned char b = 0, is_past_c, is_past_cp1;
|
||||
if (k < header_length)
|
||||
b = header[k];
|
||||
else if (k < data_plus_mac_plus_padding_size + header_length)
|
||||
b = data[k - header_length];
|
||||
k++;
|
||||
|
||||
is_past_c = is_block_a & constant_time_ge_8_s(j, c);
|
||||
is_past_cp1 = is_block_a & constant_time_ge_8_s(j, c + 1);
|
||||
/*
|
||||
* If this is the block containing the end of the application
|
||||
* data, and we are at the offset for the 0x80 value, then
|
||||
* overwrite b with 0x80.
|
||||
*/
|
||||
b = constant_time_select_8(is_past_c, 0x80, b);
|
||||
/*
|
||||
* If this block contains the end of the application data
|
||||
* and we're past the 0x80 value then just write zero.
|
||||
*/
|
||||
b = b & ~is_past_cp1;
|
||||
/*
|
||||
* If this is index_b (the final block), but not index_a (the end
|
||||
* of the data), then the 64-bit length didn't fit into index_a
|
||||
* and we're having to add an extra block of zeros.
|
||||
*/
|
||||
b &= ~is_block_b | is_block_a;
|
||||
|
||||
/*
|
||||
* The final bytes of one of the blocks contains the length.
|
||||
*/
|
||||
if (j >= md_block_size - md_length_size) {
|
||||
/* If this is index_b, write a length byte. */
|
||||
b = constant_time_select_8(is_block_b,
|
||||
length_bytes[j -
|
||||
(md_block_size -
|
||||
md_length_size)], b);
|
||||
}
|
||||
block[j] = b;
|
||||
}
|
||||
|
||||
md_transform(md_state.c, block);
|
||||
md_final_raw(md_state.c, block);
|
||||
/* If this is index_b, copy the hash value to |mac_out|. */
|
||||
for (j = 0; j < md_size; j++)
|
||||
mac_out[j] |= block[j] & is_block_b;
|
||||
}
|
||||
|
||||
md_ctx = EVP_MD_CTX_new();
|
||||
if (md_ctx == NULL)
|
||||
goto err;
|
||||
if (EVP_DigestInit_ex(md_ctx, EVP_MD_CTX_md(ctx), NULL /* engine */ ) <= 0)
|
||||
goto err;
|
||||
if (is_sslv3) {
|
||||
/* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */
|
||||
memset(hmac_pad, 0x5c, sslv3_pad_length);
|
||||
|
||||
if (EVP_DigestUpdate(md_ctx, mac_secret, mac_secret_length) <= 0
|
||||
|| EVP_DigestUpdate(md_ctx, hmac_pad, sslv3_pad_length) <= 0
|
||||
|| EVP_DigestUpdate(md_ctx, mac_out, md_size) <= 0)
|
||||
goto err;
|
||||
} else {
|
||||
/* Complete the HMAC in the standard manner. */
|
||||
for (i = 0; i < md_block_size; i++)
|
||||
hmac_pad[i] ^= 0x6a;
|
||||
|
||||
if (EVP_DigestUpdate(md_ctx, hmac_pad, md_block_size) <= 0
|
||||
|| EVP_DigestUpdate(md_ctx, mac_out, md_size) <= 0)
|
||||
goto err;
|
||||
}
|
||||
/* TODO(size_t): Convert me */
|
||||
ret = EVP_DigestFinal(md_ctx, md_out, &md_out_size_u);
|
||||
if (ret && md_out_size)
|
||||
*md_out_size = md_out_size_u;
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
|
||||
return 1;
|
||||
err:
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
return 0;
|
||||
}
|
595
trunk/3rdparty/openssl-1.1-fit/ssl/s3_enc.c
vendored
Normal file
595
trunk/3rdparty/openssl-1.1-fit/ssl/s3_enc.c
vendored
Normal file
|
@ -0,0 +1,595 @@
|
|||
/*
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2005 Nokia. All rights reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "ssl_locl.h"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/md5.h>
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
|
||||
{
|
||||
EVP_MD_CTX *m5;
|
||||
EVP_MD_CTX *s1;
|
||||
unsigned char buf[16], smd[SHA_DIGEST_LENGTH];
|
||||
unsigned char c = 'A';
|
||||
unsigned int i, j, k;
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CHARSET_EBCDIC
|
||||
c = os_toascii[c]; /* 'A' in ASCII */
|
||||
#endif
|
||||
k = 0;
|
||||
m5 = EVP_MD_CTX_new();
|
||||
s1 = EVP_MD_CTX_new();
|
||||
if (m5 == NULL || s1 == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
EVP_MD_CTX_set_flags(m5, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
|
||||
for (i = 0; (int)i < num; i += MD5_DIGEST_LENGTH) {
|
||||
k++;
|
||||
if (k > sizeof(buf)) {
|
||||
/* bug: 'buf' is too small for this ciphersuite */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (j = 0; j < k; j++)
|
||||
buf[j] = c;
|
||||
c++;
|
||||
if (!EVP_DigestInit_ex(s1, EVP_sha1(), NULL)
|
||||
|| !EVP_DigestUpdate(s1, buf, k)
|
||||
|| !EVP_DigestUpdate(s1, s->session->master_key,
|
||||
s->session->master_key_length)
|
||||
|| !EVP_DigestUpdate(s1, s->s3->server_random, SSL3_RANDOM_SIZE)
|
||||
|| !EVP_DigestUpdate(s1, s->s3->client_random, SSL3_RANDOM_SIZE)
|
||||
|| !EVP_DigestFinal_ex(s1, smd, NULL)
|
||||
|| !EVP_DigestInit_ex(m5, EVP_md5(), NULL)
|
||||
|| !EVP_DigestUpdate(m5, s->session->master_key,
|
||||
s->session->master_key_length)
|
||||
|| !EVP_DigestUpdate(m5, smd, SHA_DIGEST_LENGTH)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if ((int)(i + MD5_DIGEST_LENGTH) > num) {
|
||||
if (!EVP_DigestFinal_ex(m5, smd, NULL)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
memcpy(km, smd, (num - i));
|
||||
} else {
|
||||
if (!EVP_DigestFinal_ex(m5, km, NULL)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
km += MD5_DIGEST_LENGTH;
|
||||
}
|
||||
OPENSSL_cleanse(smd, sizeof(smd));
|
||||
ret = 1;
|
||||
err:
|
||||
EVP_MD_CTX_free(m5);
|
||||
EVP_MD_CTX_free(s1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssl3_change_cipher_state(SSL *s, int which)
|
||||
{
|
||||
unsigned char *p, *mac_secret;
|
||||
unsigned char *ms, *key, *iv;
|
||||
EVP_CIPHER_CTX *dd;
|
||||
const EVP_CIPHER *c;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
COMP_METHOD *comp;
|
||||
#endif
|
||||
const EVP_MD *m;
|
||||
int mdi;
|
||||
size_t n, i, j, k, cl;
|
||||
int reuse_dd = 0;
|
||||
|
||||
c = s->s3->tmp.new_sym_enc;
|
||||
m = s->s3->tmp.new_hash;
|
||||
/* m == NULL will lead to a crash later */
|
||||
if (!ossl_assert(m != NULL)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
if (s->s3->tmp.new_compression == NULL)
|
||||
comp = NULL;
|
||||
else
|
||||
comp = s->s3->tmp.new_compression->method;
|
||||
#endif
|
||||
|
||||
if (which & SSL3_CC_READ) {
|
||||
if (s->enc_read_ctx != NULL) {
|
||||
reuse_dd = 1;
|
||||
} else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
} else {
|
||||
/*
|
||||
* make sure it's initialised in case we exit later with an error
|
||||
*/
|
||||
EVP_CIPHER_CTX_reset(s->enc_read_ctx);
|
||||
}
|
||||
dd = s->enc_read_ctx;
|
||||
|
||||
if (ssl_replace_hash(&s->read_hash, m) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
/* COMPRESS */
|
||||
COMP_CTX_free(s->expand);
|
||||
s->expand = NULL;
|
||||
if (comp != NULL) {
|
||||
s->expand = COMP_CTX_new(comp);
|
||||
if (s->expand == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_SSL3_CHANGE_CIPHER_STATE,
|
||||
SSL_R_COMPRESSION_LIBRARY_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
RECORD_LAYER_reset_read_sequence(&s->rlayer);
|
||||
mac_secret = &(s->s3->read_mac_secret[0]);
|
||||
} else {
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
|
||||
if (s->enc_write_ctx != NULL) {
|
||||
reuse_dd = 1;
|
||||
} else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
} else {
|
||||
/*
|
||||
* make sure it's initialised in case we exit later with an error
|
||||
*/
|
||||
EVP_CIPHER_CTX_reset(s->enc_write_ctx);
|
||||
}
|
||||
dd = s->enc_write_ctx;
|
||||
if (ssl_replace_hash(&s->write_hash, m) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
/* COMPRESS */
|
||||
COMP_CTX_free(s->compress);
|
||||
s->compress = NULL;
|
||||
if (comp != NULL) {
|
||||
s->compress = COMP_CTX_new(comp);
|
||||
if (s->compress == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_SSL3_CHANGE_CIPHER_STATE,
|
||||
SSL_R_COMPRESSION_LIBRARY_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
RECORD_LAYER_reset_write_sequence(&s->rlayer);
|
||||
mac_secret = &(s->s3->write_mac_secret[0]);
|
||||
}
|
||||
|
||||
if (reuse_dd)
|
||||
EVP_CIPHER_CTX_reset(dd);
|
||||
|
||||
p = s->s3->tmp.key_block;
|
||||
mdi = EVP_MD_size(m);
|
||||
if (mdi < 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
i = mdi;
|
||||
cl = EVP_CIPHER_key_length(c);
|
||||
j = cl;
|
||||
k = EVP_CIPHER_iv_length(c);
|
||||
if ((which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
|
||||
(which == SSL3_CHANGE_CIPHER_SERVER_READ)) {
|
||||
ms = &(p[0]);
|
||||
n = i + i;
|
||||
key = &(p[n]);
|
||||
n += j + j;
|
||||
iv = &(p[n]);
|
||||
n += k + k;
|
||||
} else {
|
||||
n = i;
|
||||
ms = &(p[n]);
|
||||
n += i + j;
|
||||
key = &(p[n]);
|
||||
n += j + k;
|
||||
iv = &(p[n]);
|
||||
n += k;
|
||||
}
|
||||
|
||||
if (n > s->s3->tmp.key_block_length) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(mac_secret, ms, i);
|
||||
|
||||
if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE))) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
|
||||
return 1;
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ssl3_setup_key_block(SSL *s)
|
||||
{
|
||||
unsigned char *p;
|
||||
const EVP_CIPHER *c;
|
||||
const EVP_MD *hash;
|
||||
int num;
|
||||
int ret = 0;
|
||||
SSL_COMP *comp;
|
||||
|
||||
if (s->s3->tmp.key_block_length != 0)
|
||||
return 1;
|
||||
|
||||
if (!ssl_cipher_get_evp(s->session, &c, &hash, NULL, NULL, &comp, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_SETUP_KEY_BLOCK,
|
||||
SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->s3->tmp.new_sym_enc = c;
|
||||
s->s3->tmp.new_hash = hash;
|
||||
#ifdef OPENSSL_NO_COMP
|
||||
s->s3->tmp.new_compression = NULL;
|
||||
#else
|
||||
s->s3->tmp.new_compression = comp;
|
||||
#endif
|
||||
|
||||
num = EVP_MD_size(hash);
|
||||
if (num < 0)
|
||||
return 0;
|
||||
|
||||
num = EVP_CIPHER_key_length(c) + num + EVP_CIPHER_iv_length(c);
|
||||
num *= 2;
|
||||
|
||||
ssl3_cleanup_key_block(s);
|
||||
|
||||
if ((p = OPENSSL_malloc(num)) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_SETUP_KEY_BLOCK,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->s3->tmp.key_block_length = num;
|
||||
s->s3->tmp.key_block = p;
|
||||
|
||||
/* Calls SSLfatal() as required */
|
||||
ret = ssl3_generate_key_block(s, p, num);
|
||||
|
||||
if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) {
|
||||
/*
|
||||
* enable vulnerability countermeasure for CBC ciphers with known-IV
|
||||
* problem (http://www.openssl.org/~bodo/tls-cbc.txt)
|
||||
*/
|
||||
s->s3->need_empty_fragments = 1;
|
||||
|
||||
if (s->session->cipher != NULL) {
|
||||
if (s->session->cipher->algorithm_enc == SSL_eNULL)
|
||||
s->s3->need_empty_fragments = 0;
|
||||
|
||||
#ifndef OPENSSL_NO_RC4
|
||||
if (s->session->cipher->algorithm_enc == SSL_RC4)
|
||||
s->s3->need_empty_fragments = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ssl3_cleanup_key_block(SSL *s)
|
||||
{
|
||||
OPENSSL_clear_free(s->s3->tmp.key_block, s->s3->tmp.key_block_length);
|
||||
s->s3->tmp.key_block = NULL;
|
||||
s->s3->tmp.key_block_length = 0;
|
||||
}
|
||||
|
||||
int ssl3_init_finished_mac(SSL *s)
|
||||
{
|
||||
BIO *buf = BIO_new(BIO_s_mem());
|
||||
|
||||
if (buf == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_INIT_FINISHED_MAC,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
ssl3_free_digest_list(s);
|
||||
s->s3->handshake_buffer = buf;
|
||||
(void)BIO_set_close(s->s3->handshake_buffer, BIO_CLOSE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free digest list. Also frees handshake buffer since they are always freed
|
||||
* together.
|
||||
*/
|
||||
|
||||
void ssl3_free_digest_list(SSL *s)
|
||||
{
|
||||
BIO_free(s->s3->handshake_buffer);
|
||||
s->s3->handshake_buffer = NULL;
|
||||
EVP_MD_CTX_free(s->s3->handshake_dgst);
|
||||
s->s3->handshake_dgst = NULL;
|
||||
}
|
||||
|
||||
int ssl3_finish_mac(SSL *s, const unsigned char *buf, size_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (s->s3->handshake_dgst == NULL) {
|
||||
/* Note: this writes to a memory BIO so a failure is a fatal error */
|
||||
if (len > INT_MAX) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
|
||||
SSL_R_OVERFLOW_ERROR);
|
||||
return 0;
|
||||
}
|
||||
ret = BIO_write(s->s3->handshake_buffer, (void *)buf, (int)len);
|
||||
if (ret <= 0 || ret != (int)len) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ret = EVP_DigestUpdate(s->s3->handshake_dgst, buf, len);
|
||||
if (!ret) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ssl3_digest_cached_records(SSL *s, int keep)
|
||||
{
|
||||
const EVP_MD *md;
|
||||
long hdatalen;
|
||||
void *hdata;
|
||||
|
||||
if (s->s3->handshake_dgst == NULL) {
|
||||
hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
|
||||
if (hdatalen <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
|
||||
SSL_R_BAD_HANDSHAKE_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->s3->handshake_dgst = EVP_MD_CTX_new();
|
||||
if (s->s3->handshake_dgst == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
md = ssl_handshake_md(s);
|
||||
if (md == NULL || !EVP_DigestInit_ex(s->s3->handshake_dgst, md, NULL)
|
||||
|| !EVP_DigestUpdate(s->s3->handshake_dgst, hdata, hdatalen)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (keep == 0) {
|
||||
BIO_free(s->s3->handshake_buffer);
|
||||
s->s3->handshake_buffer = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t len,
|
||||
unsigned char *p)
|
||||
{
|
||||
int ret;
|
||||
EVP_MD_CTX *ctx = NULL;
|
||||
|
||||
if (!ssl3_digest_cached_records(s, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (EVP_MD_CTX_type(s->s3->handshake_dgst) != NID_md5_sha1) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
|
||||
SSL_R_NO_REQUIRED_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx = EVP_MD_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (!EVP_MD_CTX_copy_ex(ctx, s->s3->handshake_dgst)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = EVP_MD_CTX_size(ctx);
|
||||
if (ret < 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((sender != NULL && EVP_DigestUpdate(ctx, sender, len) <= 0)
|
||||
|| EVP_MD_CTX_ctrl(ctx, EVP_CTRL_SSL3_MASTER_SECRET,
|
||||
(int)s->session->master_key_length,
|
||||
s->session->master_key) <= 0
|
||||
|| EVP_DigestFinal_ex(ctx, p, NULL) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
err:
|
||||
EVP_MD_CTX_free(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
|
||||
size_t len, size_t *secret_size)
|
||||
{
|
||||
static const unsigned char *salt[3] = {
|
||||
#ifndef CHARSET_EBCDIC
|
||||
(const unsigned char *)"A",
|
||||
(const unsigned char *)"BB",
|
||||
(const unsigned char *)"CCC",
|
||||
#else
|
||||
(const unsigned char *)"\x41",
|
||||
(const unsigned char *)"\x42\x42",
|
||||
(const unsigned char *)"\x43\x43\x43",
|
||||
#endif
|
||||
};
|
||||
unsigned char buf[EVP_MAX_MD_SIZE];
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
int i, ret = 1;
|
||||
unsigned int n;
|
||||
size_t ret_secret_size = 0;
|
||||
|
||||
if (ctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_MASTER_SECRET,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (EVP_DigestInit_ex(ctx, s->ctx->sha1, NULL) <= 0
|
||||
|| EVP_DigestUpdate(ctx, salt[i],
|
||||
strlen((const char *)salt[i])) <= 0
|
||||
|| EVP_DigestUpdate(ctx, p, len) <= 0
|
||||
|| EVP_DigestUpdate(ctx, &(s->s3->client_random[0]),
|
||||
SSL3_RANDOM_SIZE) <= 0
|
||||
|| EVP_DigestUpdate(ctx, &(s->s3->server_random[0]),
|
||||
SSL3_RANDOM_SIZE) <= 0
|
||||
/* TODO(size_t) : convert me */
|
||||
|| EVP_DigestFinal_ex(ctx, buf, &n) <= 0
|
||||
|| EVP_DigestInit_ex(ctx, s->ctx->md5, NULL) <= 0
|
||||
|| EVP_DigestUpdate(ctx, p, len) <= 0
|
||||
|| EVP_DigestUpdate(ctx, buf, n) <= 0
|
||||
|| EVP_DigestFinal_ex(ctx, out, &n) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_SSL3_GENERATE_MASTER_SECRET, ERR_R_INTERNAL_ERROR);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
out += n;
|
||||
ret_secret_size += n;
|
||||
}
|
||||
EVP_MD_CTX_free(ctx);
|
||||
|
||||
OPENSSL_cleanse(buf, sizeof(buf));
|
||||
if (ret)
|
||||
*secret_size = ret_secret_size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssl3_alert_code(int code)
|
||||
{
|
||||
switch (code) {
|
||||
case SSL_AD_CLOSE_NOTIFY:
|
||||
return SSL3_AD_CLOSE_NOTIFY;
|
||||
case SSL_AD_UNEXPECTED_MESSAGE:
|
||||
return SSL3_AD_UNEXPECTED_MESSAGE;
|
||||
case SSL_AD_BAD_RECORD_MAC:
|
||||
return SSL3_AD_BAD_RECORD_MAC;
|
||||
case SSL_AD_DECRYPTION_FAILED:
|
||||
return SSL3_AD_BAD_RECORD_MAC;
|
||||
case SSL_AD_RECORD_OVERFLOW:
|
||||
return SSL3_AD_BAD_RECORD_MAC;
|
||||
case SSL_AD_DECOMPRESSION_FAILURE:
|
||||
return SSL3_AD_DECOMPRESSION_FAILURE;
|
||||
case SSL_AD_HANDSHAKE_FAILURE:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_NO_CERTIFICATE:
|
||||
return SSL3_AD_NO_CERTIFICATE;
|
||||
case SSL_AD_BAD_CERTIFICATE:
|
||||
return SSL3_AD_BAD_CERTIFICATE;
|
||||
case SSL_AD_UNSUPPORTED_CERTIFICATE:
|
||||
return SSL3_AD_UNSUPPORTED_CERTIFICATE;
|
||||
case SSL_AD_CERTIFICATE_REVOKED:
|
||||
return SSL3_AD_CERTIFICATE_REVOKED;
|
||||
case SSL_AD_CERTIFICATE_EXPIRED:
|
||||
return SSL3_AD_CERTIFICATE_EXPIRED;
|
||||
case SSL_AD_CERTIFICATE_UNKNOWN:
|
||||
return SSL3_AD_CERTIFICATE_UNKNOWN;
|
||||
case SSL_AD_ILLEGAL_PARAMETER:
|
||||
return SSL3_AD_ILLEGAL_PARAMETER;
|
||||
case SSL_AD_UNKNOWN_CA:
|
||||
return SSL3_AD_BAD_CERTIFICATE;
|
||||
case SSL_AD_ACCESS_DENIED:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_DECODE_ERROR:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_DECRYPT_ERROR:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_EXPORT_RESTRICTION:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_PROTOCOL_VERSION:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_INSUFFICIENT_SECURITY:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_INTERNAL_ERROR:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_USER_CANCELLED:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_NO_RENEGOTIATION:
|
||||
return -1; /* Don't send it :-) */
|
||||
case SSL_AD_UNSUPPORTED_EXTENSION:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_CERTIFICATE_UNOBTAINABLE:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_UNRECOGNIZED_NAME:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_BAD_CERTIFICATE_HASH_VALUE:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_UNKNOWN_PSK_IDENTITY:
|
||||
return TLS1_AD_UNKNOWN_PSK_IDENTITY;
|
||||
case SSL_AD_INAPPROPRIATE_FALLBACK:
|
||||
return TLS1_AD_INAPPROPRIATE_FALLBACK;
|
||||
case SSL_AD_NO_APPLICATION_PROTOCOL:
|
||||
return TLS1_AD_NO_APPLICATION_PROTOCOL;
|
||||
case SSL_AD_CERTIFICATE_REQUIRED:
|
||||
return SSL_AD_HANDSHAKE_FAILURE;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
4864
trunk/3rdparty/openssl-1.1-fit/ssl/s3_lib.c
vendored
Normal file
4864
trunk/3rdparty/openssl-1.1-fit/ssl/s3_lib.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
104
trunk/3rdparty/openssl-1.1-fit/ssl/s3_msg.c
vendored
Normal file
104
trunk/3rdparty/openssl-1.1-fit/ssl/s3_msg.c
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "ssl_locl.h"
|
||||
|
||||
int ssl3_do_change_cipher_spec(SSL *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (s->server)
|
||||
i = SSL3_CHANGE_CIPHER_SERVER_READ;
|
||||
else
|
||||
i = SSL3_CHANGE_CIPHER_CLIENT_READ;
|
||||
|
||||
if (s->s3->tmp.key_block == NULL) {
|
||||
if (s->session == NULL || s->session->master_key_length == 0) {
|
||||
/* might happen if dtls1_read_bytes() calls this */
|
||||
SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->session->cipher = s->s3->tmp.new_cipher;
|
||||
if (!s->method->ssl3_enc->setup_key_block(s))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s->method->ssl3_enc->change_cipher_state(s, i))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ssl3_send_alert(SSL *s, int level, int desc)
|
||||
{
|
||||
/* Map tls/ssl alert value to correct one */
|
||||
if (SSL_TREAT_AS_TLS13(s))
|
||||
desc = tls13_alert_code(desc);
|
||||
else
|
||||
desc = s->method->ssl3_enc->alert_value(desc);
|
||||
if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION)
|
||||
desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have
|
||||
* protocol_version alerts */
|
||||
if (desc < 0)
|
||||
return -1;
|
||||
/* If a fatal one, remove from cache */
|
||||
if ((level == SSL3_AL_FATAL) && (s->session != NULL))
|
||||
SSL_CTX_remove_session(s->session_ctx, s->session);
|
||||
|
||||
s->s3->alert_dispatch = 1;
|
||||
s->s3->send_alert[0] = level;
|
||||
s->s3->send_alert[1] = desc;
|
||||
if (!RECORD_LAYER_write_pending(&s->rlayer)) {
|
||||
/* data still being written out? */
|
||||
return s->method->ssl_dispatch_alert(s);
|
||||
}
|
||||
/*
|
||||
* else data is still being written out, we will get written some time in
|
||||
* the future
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ssl3_dispatch_alert(SSL *s)
|
||||
{
|
||||
int i, j;
|
||||
size_t alertlen;
|
||||
void (*cb) (const SSL *ssl, int type, int val) = NULL;
|
||||
size_t written;
|
||||
|
||||
s->s3->alert_dispatch = 0;
|
||||
alertlen = 2;
|
||||
i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], &alertlen, 1, 0,
|
||||
&written);
|
||||
if (i <= 0) {
|
||||
s->s3->alert_dispatch = 1;
|
||||
} else {
|
||||
/*
|
||||
* Alert sent to BIO - now flush. If the message does not get sent due
|
||||
* to non-blocking IO, we will not worry too much.
|
||||
*/
|
||||
(void)BIO_flush(s->wbio);
|
||||
|
||||
if (s->msg_callback)
|
||||
s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,
|
||||
2, s, s->msg_callback_arg);
|
||||
|
||||
if (s->info_callback != NULL)
|
||||
cb = s->info_callback;
|
||||
else if (s->ctx->info_callback != NULL)
|
||||
cb = s->ctx->info_callback;
|
||||
|
||||
if (cb != NULL) {
|
||||
j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
|
||||
cb(s, SSL_CB_WRITE_ALERT, j);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
393
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_asn1.c
vendored
Normal file
393
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_asn1.c
vendored
Normal file
|
@ -0,0 +1,393 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2005 Nokia. All rights reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "ssl_locl.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t version;
|
||||
int32_t ssl_version;
|
||||
ASN1_OCTET_STRING *cipher;
|
||||
ASN1_OCTET_STRING *comp_id;
|
||||
ASN1_OCTET_STRING *master_key;
|
||||
ASN1_OCTET_STRING *session_id;
|
||||
ASN1_OCTET_STRING *key_arg;
|
||||
int64_t time;
|
||||
int64_t timeout;
|
||||
X509 *peer;
|
||||
ASN1_OCTET_STRING *session_id_context;
|
||||
int32_t verify_result;
|
||||
ASN1_OCTET_STRING *tlsext_hostname;
|
||||
uint64_t tlsext_tick_lifetime_hint;
|
||||
uint32_t tlsext_tick_age_add;
|
||||
ASN1_OCTET_STRING *tlsext_tick;
|
||||
#ifndef OPENSSL_NO_PSK
|
||||
ASN1_OCTET_STRING *psk_identity_hint;
|
||||
ASN1_OCTET_STRING *psk_identity;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
ASN1_OCTET_STRING *srp_username;
|
||||
#endif
|
||||
uint64_t flags;
|
||||
uint32_t max_early_data;
|
||||
ASN1_OCTET_STRING *alpn_selected;
|
||||
uint32_t tlsext_max_fragment_len_mode;
|
||||
ASN1_OCTET_STRING *ticket_appdata;
|
||||
} SSL_SESSION_ASN1;
|
||||
|
||||
ASN1_SEQUENCE(SSL_SESSION_ASN1) = {
|
||||
ASN1_EMBED(SSL_SESSION_ASN1, version, UINT32),
|
||||
ASN1_EMBED(SSL_SESSION_ASN1, ssl_version, INT32),
|
||||
ASN1_SIMPLE(SSL_SESSION_ASN1, cipher, ASN1_OCTET_STRING),
|
||||
ASN1_SIMPLE(SSL_SESSION_ASN1, session_id, ASN1_OCTET_STRING),
|
||||
ASN1_SIMPLE(SSL_SESSION_ASN1, master_key, ASN1_OCTET_STRING),
|
||||
ASN1_IMP_OPT(SSL_SESSION_ASN1, key_arg, ASN1_OCTET_STRING, 0),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, time, ZINT64, 1),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, timeout, ZINT64, 2),
|
||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, peer, X509, 3),
|
||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, session_id_context, ASN1_OCTET_STRING, 4),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, verify_result, ZINT32, 5),
|
||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, tlsext_hostname, ASN1_OCTET_STRING, 6),
|
||||
#ifndef OPENSSL_NO_PSK
|
||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, psk_identity_hint, ASN1_OCTET_STRING, 7),
|
||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, psk_identity, ASN1_OCTET_STRING, 8),
|
||||
#endif
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_tick_lifetime_hint, ZUINT64, 9),
|
||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, tlsext_tick, ASN1_OCTET_STRING, 10),
|
||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, comp_id, ASN1_OCTET_STRING, 11),
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, srp_username, ASN1_OCTET_STRING, 12),
|
||||
#endif
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, flags, ZUINT64, 13),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_tick_age_add, ZUINT32, 14),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, max_early_data, ZUINT32, 15),
|
||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, alpn_selected, ASN1_OCTET_STRING, 16),
|
||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_max_fragment_len_mode, ZUINT32, 17),
|
||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, ticket_appdata, ASN1_OCTET_STRING, 18)
|
||||
} static_ASN1_SEQUENCE_END(SSL_SESSION_ASN1)
|
||||
|
||||
IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(SSL_SESSION_ASN1)
|
||||
|
||||
/* Utility functions for i2d_SSL_SESSION */
|
||||
|
||||
/* Initialise OCTET STRING from buffer and length */
|
||||
|
||||
static void ssl_session_oinit(ASN1_OCTET_STRING **dest, ASN1_OCTET_STRING *os,
|
||||
unsigned char *data, size_t len)
|
||||
{
|
||||
os->data = data;
|
||||
os->length = (int)len;
|
||||
os->flags = 0;
|
||||
*dest = os;
|
||||
}
|
||||
|
||||
/* Initialise OCTET STRING from string */
|
||||
static void ssl_session_sinit(ASN1_OCTET_STRING **dest, ASN1_OCTET_STRING *os,
|
||||
char *data)
|
||||
{
|
||||
if (data != NULL)
|
||||
ssl_session_oinit(dest, os, (unsigned char *)data, strlen(data));
|
||||
else
|
||||
*dest = NULL;
|
||||
}
|
||||
|
||||
int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
|
||||
{
|
||||
|
||||
SSL_SESSION_ASN1 as;
|
||||
|
||||
ASN1_OCTET_STRING cipher;
|
||||
unsigned char cipher_data[2];
|
||||
ASN1_OCTET_STRING master_key, session_id, sid_ctx;
|
||||
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
ASN1_OCTET_STRING comp_id;
|
||||
unsigned char comp_id_data;
|
||||
#endif
|
||||
ASN1_OCTET_STRING tlsext_hostname, tlsext_tick;
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
ASN1_OCTET_STRING srp_username;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_PSK
|
||||
ASN1_OCTET_STRING psk_identity, psk_identity_hint;
|
||||
#endif
|
||||
ASN1_OCTET_STRING alpn_selected;
|
||||
ASN1_OCTET_STRING ticket_appdata;
|
||||
|
||||
long l;
|
||||
|
||||
if ((in == NULL) || ((in->cipher == NULL) && (in->cipher_id == 0)))
|
||||
return 0;
|
||||
|
||||
memset(&as, 0, sizeof(as));
|
||||
|
||||
as.version = SSL_SESSION_ASN1_VERSION;
|
||||
as.ssl_version = in->ssl_version;
|
||||
|
||||
if (in->cipher == NULL)
|
||||
l = in->cipher_id;
|
||||
else
|
||||
l = in->cipher->id;
|
||||
cipher_data[0] = ((unsigned char)(l >> 8L)) & 0xff;
|
||||
cipher_data[1] = ((unsigned char)(l)) & 0xff;
|
||||
|
||||
ssl_session_oinit(&as.cipher, &cipher, cipher_data, 2);
|
||||
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
if (in->compress_meth) {
|
||||
comp_id_data = (unsigned char)in->compress_meth;
|
||||
ssl_session_oinit(&as.comp_id, &comp_id, &comp_id_data, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
ssl_session_oinit(&as.master_key, &master_key,
|
||||
in->master_key, in->master_key_length);
|
||||
|
||||
ssl_session_oinit(&as.session_id, &session_id,
|
||||
in->session_id, in->session_id_length);
|
||||
|
||||
ssl_session_oinit(&as.session_id_context, &sid_ctx,
|
||||
in->sid_ctx, in->sid_ctx_length);
|
||||
|
||||
as.time = in->time;
|
||||
as.timeout = in->timeout;
|
||||
as.verify_result = in->verify_result;
|
||||
|
||||
as.peer = in->peer;
|
||||
|
||||
ssl_session_sinit(&as.tlsext_hostname, &tlsext_hostname,
|
||||
in->ext.hostname);
|
||||
if (in->ext.tick) {
|
||||
ssl_session_oinit(&as.tlsext_tick, &tlsext_tick,
|
||||
in->ext.tick, in->ext.ticklen);
|
||||
}
|
||||
if (in->ext.tick_lifetime_hint > 0)
|
||||
as.tlsext_tick_lifetime_hint = in->ext.tick_lifetime_hint;
|
||||
as.tlsext_tick_age_add = in->ext.tick_age_add;
|
||||
#ifndef OPENSSL_NO_PSK
|
||||
ssl_session_sinit(&as.psk_identity_hint, &psk_identity_hint,
|
||||
in->psk_identity_hint);
|
||||
ssl_session_sinit(&as.psk_identity, &psk_identity, in->psk_identity);
|
||||
#endif /* OPENSSL_NO_PSK */
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
ssl_session_sinit(&as.srp_username, &srp_username, in->srp_username);
|
||||
#endif /* OPENSSL_NO_SRP */
|
||||
|
||||
as.flags = in->flags;
|
||||
as.max_early_data = in->ext.max_early_data;
|
||||
|
||||
if (in->ext.alpn_selected == NULL)
|
||||
as.alpn_selected = NULL;
|
||||
else
|
||||
ssl_session_oinit(&as.alpn_selected, &alpn_selected,
|
||||
in->ext.alpn_selected, in->ext.alpn_selected_len);
|
||||
|
||||
as.tlsext_max_fragment_len_mode = in->ext.max_fragment_len_mode;
|
||||
|
||||
if (in->ticket_appdata == NULL)
|
||||
as.ticket_appdata = NULL;
|
||||
else
|
||||
ssl_session_oinit(&as.ticket_appdata, &ticket_appdata,
|
||||
in->ticket_appdata, in->ticket_appdata_len);
|
||||
|
||||
return i2d_SSL_SESSION_ASN1(&as, pp);
|
||||
|
||||
}
|
||||
|
||||
/* Utility functions for d2i_SSL_SESSION */
|
||||
|
||||
/* OPENSSL_strndup an OCTET STRING */
|
||||
|
||||
static int ssl_session_strndup(char **pdst, ASN1_OCTET_STRING *src)
|
||||
{
|
||||
OPENSSL_free(*pdst);
|
||||
*pdst = NULL;
|
||||
if (src == NULL)
|
||||
return 1;
|
||||
*pdst = OPENSSL_strndup((char *)src->data, src->length);
|
||||
if (*pdst == NULL)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy an OCTET STRING, return error if it exceeds maximum length */
|
||||
|
||||
static int ssl_session_memcpy(unsigned char *dst, size_t *pdstlen,
|
||||
ASN1_OCTET_STRING *src, size_t maxlen)
|
||||
{
|
||||
if (src == NULL) {
|
||||
*pdstlen = 0;
|
||||
return 1;
|
||||
}
|
||||
if (src->length < 0 || src->length > (int)maxlen)
|
||||
return 0;
|
||||
memcpy(dst, src->data, src->length);
|
||||
*pdstlen = src->length;
|
||||
return 1;
|
||||
}
|
||||
|
||||
SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
|
||||
long length)
|
||||
{
|
||||
long id;
|
||||
size_t tmpl;
|
||||
const unsigned char *p = *pp;
|
||||
SSL_SESSION_ASN1 *as = NULL;
|
||||
SSL_SESSION *ret = NULL;
|
||||
|
||||
as = d2i_SSL_SESSION_ASN1(NULL, &p, length);
|
||||
/* ASN.1 code returns suitable error */
|
||||
if (as == NULL)
|
||||
goto err;
|
||||
|
||||
if (!a || !*a) {
|
||||
ret = SSL_SESSION_new();
|
||||
if (ret == NULL)
|
||||
goto err;
|
||||
} else {
|
||||
ret = *a;
|
||||
}
|
||||
|
||||
if (as->version != SSL_SESSION_ASN1_VERSION) {
|
||||
SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_UNKNOWN_SSL_VERSION);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((as->ssl_version >> 8) != SSL3_VERSION_MAJOR
|
||||
&& (as->ssl_version >> 8) != DTLS1_VERSION_MAJOR
|
||||
&& as->ssl_version != DTLS1_BAD_VER) {
|
||||
SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_UNSUPPORTED_SSL_VERSION);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret->ssl_version = (int)as->ssl_version;
|
||||
|
||||
if (as->cipher->length != 2) {
|
||||
SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_CIPHER_CODE_WRONG_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
id = 0x03000000L | ((unsigned long)as->cipher->data[0] << 8L)
|
||||
| (unsigned long)as->cipher->data[1];
|
||||
|
||||
ret->cipher_id = id;
|
||||
ret->cipher = ssl3_get_cipher_by_id(id);
|
||||
if (ret->cipher == NULL)
|
||||
goto err;
|
||||
|
||||
if (!ssl_session_memcpy(ret->session_id, &ret->session_id_length,
|
||||
as->session_id, SSL3_MAX_SSL_SESSION_ID_LENGTH))
|
||||
goto err;
|
||||
|
||||
if (!ssl_session_memcpy(ret->master_key, &tmpl,
|
||||
as->master_key, TLS13_MAX_RESUMPTION_PSK_LENGTH))
|
||||
goto err;
|
||||
|
||||
ret->master_key_length = tmpl;
|
||||
|
||||
if (as->time != 0)
|
||||
ret->time = (long)as->time;
|
||||
else
|
||||
ret->time = (long)time(NULL);
|
||||
|
||||
if (as->timeout != 0)
|
||||
ret->timeout = (long)as->timeout;
|
||||
else
|
||||
ret->timeout = 3;
|
||||
|
||||
X509_free(ret->peer);
|
||||
ret->peer = as->peer;
|
||||
as->peer = NULL;
|
||||
|
||||
if (!ssl_session_memcpy(ret->sid_ctx, &ret->sid_ctx_length,
|
||||
as->session_id_context, SSL_MAX_SID_CTX_LENGTH))
|
||||
goto err;
|
||||
|
||||
/* NB: this defaults to zero which is X509_V_OK */
|
||||
ret->verify_result = as->verify_result;
|
||||
|
||||
if (!ssl_session_strndup(&ret->ext.hostname, as->tlsext_hostname))
|
||||
goto err;
|
||||
|
||||
#ifndef OPENSSL_NO_PSK
|
||||
if (!ssl_session_strndup(&ret->psk_identity_hint, as->psk_identity_hint))
|
||||
goto err;
|
||||
if (!ssl_session_strndup(&ret->psk_identity, as->psk_identity))
|
||||
goto err;
|
||||
#endif
|
||||
|
||||
ret->ext.tick_lifetime_hint = (unsigned long)as->tlsext_tick_lifetime_hint;
|
||||
ret->ext.tick_age_add = as->tlsext_tick_age_add;
|
||||
OPENSSL_free(ret->ext.tick);
|
||||
if (as->tlsext_tick != NULL) {
|
||||
ret->ext.tick = as->tlsext_tick->data;
|
||||
ret->ext.ticklen = as->tlsext_tick->length;
|
||||
as->tlsext_tick->data = NULL;
|
||||
} else {
|
||||
ret->ext.tick = NULL;
|
||||
}
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
if (as->comp_id) {
|
||||
if (as->comp_id->length != 1) {
|
||||
SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_BAD_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
ret->compress_meth = as->comp_id->data[0];
|
||||
} else {
|
||||
ret->compress_meth = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
if (!ssl_session_strndup(&ret->srp_username, as->srp_username))
|
||||
goto err;
|
||||
#endif /* OPENSSL_NO_SRP */
|
||||
/* Flags defaults to zero which is fine */
|
||||
ret->flags = (int32_t)as->flags;
|
||||
ret->ext.max_early_data = as->max_early_data;
|
||||
|
||||
OPENSSL_free(ret->ext.alpn_selected);
|
||||
if (as->alpn_selected != NULL) {
|
||||
ret->ext.alpn_selected = as->alpn_selected->data;
|
||||
ret->ext.alpn_selected_len = as->alpn_selected->length;
|
||||
as->alpn_selected->data = NULL;
|
||||
} else {
|
||||
ret->ext.alpn_selected = NULL;
|
||||
ret->ext.alpn_selected_len = 0;
|
||||
}
|
||||
|
||||
ret->ext.max_fragment_len_mode = as->tlsext_max_fragment_len_mode;
|
||||
|
||||
OPENSSL_free(ret->ticket_appdata);
|
||||
if (as->ticket_appdata != NULL) {
|
||||
ret->ticket_appdata = as->ticket_appdata->data;
|
||||
ret->ticket_appdata_len = as->ticket_appdata->length;
|
||||
as->ticket_appdata->data = NULL;
|
||||
} else {
|
||||
ret->ticket_appdata = NULL;
|
||||
ret->ticket_appdata_len = 0;
|
||||
}
|
||||
|
||||
M_ASN1_free_of(as, SSL_SESSION_ASN1);
|
||||
|
||||
if ((a != NULL) && (*a == NULL))
|
||||
*a = ret;
|
||||
*pp = p;
|
||||
return ret;
|
||||
|
||||
err:
|
||||
M_ASN1_free_of(as, SSL_SESSION_ASN1);
|
||||
if ((a == NULL) || (*a != ret))
|
||||
SSL_SESSION_free(ret);
|
||||
return NULL;
|
||||
}
|
1040
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_cert.c
vendored
Normal file
1040
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_cert.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
23
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_cert_table.h
vendored
Normal file
23
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_cert_table.h
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* Certificate table information. NB: table entries must match SSL_PKEY indices
|
||||
*/
|
||||
static const SSL_CERT_LOOKUP ssl_cert_info [] = {
|
||||
{EVP_PKEY_RSA, SSL_aRSA}, /* SSL_PKEY_RSA */
|
||||
{EVP_PKEY_RSA_PSS, SSL_aRSA}, /* SSL_PKEY_RSA_PSS_SIGN */
|
||||
{EVP_PKEY_DSA, SSL_aDSS}, /* SSL_PKEY_DSA_SIGN */
|
||||
{EVP_PKEY_EC, SSL_aECDSA}, /* SSL_PKEY_ECC */
|
||||
{NID_id_GostR3410_2001, SSL_aGOST01}, /* SSL_PKEY_GOST01 */
|
||||
{NID_id_GostR3410_2012_256, SSL_aGOST12}, /* SSL_PKEY_GOST12_256 */
|
||||
{NID_id_GostR3410_2012_512, SSL_aGOST12}, /* SSL_PKEY_GOST12_512 */
|
||||
{EVP_PKEY_ED25519, SSL_aECDSA}, /* SSL_PKEY_ED25519 */
|
||||
{EVP_PKEY_ED448, SSL_aECDSA} /* SSL_PKEY_ED448 */
|
||||
};
|
2163
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_ciph.c
vendored
Normal file
2163
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_ciph.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
993
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_conf.c
vendored
Normal file
993
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_conf.c
vendored
Normal file
|
@ -0,0 +1,993 @@
|
|||
/*
|
||||
* Copyright 2012-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "ssl_locl.h"
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/dh.h>
|
||||
#include "internal/nelem.h"
|
||||
|
||||
/*
|
||||
* structure holding name tables. This is used for permitted elements in lists
|
||||
* such as TLSv1.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int namelen;
|
||||
unsigned int name_flags;
|
||||
unsigned long option_value;
|
||||
} ssl_flag_tbl;
|
||||
|
||||
/* Switch table: use for single command line switches like no_tls2 */
|
||||
typedef struct {
|
||||
unsigned long option_value;
|
||||
unsigned int name_flags;
|
||||
} ssl_switch_tbl;
|
||||
|
||||
/* Sense of name is inverted e.g. "TLSv1" will clear SSL_OP_NO_TLSv1 */
|
||||
#define SSL_TFLAG_INV 0x1
|
||||
/* Mask for type of flag referred to */
|
||||
#define SSL_TFLAG_TYPE_MASK 0xf00
|
||||
/* Flag is for options */
|
||||
#define SSL_TFLAG_OPTION 0x000
|
||||
/* Flag is for cert_flags */
|
||||
#define SSL_TFLAG_CERT 0x100
|
||||
/* Flag is for verify mode */
|
||||
#define SSL_TFLAG_VFY 0x200
|
||||
/* Option can only be used for clients */
|
||||
#define SSL_TFLAG_CLIENT SSL_CONF_FLAG_CLIENT
|
||||
/* Option can only be used for servers */
|
||||
#define SSL_TFLAG_SERVER SSL_CONF_FLAG_SERVER
|
||||
#define SSL_TFLAG_BOTH (SSL_TFLAG_CLIENT|SSL_TFLAG_SERVER)
|
||||
|
||||
#define SSL_FLAG_TBL(str, flag) \
|
||||
{str, (int)(sizeof(str) - 1), SSL_TFLAG_BOTH, flag}
|
||||
#define SSL_FLAG_TBL_SRV(str, flag) \
|
||||
{str, (int)(sizeof(str) - 1), SSL_TFLAG_SERVER, flag}
|
||||
#define SSL_FLAG_TBL_CLI(str, flag) \
|
||||
{str, (int)(sizeof(str) - 1), SSL_TFLAG_CLIENT, flag}
|
||||
#define SSL_FLAG_TBL_INV(str, flag) \
|
||||
{str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_BOTH, flag}
|
||||
#define SSL_FLAG_TBL_SRV_INV(str, flag) \
|
||||
{str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_SERVER, flag}
|
||||
#define SSL_FLAG_TBL_CERT(str, flag) \
|
||||
{str, (int)(sizeof(str) - 1), SSL_TFLAG_CERT|SSL_TFLAG_BOTH, flag}
|
||||
|
||||
#define SSL_FLAG_VFY_CLI(str, flag) \
|
||||
{str, (int)(sizeof(str) - 1), SSL_TFLAG_VFY | SSL_TFLAG_CLIENT, flag}
|
||||
#define SSL_FLAG_VFY_SRV(str, flag) \
|
||||
{str, (int)(sizeof(str) - 1), SSL_TFLAG_VFY | SSL_TFLAG_SERVER, flag}
|
||||
|
||||
/*
|
||||
* Opaque structure containing SSL configuration context.
|
||||
*/
|
||||
|
||||
struct ssl_conf_ctx_st {
|
||||
/*
|
||||
* Various flags indicating (among other things) which options we will
|
||||
* recognise.
|
||||
*/
|
||||
unsigned int flags;
|
||||
/* Prefix and length of commands */
|
||||
char *prefix;
|
||||
size_t prefixlen;
|
||||
/* SSL_CTX or SSL structure to perform operations on */
|
||||
SSL_CTX *ctx;
|
||||
SSL *ssl;
|
||||
/* Pointer to SSL or SSL_CTX options field or NULL if none */
|
||||
uint32_t *poptions;
|
||||
/* Certificate filenames for each type */
|
||||
char *cert_filename[SSL_PKEY_NUM];
|
||||
/* Pointer to SSL or SSL_CTX cert_flags or NULL if none */
|
||||
uint32_t *pcert_flags;
|
||||
/* Pointer to SSL or SSL_CTX verify_mode or NULL if none */
|
||||
uint32_t *pvfy_flags;
|
||||
/* Pointer to SSL or SSL_CTX min_version field or NULL if none */
|
||||
int *min_version;
|
||||
/* Pointer to SSL or SSL_CTX max_version field or NULL if none */
|
||||
int *max_version;
|
||||
/* Current flag table being worked on */
|
||||
const ssl_flag_tbl *tbl;
|
||||
/* Size of table */
|
||||
size_t ntbl;
|
||||
/* Client CA names */
|
||||
STACK_OF(X509_NAME) *canames;
|
||||
};
|
||||
|
||||
static void ssl_set_option(SSL_CONF_CTX *cctx, unsigned int name_flags,
|
||||
unsigned long option_value, int onoff)
|
||||
{
|
||||
uint32_t *pflags;
|
||||
if (cctx->poptions == NULL)
|
||||
return;
|
||||
if (name_flags & SSL_TFLAG_INV)
|
||||
onoff ^= 1;
|
||||
switch (name_flags & SSL_TFLAG_TYPE_MASK) {
|
||||
|
||||
case SSL_TFLAG_CERT:
|
||||
pflags = cctx->pcert_flags;
|
||||
break;
|
||||
|
||||
case SSL_TFLAG_VFY:
|
||||
pflags = cctx->pvfy_flags;
|
||||
break;
|
||||
|
||||
case SSL_TFLAG_OPTION:
|
||||
pflags = cctx->poptions;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
|
||||
}
|
||||
if (onoff)
|
||||
*pflags |= option_value;
|
||||
else
|
||||
*pflags &= ~option_value;
|
||||
}
|
||||
|
||||
static int ssl_match_option(SSL_CONF_CTX *cctx, const ssl_flag_tbl *tbl,
|
||||
const char *name, int namelen, int onoff)
|
||||
{
|
||||
/* If name not relevant for context skip */
|
||||
if (!(cctx->flags & tbl->name_flags & SSL_TFLAG_BOTH))
|
||||
return 0;
|
||||
if (namelen == -1) {
|
||||
if (strcmp(tbl->name, name))
|
||||
return 0;
|
||||
} else if (tbl->namelen != namelen || strncasecmp(tbl->name, name, namelen))
|
||||
return 0;
|
||||
ssl_set_option(cctx, tbl->name_flags, tbl->option_value, onoff);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ssl_set_option_list(const char *elem, int len, void *usr)
|
||||
{
|
||||
SSL_CONF_CTX *cctx = usr;
|
||||
size_t i;
|
||||
const ssl_flag_tbl *tbl;
|
||||
int onoff = 1;
|
||||
/*
|
||||
* len == -1 indicates not being called in list context, just for single
|
||||
* command line switches, so don't allow +, -.
|
||||
*/
|
||||
if (elem == NULL)
|
||||
return 0;
|
||||
if (len != -1) {
|
||||
if (*elem == '+') {
|
||||
elem++;
|
||||
len--;
|
||||
onoff = 1;
|
||||
} else if (*elem == '-') {
|
||||
elem++;
|
||||
len--;
|
||||
onoff = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0, tbl = cctx->tbl; i < cctx->ntbl; i++, tbl++) {
|
||||
if (ssl_match_option(cctx, tbl, elem, len, onoff))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set supported signature algorithms */
|
||||
static int cmd_SignatureAlgorithms(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
int rv;
|
||||
if (cctx->ssl)
|
||||
rv = SSL_set1_sigalgs_list(cctx->ssl, value);
|
||||
/* NB: ctx == NULL performs syntax checking only */
|
||||
else
|
||||
rv = SSL_CTX_set1_sigalgs_list(cctx->ctx, value);
|
||||
return rv > 0;
|
||||
}
|
||||
|
||||
/* Set supported client signature algorithms */
|
||||
static int cmd_ClientSignatureAlgorithms(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
int rv;
|
||||
if (cctx->ssl)
|
||||
rv = SSL_set1_client_sigalgs_list(cctx->ssl, value);
|
||||
/* NB: ctx == NULL performs syntax checking only */
|
||||
else
|
||||
rv = SSL_CTX_set1_client_sigalgs_list(cctx->ctx, value);
|
||||
return rv > 0;
|
||||
}
|
||||
|
||||
static int cmd_Groups(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
int rv;
|
||||
if (cctx->ssl)
|
||||
rv = SSL_set1_groups_list(cctx->ssl, value);
|
||||
/* NB: ctx == NULL performs syntax checking only */
|
||||
else
|
||||
rv = SSL_CTX_set1_groups_list(cctx->ctx, value);
|
||||
return rv > 0;
|
||||
}
|
||||
|
||||
/* This is the old name for cmd_Groups - retained for backwards compatibility */
|
||||
static int cmd_Curves(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
return cmd_Groups(cctx, value);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
/* ECDH temporary parameters */
|
||||
static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
int rv = 1;
|
||||
EC_KEY *ecdh;
|
||||
int nid;
|
||||
|
||||
/* Ignore values supported by 1.0.2 for the automatic selection */
|
||||
if ((cctx->flags & SSL_CONF_FLAG_FILE)
|
||||
&& (strcasecmp(value, "+automatic") == 0
|
||||
|| strcasecmp(value, "automatic") == 0))
|
||||
return 1;
|
||||
if ((cctx->flags & SSL_CONF_FLAG_CMDLINE) &&
|
||||
strcmp(value, "auto") == 0)
|
||||
return 1;
|
||||
|
||||
nid = EC_curve_nist2nid(value);
|
||||
if (nid == NID_undef)
|
||||
nid = OBJ_sn2nid(value);
|
||||
if (nid == 0)
|
||||
return 0;
|
||||
ecdh = EC_KEY_new_by_curve_name(nid);
|
||||
if (!ecdh)
|
||||
return 0;
|
||||
if (cctx->ctx)
|
||||
rv = SSL_CTX_set_tmp_ecdh(cctx->ctx, ecdh);
|
||||
else if (cctx->ssl)
|
||||
rv = SSL_set_tmp_ecdh(cctx->ssl, ecdh);
|
||||
EC_KEY_free(ecdh);
|
||||
|
||||
return rv > 0;
|
||||
}
|
||||
#endif
|
||||
static int cmd_CipherString(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
int rv = 1;
|
||||
|
||||
if (cctx->ctx)
|
||||
rv = SSL_CTX_set_cipher_list(cctx->ctx, value);
|
||||
if (cctx->ssl)
|
||||
rv = SSL_set_cipher_list(cctx->ssl, value);
|
||||
return rv > 0;
|
||||
}
|
||||
|
||||
static int cmd_Ciphersuites(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
int rv = 1;
|
||||
|
||||
if (cctx->ctx)
|
||||
rv = SSL_CTX_set_ciphersuites(cctx->ctx, value);
|
||||
if (cctx->ssl)
|
||||
rv = SSL_set_ciphersuites(cctx->ssl, value);
|
||||
return rv > 0;
|
||||
}
|
||||
|
||||
static int cmd_Protocol(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
static const ssl_flag_tbl ssl_protocol_list[] = {
|
||||
SSL_FLAG_TBL_INV("ALL", SSL_OP_NO_SSL_MASK),
|
||||
SSL_FLAG_TBL_INV("SSLv2", SSL_OP_NO_SSLv2),
|
||||
SSL_FLAG_TBL_INV("SSLv3", SSL_OP_NO_SSLv3),
|
||||
SSL_FLAG_TBL_INV("TLSv1", SSL_OP_NO_TLSv1),
|
||||
SSL_FLAG_TBL_INV("TLSv1.1", SSL_OP_NO_TLSv1_1),
|
||||
SSL_FLAG_TBL_INV("TLSv1.2", SSL_OP_NO_TLSv1_2),
|
||||
SSL_FLAG_TBL_INV("TLSv1.3", SSL_OP_NO_TLSv1_3),
|
||||
SSL_FLAG_TBL_INV("DTLSv1", SSL_OP_NO_DTLSv1),
|
||||
SSL_FLAG_TBL_INV("DTLSv1.2", SSL_OP_NO_DTLSv1_2)
|
||||
};
|
||||
cctx->tbl = ssl_protocol_list;
|
||||
cctx->ntbl = OSSL_NELEM(ssl_protocol_list);
|
||||
return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* protocol_from_string - converts a protocol version string to a number
|
||||
*
|
||||
* Returns -1 on failure or the version on success
|
||||
*/
|
||||
static int protocol_from_string(const char *value)
|
||||
{
|
||||
struct protocol_versions {
|
||||
const char *name;
|
||||
int version;
|
||||
};
|
||||
static const struct protocol_versions versions[] = {
|
||||
{"None", 0},
|
||||
{"SSLv3", SSL3_VERSION},
|
||||
{"TLSv1", TLS1_VERSION},
|
||||
{"TLSv1.1", TLS1_1_VERSION},
|
||||
{"TLSv1.2", TLS1_2_VERSION},
|
||||
{"TLSv1.3", TLS1_3_VERSION},
|
||||
{"DTLSv1", DTLS1_VERSION},
|
||||
{"DTLSv1.2", DTLS1_2_VERSION}
|
||||
};
|
||||
size_t i;
|
||||
size_t n = OSSL_NELEM(versions);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
if (strcmp(versions[i].name, value) == 0)
|
||||
return versions[i].version;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int min_max_proto(SSL_CONF_CTX *cctx, const char *value, int *bound)
|
||||
{
|
||||
int method_version;
|
||||
int new_version;
|
||||
|
||||
if (cctx->ctx != NULL)
|
||||
method_version = cctx->ctx->method->version;
|
||||
else if (cctx->ssl != NULL)
|
||||
method_version = cctx->ssl->ctx->method->version;
|
||||
else
|
||||
return 0;
|
||||
if ((new_version = protocol_from_string(value)) < 0)
|
||||
return 0;
|
||||
return ssl_set_version_bound(method_version, new_version, bound);
|
||||
}
|
||||
|
||||
/*
|
||||
* cmd_MinProtocol - Set min protocol version
|
||||
* @cctx: config structure to save settings in
|
||||
* @value: The min protocol version in string form
|
||||
*
|
||||
* Returns 1 on success and 0 on failure.
|
||||
*/
|
||||
static int cmd_MinProtocol(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
return min_max_proto(cctx, value, cctx->min_version);
|
||||
}
|
||||
|
||||
/*
|
||||
* cmd_MaxProtocol - Set max protocol version
|
||||
* @cctx: config structure to save settings in
|
||||
* @value: The max protocol version in string form
|
||||
*
|
||||
* Returns 1 on success and 0 on failure.
|
||||
*/
|
||||
static int cmd_MaxProtocol(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
return min_max_proto(cctx, value, cctx->max_version);
|
||||
}
|
||||
|
||||
static int cmd_Options(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
static const ssl_flag_tbl ssl_option_list[] = {
|
||||
SSL_FLAG_TBL_INV("SessionTicket", SSL_OP_NO_TICKET),
|
||||
SSL_FLAG_TBL_INV("EmptyFragments",
|
||||
SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS),
|
||||
SSL_FLAG_TBL("Bugs", SSL_OP_ALL),
|
||||
SSL_FLAG_TBL_INV("Compression", SSL_OP_NO_COMPRESSION),
|
||||
SSL_FLAG_TBL_SRV("ServerPreference", SSL_OP_CIPHER_SERVER_PREFERENCE),
|
||||
SSL_FLAG_TBL_SRV("NoResumptionOnRenegotiation",
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION),
|
||||
SSL_FLAG_TBL_SRV("DHSingle", SSL_OP_SINGLE_DH_USE),
|
||||
SSL_FLAG_TBL_SRV("ECDHSingle", SSL_OP_SINGLE_ECDH_USE),
|
||||
SSL_FLAG_TBL("UnsafeLegacyRenegotiation",
|
||||
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION),
|
||||
SSL_FLAG_TBL_INV("EncryptThenMac", SSL_OP_NO_ENCRYPT_THEN_MAC),
|
||||
SSL_FLAG_TBL("NoRenegotiation", SSL_OP_NO_RENEGOTIATION),
|
||||
SSL_FLAG_TBL("AllowNoDHEKEX", SSL_OP_ALLOW_NO_DHE_KEX),
|
||||
SSL_FLAG_TBL("PrioritizeChaCha", SSL_OP_PRIORITIZE_CHACHA),
|
||||
SSL_FLAG_TBL("MiddleboxCompat", SSL_OP_ENABLE_MIDDLEBOX_COMPAT),
|
||||
SSL_FLAG_TBL_INV("AntiReplay", SSL_OP_NO_ANTI_REPLAY)
|
||||
};
|
||||
if (value == NULL)
|
||||
return -3;
|
||||
cctx->tbl = ssl_option_list;
|
||||
cctx->ntbl = OSSL_NELEM(ssl_option_list);
|
||||
return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
|
||||
}
|
||||
|
||||
static int cmd_VerifyMode(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
static const ssl_flag_tbl ssl_vfy_list[] = {
|
||||
SSL_FLAG_VFY_CLI("Peer", SSL_VERIFY_PEER),
|
||||
SSL_FLAG_VFY_SRV("Request", SSL_VERIFY_PEER),
|
||||
SSL_FLAG_VFY_SRV("Require",
|
||||
SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT),
|
||||
SSL_FLAG_VFY_SRV("Once", SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE),
|
||||
SSL_FLAG_VFY_SRV("RequestPostHandshake",
|
||||
SSL_VERIFY_PEER | SSL_VERIFY_POST_HANDSHAKE),
|
||||
SSL_FLAG_VFY_SRV("RequirePostHandshake",
|
||||
SSL_VERIFY_PEER | SSL_VERIFY_POST_HANDSHAKE |
|
||||
SSL_VERIFY_FAIL_IF_NO_PEER_CERT),
|
||||
};
|
||||
if (value == NULL)
|
||||
return -3;
|
||||
cctx->tbl = ssl_vfy_list;
|
||||
cctx->ntbl = OSSL_NELEM(ssl_vfy_list);
|
||||
return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
|
||||
}
|
||||
|
||||
static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
int rv = 1;
|
||||
CERT *c = NULL;
|
||||
if (cctx->ctx) {
|
||||
rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value);
|
||||
c = cctx->ctx->cert;
|
||||
}
|
||||
if (cctx->ssl) {
|
||||
rv = SSL_use_certificate_chain_file(cctx->ssl, value);
|
||||
c = cctx->ssl->cert;
|
||||
}
|
||||
if (rv > 0 && c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
|
||||
char **pfilename = &cctx->cert_filename[c->key - c->pkeys];
|
||||
OPENSSL_free(*pfilename);
|
||||
*pfilename = OPENSSL_strdup(value);
|
||||
if (!*pfilename)
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
return rv > 0;
|
||||
}
|
||||
|
||||
static int cmd_PrivateKey(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
int rv = 1;
|
||||
if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE))
|
||||
return -2;
|
||||
if (cctx->ctx)
|
||||
rv = SSL_CTX_use_PrivateKey_file(cctx->ctx, value, SSL_FILETYPE_PEM);
|
||||
if (cctx->ssl)
|
||||
rv = SSL_use_PrivateKey_file(cctx->ssl, value, SSL_FILETYPE_PEM);
|
||||
return rv > 0;
|
||||
}
|
||||
|
||||
static int cmd_ServerInfoFile(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
int rv = 1;
|
||||
if (cctx->ctx)
|
||||
rv = SSL_CTX_use_serverinfo_file(cctx->ctx, value);
|
||||
return rv > 0;
|
||||
}
|
||||
|
||||
static int do_store(SSL_CONF_CTX *cctx,
|
||||
const char *CAfile, const char *CApath, int verify_store)
|
||||
{
|
||||
CERT *cert;
|
||||
X509_STORE **st;
|
||||
if (cctx->ctx)
|
||||
cert = cctx->ctx->cert;
|
||||
else if (cctx->ssl)
|
||||
cert = cctx->ssl->cert;
|
||||
else
|
||||
return 1;
|
||||
st = verify_store ? &cert->verify_store : &cert->chain_store;
|
||||
if (*st == NULL) {
|
||||
*st = X509_STORE_new();
|
||||
if (*st == NULL)
|
||||
return 0;
|
||||
}
|
||||
return X509_STORE_load_locations(*st, CAfile, CApath) > 0;
|
||||
}
|
||||
|
||||
static int cmd_ChainCAPath(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
return do_store(cctx, NULL, value, 0);
|
||||
}
|
||||
|
||||
static int cmd_ChainCAFile(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
return do_store(cctx, value, NULL, 0);
|
||||
}
|
||||
|
||||
static int cmd_VerifyCAPath(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
return do_store(cctx, NULL, value, 1);
|
||||
}
|
||||
|
||||
static int cmd_VerifyCAFile(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
return do_store(cctx, value, NULL, 1);
|
||||
}
|
||||
|
||||
static int cmd_RequestCAFile(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
if (cctx->canames == NULL)
|
||||
cctx->canames = sk_X509_NAME_new_null();
|
||||
if (cctx->canames == NULL)
|
||||
return 0;
|
||||
return SSL_add_file_cert_subjects_to_stack(cctx->canames, value);
|
||||
}
|
||||
|
||||
static int cmd_ClientCAFile(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
return cmd_RequestCAFile(cctx, value);
|
||||
}
|
||||
|
||||
static int cmd_RequestCAPath(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
if (cctx->canames == NULL)
|
||||
cctx->canames = sk_X509_NAME_new_null();
|
||||
if (cctx->canames == NULL)
|
||||
return 0;
|
||||
return SSL_add_dir_cert_subjects_to_stack(cctx->canames, value);
|
||||
}
|
||||
|
||||
static int cmd_ClientCAPath(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
return cmd_RequestCAPath(cctx, value);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_DH
|
||||
static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
int rv = 0;
|
||||
DH *dh = NULL;
|
||||
BIO *in = NULL;
|
||||
if (cctx->ctx || cctx->ssl) {
|
||||
in = BIO_new(BIO_s_file());
|
||||
if (in == NULL)
|
||||
goto end;
|
||||
if (BIO_read_filename(in, value) <= 0)
|
||||
goto end;
|
||||
dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
|
||||
if (dh == NULL)
|
||||
goto end;
|
||||
} else
|
||||
return 1;
|
||||
if (cctx->ctx)
|
||||
rv = SSL_CTX_set_tmp_dh(cctx->ctx, dh);
|
||||
if (cctx->ssl)
|
||||
rv = SSL_set_tmp_dh(cctx->ssl, dh);
|
||||
end:
|
||||
DH_free(dh);
|
||||
BIO_free(in);
|
||||
return rv > 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int cmd_RecordPadding(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
int rv = 0;
|
||||
int block_size = atoi(value);
|
||||
|
||||
/*
|
||||
* All we care about is a non-negative value,
|
||||
* the setters check the range
|
||||
*/
|
||||
if (block_size >= 0) {
|
||||
if (cctx->ctx)
|
||||
rv = SSL_CTX_set_block_padding(cctx->ctx, block_size);
|
||||
if (cctx->ssl)
|
||||
rv = SSL_set_block_padding(cctx->ssl, block_size);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static int cmd_NumTickets(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
int rv = 0;
|
||||
int num_tickets = atoi(value);
|
||||
|
||||
if (num_tickets >= 0) {
|
||||
if (cctx->ctx)
|
||||
rv = SSL_CTX_set_num_tickets(cctx->ctx, num_tickets);
|
||||
if (cctx->ssl)
|
||||
rv = SSL_set_num_tickets(cctx->ssl, num_tickets);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int (*cmd) (SSL_CONF_CTX *cctx, const char *value);
|
||||
const char *str_file;
|
||||
const char *str_cmdline;
|
||||
unsigned short flags;
|
||||
unsigned short value_type;
|
||||
} ssl_conf_cmd_tbl;
|
||||
|
||||
/* Table of supported parameters */
|
||||
|
||||
#define SSL_CONF_CMD(name, cmdopt, flags, type) \
|
||||
{cmd_##name, #name, cmdopt, flags, type}
|
||||
|
||||
#define SSL_CONF_CMD_STRING(name, cmdopt, flags) \
|
||||
SSL_CONF_CMD(name, cmdopt, flags, SSL_CONF_TYPE_STRING)
|
||||
|
||||
#define SSL_CONF_CMD_SWITCH(name, flags) \
|
||||
{0, NULL, name, flags, SSL_CONF_TYPE_NONE}
|
||||
|
||||
/* See apps/apps.h if you change this table. */
|
||||
static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
|
||||
SSL_CONF_CMD_SWITCH("no_ssl3", 0),
|
||||
SSL_CONF_CMD_SWITCH("no_tls1", 0),
|
||||
SSL_CONF_CMD_SWITCH("no_tls1_1", 0),
|
||||
SSL_CONF_CMD_SWITCH("no_tls1_2", 0),
|
||||
SSL_CONF_CMD_SWITCH("no_tls1_3", 0),
|
||||
SSL_CONF_CMD_SWITCH("bugs", 0),
|
||||
SSL_CONF_CMD_SWITCH("no_comp", 0),
|
||||
SSL_CONF_CMD_SWITCH("comp", 0),
|
||||
SSL_CONF_CMD_SWITCH("ecdh_single", SSL_CONF_FLAG_SERVER),
|
||||
SSL_CONF_CMD_SWITCH("no_ticket", 0),
|
||||
SSL_CONF_CMD_SWITCH("serverpref", SSL_CONF_FLAG_SERVER),
|
||||
SSL_CONF_CMD_SWITCH("legacy_renegotiation", 0),
|
||||
SSL_CONF_CMD_SWITCH("legacy_server_connect", SSL_CONF_FLAG_SERVER),
|
||||
SSL_CONF_CMD_SWITCH("no_renegotiation", 0),
|
||||
SSL_CONF_CMD_SWITCH("no_resumption_on_reneg", SSL_CONF_FLAG_SERVER),
|
||||
SSL_CONF_CMD_SWITCH("no_legacy_server_connect", SSL_CONF_FLAG_SERVER),
|
||||
SSL_CONF_CMD_SWITCH("allow_no_dhe_kex", 0),
|
||||
SSL_CONF_CMD_SWITCH("prioritize_chacha", SSL_CONF_FLAG_SERVER),
|
||||
SSL_CONF_CMD_SWITCH("strict", 0),
|
||||
SSL_CONF_CMD_SWITCH("no_middlebox", 0),
|
||||
SSL_CONF_CMD_SWITCH("anti_replay", SSL_CONF_FLAG_SERVER),
|
||||
SSL_CONF_CMD_SWITCH("no_anti_replay", SSL_CONF_FLAG_SERVER),
|
||||
SSL_CONF_CMD_STRING(SignatureAlgorithms, "sigalgs", 0),
|
||||
SSL_CONF_CMD_STRING(ClientSignatureAlgorithms, "client_sigalgs", 0),
|
||||
SSL_CONF_CMD_STRING(Curves, "curves", 0),
|
||||
SSL_CONF_CMD_STRING(Groups, "groups", 0),
|
||||
#ifndef OPENSSL_NO_EC
|
||||
SSL_CONF_CMD_STRING(ECDHParameters, "named_curve", SSL_CONF_FLAG_SERVER),
|
||||
#endif
|
||||
SSL_CONF_CMD_STRING(CipherString, "cipher", 0),
|
||||
SSL_CONF_CMD_STRING(Ciphersuites, "ciphersuites", 0),
|
||||
SSL_CONF_CMD_STRING(Protocol, NULL, 0),
|
||||
SSL_CONF_CMD_STRING(MinProtocol, "min_protocol", 0),
|
||||
SSL_CONF_CMD_STRING(MaxProtocol, "max_protocol", 0),
|
||||
SSL_CONF_CMD_STRING(Options, NULL, 0),
|
||||
SSL_CONF_CMD_STRING(VerifyMode, NULL, 0),
|
||||
SSL_CONF_CMD(Certificate, "cert", SSL_CONF_FLAG_CERTIFICATE,
|
||||
SSL_CONF_TYPE_FILE),
|
||||
SSL_CONF_CMD(PrivateKey, "key", SSL_CONF_FLAG_CERTIFICATE,
|
||||
SSL_CONF_TYPE_FILE),
|
||||
SSL_CONF_CMD(ServerInfoFile, NULL,
|
||||
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
|
||||
SSL_CONF_TYPE_FILE),
|
||||
SSL_CONF_CMD(ChainCAPath, "chainCApath", SSL_CONF_FLAG_CERTIFICATE,
|
||||
SSL_CONF_TYPE_DIR),
|
||||
SSL_CONF_CMD(ChainCAFile, "chainCAfile", SSL_CONF_FLAG_CERTIFICATE,
|
||||
SSL_CONF_TYPE_FILE),
|
||||
SSL_CONF_CMD(VerifyCAPath, "verifyCApath", SSL_CONF_FLAG_CERTIFICATE,
|
||||
SSL_CONF_TYPE_DIR),
|
||||
SSL_CONF_CMD(VerifyCAFile, "verifyCAfile", SSL_CONF_FLAG_CERTIFICATE,
|
||||
SSL_CONF_TYPE_FILE),
|
||||
SSL_CONF_CMD(RequestCAFile, "requestCAFile", SSL_CONF_FLAG_CERTIFICATE,
|
||||
SSL_CONF_TYPE_FILE),
|
||||
SSL_CONF_CMD(ClientCAFile, NULL,
|
||||
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
|
||||
SSL_CONF_TYPE_FILE),
|
||||
SSL_CONF_CMD(RequestCAPath, NULL, SSL_CONF_FLAG_CERTIFICATE,
|
||||
SSL_CONF_TYPE_DIR),
|
||||
SSL_CONF_CMD(ClientCAPath, NULL,
|
||||
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
|
||||
SSL_CONF_TYPE_DIR),
|
||||
#ifndef OPENSSL_NO_DH
|
||||
SSL_CONF_CMD(DHParameters, "dhparam",
|
||||
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
|
||||
SSL_CONF_TYPE_FILE),
|
||||
#endif
|
||||
SSL_CONF_CMD_STRING(RecordPadding, "record_padding", 0),
|
||||
SSL_CONF_CMD_STRING(NumTickets, "num_tickets", SSL_CONF_FLAG_SERVER),
|
||||
};
|
||||
|
||||
/* Supported switches: must match order of switches in ssl_conf_cmds */
|
||||
static const ssl_switch_tbl ssl_cmd_switches[] = {
|
||||
{SSL_OP_NO_SSLv3, 0}, /* no_ssl3 */
|
||||
{SSL_OP_NO_TLSv1, 0}, /* no_tls1 */
|
||||
{SSL_OP_NO_TLSv1_1, 0}, /* no_tls1_1 */
|
||||
{SSL_OP_NO_TLSv1_2, 0}, /* no_tls1_2 */
|
||||
{SSL_OP_NO_TLSv1_3, 0}, /* no_tls1_3 */
|
||||
{SSL_OP_ALL, 0}, /* bugs */
|
||||
{SSL_OP_NO_COMPRESSION, 0}, /* no_comp */
|
||||
{SSL_OP_NO_COMPRESSION, SSL_TFLAG_INV}, /* comp */
|
||||
{SSL_OP_SINGLE_ECDH_USE, 0}, /* ecdh_single */
|
||||
{SSL_OP_NO_TICKET, 0}, /* no_ticket */
|
||||
{SSL_OP_CIPHER_SERVER_PREFERENCE, 0}, /* serverpref */
|
||||
/* legacy_renegotiation */
|
||||
{SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, 0},
|
||||
/* legacy_server_connect */
|
||||
{SSL_OP_LEGACY_SERVER_CONNECT, 0},
|
||||
/* no_renegotiation */
|
||||
{SSL_OP_NO_RENEGOTIATION, 0},
|
||||
/* no_resumption_on_reneg */
|
||||
{SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION, 0},
|
||||
/* no_legacy_server_connect */
|
||||
{SSL_OP_LEGACY_SERVER_CONNECT, SSL_TFLAG_INV},
|
||||
/* allow_no_dhe_kex */
|
||||
{SSL_OP_ALLOW_NO_DHE_KEX, 0},
|
||||
/* chacha reprioritization */
|
||||
{SSL_OP_PRIORITIZE_CHACHA, 0},
|
||||
{SSL_CERT_FLAG_TLS_STRICT, SSL_TFLAG_CERT}, /* strict */
|
||||
/* no_middlebox */
|
||||
{SSL_OP_ENABLE_MIDDLEBOX_COMPAT, SSL_TFLAG_INV},
|
||||
/* anti_replay */
|
||||
{SSL_OP_NO_ANTI_REPLAY, SSL_TFLAG_INV},
|
||||
/* no_anti_replay */
|
||||
{SSL_OP_NO_ANTI_REPLAY, 0},
|
||||
};
|
||||
|
||||
static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd)
|
||||
{
|
||||
if (!pcmd || !*pcmd)
|
||||
return 0;
|
||||
/* If a prefix is set, check and skip */
|
||||
if (cctx->prefix) {
|
||||
if (strlen(*pcmd) <= cctx->prefixlen)
|
||||
return 0;
|
||||
if (cctx->flags & SSL_CONF_FLAG_CMDLINE &&
|
||||
strncmp(*pcmd, cctx->prefix, cctx->prefixlen))
|
||||
return 0;
|
||||
if (cctx->flags & SSL_CONF_FLAG_FILE &&
|
||||
strncasecmp(*pcmd, cctx->prefix, cctx->prefixlen))
|
||||
return 0;
|
||||
*pcmd += cctx->prefixlen;
|
||||
} else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) {
|
||||
if (**pcmd != '-' || !(*pcmd)[1])
|
||||
return 0;
|
||||
*pcmd += 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Determine if a command is allowed according to cctx flags */
|
||||
static int ssl_conf_cmd_allowed(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl * t)
|
||||
{
|
||||
unsigned int tfl = t->flags;
|
||||
unsigned int cfl = cctx->flags;
|
||||
if ((tfl & SSL_CONF_FLAG_SERVER) && !(cfl & SSL_CONF_FLAG_SERVER))
|
||||
return 0;
|
||||
if ((tfl & SSL_CONF_FLAG_CLIENT) && !(cfl & SSL_CONF_FLAG_CLIENT))
|
||||
return 0;
|
||||
if ((tfl & SSL_CONF_FLAG_CERTIFICATE)
|
||||
&& !(cfl & SSL_CONF_FLAG_CERTIFICATE))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const ssl_conf_cmd_tbl *ssl_conf_cmd_lookup(SSL_CONF_CTX *cctx,
|
||||
const char *cmd)
|
||||
{
|
||||
const ssl_conf_cmd_tbl *t;
|
||||
size_t i;
|
||||
if (cmd == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Look for matching parameter name in table */
|
||||
for (i = 0, t = ssl_conf_cmds; i < OSSL_NELEM(ssl_conf_cmds); i++, t++) {
|
||||
if (ssl_conf_cmd_allowed(cctx, t)) {
|
||||
if (cctx->flags & SSL_CONF_FLAG_CMDLINE) {
|
||||
if (t->str_cmdline && strcmp(t->str_cmdline, cmd) == 0)
|
||||
return t;
|
||||
}
|
||||
if (cctx->flags & SSL_CONF_FLAG_FILE) {
|
||||
if (t->str_file && strcasecmp(t->str_file, cmd) == 0)
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ctrl_switch_option(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl * cmd)
|
||||
{
|
||||
/* Find index of command in table */
|
||||
size_t idx = cmd - ssl_conf_cmds;
|
||||
const ssl_switch_tbl *scmd;
|
||||
/* Sanity check index */
|
||||
if (idx >= OSSL_NELEM(ssl_cmd_switches))
|
||||
return 0;
|
||||
/* Obtain switches entry with same index */
|
||||
scmd = ssl_cmd_switches + idx;
|
||||
ssl_set_option(cctx, scmd->name_flags, scmd->option_value, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value)
|
||||
{
|
||||
const ssl_conf_cmd_tbl *runcmd;
|
||||
if (cmd == NULL) {
|
||||
SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_INVALID_NULL_CMD_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ssl_conf_cmd_skip_prefix(cctx, &cmd))
|
||||
return -2;
|
||||
|
||||
runcmd = ssl_conf_cmd_lookup(cctx, cmd);
|
||||
|
||||
if (runcmd) {
|
||||
int rv;
|
||||
if (runcmd->value_type == SSL_CONF_TYPE_NONE) {
|
||||
return ctrl_switch_option(cctx, runcmd);
|
||||
}
|
||||
if (value == NULL)
|
||||
return -3;
|
||||
rv = runcmd->cmd(cctx, value);
|
||||
if (rv > 0)
|
||||
return 2;
|
||||
if (rv == -2)
|
||||
return -2;
|
||||
if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) {
|
||||
SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_BAD_VALUE);
|
||||
ERR_add_error_data(4, "cmd=", cmd, ", value=", value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) {
|
||||
SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_UNKNOWN_CMD_NAME);
|
||||
ERR_add_error_data(2, "cmd=", cmd);
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv)
|
||||
{
|
||||
int rv;
|
||||
const char *arg = NULL, *argn;
|
||||
if (pargc && *pargc == 0)
|
||||
return 0;
|
||||
if (!pargc || *pargc > 0)
|
||||
arg = **pargv;
|
||||
if (arg == NULL)
|
||||
return 0;
|
||||
if (!pargc || *pargc > 1)
|
||||
argn = (*pargv)[1];
|
||||
else
|
||||
argn = NULL;
|
||||
cctx->flags &= ~SSL_CONF_FLAG_FILE;
|
||||
cctx->flags |= SSL_CONF_FLAG_CMDLINE;
|
||||
rv = SSL_CONF_cmd(cctx, arg, argn);
|
||||
if (rv > 0) {
|
||||
/* Success: update pargc, pargv */
|
||||
(*pargv) += rv;
|
||||
if (pargc)
|
||||
(*pargc) -= rv;
|
||||
return rv;
|
||||
}
|
||||
/* Unknown switch: indicate no arguments processed */
|
||||
if (rv == -2)
|
||||
return 0;
|
||||
/* Some error occurred processing command, return fatal error */
|
||||
if (rv == 0)
|
||||
return -1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd)
|
||||
{
|
||||
if (ssl_conf_cmd_skip_prefix(cctx, &cmd)) {
|
||||
const ssl_conf_cmd_tbl *runcmd;
|
||||
runcmd = ssl_conf_cmd_lookup(cctx, cmd);
|
||||
if (runcmd)
|
||||
return runcmd->value_type;
|
||||
}
|
||||
return SSL_CONF_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
SSL_CONF_CTX *SSL_CONF_CTX_new(void)
|
||||
{
|
||||
SSL_CONF_CTX *ret = OPENSSL_zalloc(sizeof(*ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx)
|
||||
{
|
||||
/* See if any certificates are missing private keys */
|
||||
size_t i;
|
||||
CERT *c = NULL;
|
||||
if (cctx->ctx)
|
||||
c = cctx->ctx->cert;
|
||||
else if (cctx->ssl)
|
||||
c = cctx->ssl->cert;
|
||||
if (c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
|
||||
for (i = 0; i < SSL_PKEY_NUM; i++) {
|
||||
const char *p = cctx->cert_filename[i];
|
||||
/*
|
||||
* If missing private key try to load one from certificate file
|
||||
*/
|
||||
if (p && !c->pkeys[i].privatekey) {
|
||||
if (!cmd_PrivateKey(cctx, p))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cctx->canames) {
|
||||
if (cctx->ssl)
|
||||
SSL_set0_CA_list(cctx->ssl, cctx->canames);
|
||||
else if (cctx->ctx)
|
||||
SSL_CTX_set0_CA_list(cctx->ctx, cctx->canames);
|
||||
else
|
||||
sk_X509_NAME_pop_free(cctx->canames, X509_NAME_free);
|
||||
cctx->canames = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx)
|
||||
{
|
||||
if (cctx) {
|
||||
size_t i;
|
||||
for (i = 0; i < SSL_PKEY_NUM; i++)
|
||||
OPENSSL_free(cctx->cert_filename[i]);
|
||||
OPENSSL_free(cctx->prefix);
|
||||
sk_X509_NAME_pop_free(cctx->canames, X509_NAME_free);
|
||||
OPENSSL_free(cctx);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags)
|
||||
{
|
||||
cctx->flags |= flags;
|
||||
return cctx->flags;
|
||||
}
|
||||
|
||||
unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx, unsigned int flags)
|
||||
{
|
||||
cctx->flags &= ~flags;
|
||||
return cctx->flags;
|
||||
}
|
||||
|
||||
int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre)
|
||||
{
|
||||
char *tmp = NULL;
|
||||
if (pre) {
|
||||
tmp = OPENSSL_strdup(pre);
|
||||
if (tmp == NULL)
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_free(cctx->prefix);
|
||||
cctx->prefix = tmp;
|
||||
if (tmp)
|
||||
cctx->prefixlen = strlen(tmp);
|
||||
else
|
||||
cctx->prefixlen = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl)
|
||||
{
|
||||
cctx->ssl = ssl;
|
||||
cctx->ctx = NULL;
|
||||
if (ssl) {
|
||||
cctx->poptions = &ssl->options;
|
||||
cctx->min_version = &ssl->min_proto_version;
|
||||
cctx->max_version = &ssl->max_proto_version;
|
||||
cctx->pcert_flags = &ssl->cert->cert_flags;
|
||||
cctx->pvfy_flags = &ssl->verify_mode;
|
||||
} else {
|
||||
cctx->poptions = NULL;
|
||||
cctx->min_version = NULL;
|
||||
cctx->max_version = NULL;
|
||||
cctx->pcert_flags = NULL;
|
||||
cctx->pvfy_flags = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx)
|
||||
{
|
||||
cctx->ctx = ctx;
|
||||
cctx->ssl = NULL;
|
||||
if (ctx) {
|
||||
cctx->poptions = &ctx->options;
|
||||
cctx->min_version = &ctx->min_proto_version;
|
||||
cctx->max_version = &ctx->max_proto_version;
|
||||
cctx->pcert_flags = &ctx->cert->cert_flags;
|
||||
cctx->pvfy_flags = &ctx->verify_mode;
|
||||
} else {
|
||||
cctx->poptions = NULL;
|
||||
cctx->min_version = NULL;
|
||||
cctx->max_version = NULL;
|
||||
cctx->pcert_flags = NULL;
|
||||
cctx->pvfy_flags = NULL;
|
||||
}
|
||||
}
|
1277
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_err.c
vendored
Normal file
1277
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_err.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
221
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_init.c
vendored
Normal file
221
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_init.c
vendored
Normal file
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "e_os.h"
|
||||
|
||||
#include "internal/err.h"
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "ssl_locl.h"
|
||||
#include "internal/thread_once.h"
|
||||
|
||||
static int stopped;
|
||||
|
||||
static void ssl_library_stop(void);
|
||||
|
||||
static CRYPTO_ONCE ssl_base = CRYPTO_ONCE_STATIC_INIT;
|
||||
static int ssl_base_inited = 0;
|
||||
DEFINE_RUN_ONCE_STATIC(ossl_init_ssl_base)
|
||||
{
|
||||
#ifdef OPENSSL_INIT_DEBUG
|
||||
fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: "
|
||||
"Adding SSL ciphers and digests\n");
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DES
|
||||
EVP_add_cipher(EVP_des_cbc());
|
||||
EVP_add_cipher(EVP_des_ede3_cbc());
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_IDEA
|
||||
EVP_add_cipher(EVP_idea_cbc());
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_RC4
|
||||
EVP_add_cipher(EVP_rc4());
|
||||
# ifndef OPENSSL_NO_MD5
|
||||
EVP_add_cipher(EVP_rc4_hmac_md5());
|
||||
# endif
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_RC2
|
||||
EVP_add_cipher(EVP_rc2_cbc());
|
||||
/*
|
||||
* Not actually used for SSL/TLS but this makes PKCS#12 work if an
|
||||
* application only calls SSL_library_init().
|
||||
*/
|
||||
EVP_add_cipher(EVP_rc2_40_cbc());
|
||||
#endif
|
||||
EVP_add_cipher(EVP_aes_128_cbc());
|
||||
EVP_add_cipher(EVP_aes_192_cbc());
|
||||
EVP_add_cipher(EVP_aes_256_cbc());
|
||||
EVP_add_cipher(EVP_aes_128_gcm());
|
||||
EVP_add_cipher(EVP_aes_256_gcm());
|
||||
EVP_add_cipher(EVP_aes_128_ccm());
|
||||
EVP_add_cipher(EVP_aes_256_ccm());
|
||||
EVP_add_cipher(EVP_aes_128_cbc_hmac_sha1());
|
||||
EVP_add_cipher(EVP_aes_256_cbc_hmac_sha1());
|
||||
EVP_add_cipher(EVP_aes_128_cbc_hmac_sha256());
|
||||
EVP_add_cipher(EVP_aes_256_cbc_hmac_sha256());
|
||||
#ifndef OPENSSL_NO_ARIA
|
||||
EVP_add_cipher(EVP_aria_128_gcm());
|
||||
EVP_add_cipher(EVP_aria_256_gcm());
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_CAMELLIA
|
||||
EVP_add_cipher(EVP_camellia_128_cbc());
|
||||
EVP_add_cipher(EVP_camellia_256_cbc());
|
||||
#endif
|
||||
#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
|
||||
EVP_add_cipher(EVP_chacha20_poly1305());
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_SEED
|
||||
EVP_add_cipher(EVP_seed_cbc());
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_MD5
|
||||
EVP_add_digest(EVP_md5());
|
||||
EVP_add_digest_alias(SN_md5, "ssl3-md5");
|
||||
EVP_add_digest(EVP_md5_sha1());
|
||||
#endif
|
||||
EVP_add_digest(EVP_sha1()); /* RSA with sha1 */
|
||||
EVP_add_digest_alias(SN_sha1, "ssl3-sha1");
|
||||
EVP_add_digest_alias(SN_sha1WithRSAEncryption, SN_sha1WithRSA);
|
||||
EVP_add_digest(EVP_sha224());
|
||||
EVP_add_digest(EVP_sha256());
|
||||
EVP_add_digest(EVP_sha384());
|
||||
EVP_add_digest(EVP_sha512());
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
# ifdef OPENSSL_INIT_DEBUG
|
||||
fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: "
|
||||
"SSL_COMP_get_compression_methods()\n");
|
||||
# endif
|
||||
/*
|
||||
* This will initialise the built-in compression algorithms. The value
|
||||
* returned is a STACK_OF(SSL_COMP), but that can be discarded safely
|
||||
*/
|
||||
SSL_COMP_get_compression_methods();
|
||||
#endif
|
||||
/* initialize cipher/digest methods table */
|
||||
if (!ssl_load_ciphers())
|
||||
return 0;
|
||||
|
||||
#ifdef OPENSSL_INIT_DEBUG
|
||||
fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: "
|
||||
"SSL_add_ssl_module()\n");
|
||||
#endif
|
||||
/*
|
||||
* We ignore an error return here. Not much we can do - but not that bad
|
||||
* either. We can still safely continue.
|
||||
*/
|
||||
OPENSSL_atexit(ssl_library_stop);
|
||||
ssl_base_inited = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static CRYPTO_ONCE ssl_strings = CRYPTO_ONCE_STATIC_INIT;
|
||||
static int ssl_strings_inited = 0;
|
||||
DEFINE_RUN_ONCE_STATIC(ossl_init_load_ssl_strings)
|
||||
{
|
||||
/*
|
||||
* OPENSSL_NO_AUTOERRINIT is provided here to prevent at compile time
|
||||
* pulling in all the error strings during static linking
|
||||
*/
|
||||
#if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT)
|
||||
# ifdef OPENSSL_INIT_DEBUG
|
||||
fprintf(stderr, "OPENSSL_INIT: ossl_init_load_ssl_strings: "
|
||||
"ERR_load_SSL_strings()\n");
|
||||
# endif
|
||||
ERR_load_SSL_strings();
|
||||
ssl_strings_inited = 1;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_ssl_strings,
|
||||
ossl_init_load_ssl_strings)
|
||||
{
|
||||
/* Do nothing in this case */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ssl_library_stop(void)
|
||||
{
|
||||
/* Might be explicitly called and also by atexit */
|
||||
if (stopped)
|
||||
return;
|
||||
stopped = 1;
|
||||
|
||||
if (ssl_base_inited) {
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
# ifdef OPENSSL_INIT_DEBUG
|
||||
fprintf(stderr, "OPENSSL_INIT: ssl_library_stop: "
|
||||
"ssl_comp_free_compression_methods_int()\n");
|
||||
# endif
|
||||
ssl_comp_free_compression_methods_int();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ssl_strings_inited) {
|
||||
#ifdef OPENSSL_INIT_DEBUG
|
||||
fprintf(stderr, "OPENSSL_INIT: ssl_library_stop: "
|
||||
"err_free_strings_int()\n");
|
||||
#endif
|
||||
/*
|
||||
* If both crypto and ssl error strings are inited we will end up
|
||||
* calling err_free_strings_int() twice - but that's ok. The second
|
||||
* time will be a no-op. It's easier to do that than to try and track
|
||||
* between the two libraries whether they have both been inited.
|
||||
*/
|
||||
err_free_strings_int();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If this function is called with a non NULL settings value then it must be
|
||||
* called prior to any threads making calls to any OpenSSL functions,
|
||||
* i.e. passing a non-null settings value is assumed to be single-threaded.
|
||||
*/
|
||||
int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS * settings)
|
||||
{
|
||||
static int stoperrset = 0;
|
||||
|
||||
if (stopped) {
|
||||
if (!stoperrset) {
|
||||
/*
|
||||
* We only ever set this once to avoid getting into an infinite
|
||||
* loop where the error system keeps trying to init and fails so
|
||||
* sets an error etc
|
||||
*/
|
||||
stoperrset = 1;
|
||||
SSLerr(SSL_F_OPENSSL_INIT_SSL, ERR_R_INIT_FAIL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
opts |= OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS;
|
||||
#ifndef OPENSSL_NO_AUTOLOAD_CONFIG
|
||||
if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG) == 0)
|
||||
opts |= OPENSSL_INIT_LOAD_CONFIG;
|
||||
#endif
|
||||
|
||||
if (!OPENSSL_init_crypto(opts, settings))
|
||||
return 0;
|
||||
|
||||
if (!RUN_ONCE(&ssl_base, ossl_init_ssl_base))
|
||||
return 0;
|
||||
|
||||
if ((opts & OPENSSL_INIT_NO_LOAD_SSL_STRINGS)
|
||||
&& !RUN_ONCE_ALT(&ssl_strings, ossl_init_no_load_ssl_strings,
|
||||
ossl_init_load_ssl_strings))
|
||||
return 0;
|
||||
|
||||
if ((opts & OPENSSL_INIT_LOAD_SSL_STRINGS)
|
||||
&& !RUN_ONCE(&ssl_strings, ossl_init_load_ssl_strings))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
5581
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_lib.c
vendored
Normal file
5581
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_lib.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
2666
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_locl.h
vendored
Normal file
2666
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_locl.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
99
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_mcnf.c
vendored
Normal file
99
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_mcnf.c
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include "ssl_locl.h"
|
||||
#include "internal/sslconf.h"
|
||||
|
||||
/* SSL library configuration module. */
|
||||
|
||||
void SSL_add_ssl_module(void)
|
||||
{
|
||||
/* Do nothing. This will be added automatically by libcrypto */
|
||||
}
|
||||
|
||||
static int ssl_do_config(SSL *s, SSL_CTX *ctx, const char *name, int system)
|
||||
{
|
||||
SSL_CONF_CTX *cctx = NULL;
|
||||
size_t i, idx, cmd_count;
|
||||
int rv = 0;
|
||||
unsigned int flags;
|
||||
const SSL_METHOD *meth;
|
||||
const SSL_CONF_CMD *cmds;
|
||||
|
||||
if (s == NULL && ctx == NULL) {
|
||||
SSLerr(SSL_F_SSL_DO_CONFIG, ERR_R_PASSED_NULL_PARAMETER);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (name == NULL && system)
|
||||
name = "system_default";
|
||||
if (!conf_ssl_name_find(name, &idx)) {
|
||||
if (!system) {
|
||||
SSLerr(SSL_F_SSL_DO_CONFIG, SSL_R_INVALID_CONFIGURATION_NAME);
|
||||
ERR_add_error_data(2, "name=", name);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
cmds = conf_ssl_get(idx, &name, &cmd_count);
|
||||
cctx = SSL_CONF_CTX_new();
|
||||
if (cctx == NULL)
|
||||
goto err;
|
||||
flags = SSL_CONF_FLAG_FILE;
|
||||
if (!system)
|
||||
flags |= SSL_CONF_FLAG_CERTIFICATE | SSL_CONF_FLAG_REQUIRE_PRIVATE;
|
||||
if (s != NULL) {
|
||||
meth = s->method;
|
||||
SSL_CONF_CTX_set_ssl(cctx, s);
|
||||
} else {
|
||||
meth = ctx->method;
|
||||
SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
|
||||
}
|
||||
if (meth->ssl_accept != ssl_undefined_function)
|
||||
flags |= SSL_CONF_FLAG_SERVER;
|
||||
if (meth->ssl_connect != ssl_undefined_function)
|
||||
flags |= SSL_CONF_FLAG_CLIENT;
|
||||
SSL_CONF_CTX_set_flags(cctx, flags);
|
||||
for (i = 0; i < cmd_count; i++) {
|
||||
char *cmdstr, *arg;
|
||||
|
||||
conf_ssl_get_cmd(cmds, i, &cmdstr, &arg);
|
||||
rv = SSL_CONF_cmd(cctx, cmdstr, arg);
|
||||
if (rv <= 0) {
|
||||
if (rv == -2)
|
||||
SSLerr(SSL_F_SSL_DO_CONFIG, SSL_R_UNKNOWN_COMMAND);
|
||||
else
|
||||
SSLerr(SSL_F_SSL_DO_CONFIG, SSL_R_BAD_VALUE);
|
||||
ERR_add_error_data(6, "section=", name, ", cmd=", cmdstr,
|
||||
", arg=", arg);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
rv = SSL_CONF_CTX_finish(cctx);
|
||||
err:
|
||||
SSL_CONF_CTX_free(cctx);
|
||||
return rv <= 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
int SSL_config(SSL *s, const char *name)
|
||||
{
|
||||
return ssl_do_config(s, NULL, name, 0);
|
||||
}
|
||||
|
||||
int SSL_CTX_config(SSL_CTX *ctx, const char *name)
|
||||
{
|
||||
return ssl_do_config(NULL, ctx, name, 0);
|
||||
}
|
||||
|
||||
void ssl_ctx_system_config(SSL_CTX *ctx)
|
||||
{
|
||||
ssl_do_config(NULL, ctx, NULL, 1);
|
||||
}
|
1148
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_rsa.c
vendored
Normal file
1148
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_rsa.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
1317
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_sess.c
vendored
Normal file
1317
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_sess.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
388
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_stat.c
vendored
Normal file
388
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_stat.c
vendored
Normal file
|
@ -0,0 +1,388 @@
|
|||
/*
|
||||
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2005 Nokia. All rights reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "ssl_locl.h"
|
||||
|
||||
const char *SSL_state_string_long(const SSL *s)
|
||||
{
|
||||
if (ossl_statem_in_error(s))
|
||||
return "error";
|
||||
|
||||
switch (SSL_get_state(s)) {
|
||||
case TLS_ST_CR_CERT_STATUS:
|
||||
return "SSLv3/TLS read certificate status";
|
||||
case TLS_ST_CW_NEXT_PROTO:
|
||||
return "SSLv3/TLS write next proto";
|
||||
case TLS_ST_SR_NEXT_PROTO:
|
||||
return "SSLv3/TLS read next proto";
|
||||
case TLS_ST_SW_CERT_STATUS:
|
||||
return "SSLv3/TLS write certificate status";
|
||||
case TLS_ST_BEFORE:
|
||||
return "before SSL initialization";
|
||||
case TLS_ST_OK:
|
||||
return "SSL negotiation finished successfully";
|
||||
case TLS_ST_CW_CLNT_HELLO:
|
||||
return "SSLv3/TLS write client hello";
|
||||
case TLS_ST_CR_SRVR_HELLO:
|
||||
return "SSLv3/TLS read server hello";
|
||||
case TLS_ST_CR_CERT:
|
||||
return "SSLv3/TLS read server certificate";
|
||||
case TLS_ST_CR_KEY_EXCH:
|
||||
return "SSLv3/TLS read server key exchange";
|
||||
case TLS_ST_CR_CERT_REQ:
|
||||
return "SSLv3/TLS read server certificate request";
|
||||
case TLS_ST_CR_SESSION_TICKET:
|
||||
return "SSLv3/TLS read server session ticket";
|
||||
case TLS_ST_CR_SRVR_DONE:
|
||||
return "SSLv3/TLS read server done";
|
||||
case TLS_ST_CW_CERT:
|
||||
return "SSLv3/TLS write client certificate";
|
||||
case TLS_ST_CW_KEY_EXCH:
|
||||
return "SSLv3/TLS write client key exchange";
|
||||
case TLS_ST_CW_CERT_VRFY:
|
||||
return "SSLv3/TLS write certificate verify";
|
||||
case TLS_ST_CW_CHANGE:
|
||||
case TLS_ST_SW_CHANGE:
|
||||
return "SSLv3/TLS write change cipher spec";
|
||||
case TLS_ST_CW_FINISHED:
|
||||
case TLS_ST_SW_FINISHED:
|
||||
return "SSLv3/TLS write finished";
|
||||
case TLS_ST_CR_CHANGE:
|
||||
case TLS_ST_SR_CHANGE:
|
||||
return "SSLv3/TLS read change cipher spec";
|
||||
case TLS_ST_CR_FINISHED:
|
||||
case TLS_ST_SR_FINISHED:
|
||||
return "SSLv3/TLS read finished";
|
||||
case TLS_ST_SR_CLNT_HELLO:
|
||||
return "SSLv3/TLS read client hello";
|
||||
case TLS_ST_SW_HELLO_REQ:
|
||||
return "SSLv3/TLS write hello request";
|
||||
case TLS_ST_SW_SRVR_HELLO:
|
||||
return "SSLv3/TLS write server hello";
|
||||
case TLS_ST_SW_CERT:
|
||||
return "SSLv3/TLS write certificate";
|
||||
case TLS_ST_SW_KEY_EXCH:
|
||||
return "SSLv3/TLS write key exchange";
|
||||
case TLS_ST_SW_CERT_REQ:
|
||||
return "SSLv3/TLS write certificate request";
|
||||
case TLS_ST_SW_SESSION_TICKET:
|
||||
return "SSLv3/TLS write session ticket";
|
||||
case TLS_ST_SW_SRVR_DONE:
|
||||
return "SSLv3/TLS write server done";
|
||||
case TLS_ST_SR_CERT:
|
||||
return "SSLv3/TLS read client certificate";
|
||||
case TLS_ST_SR_KEY_EXCH:
|
||||
return "SSLv3/TLS read client key exchange";
|
||||
case TLS_ST_SR_CERT_VRFY:
|
||||
return "SSLv3/TLS read certificate verify";
|
||||
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
|
||||
return "DTLS1 read hello verify request";
|
||||
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
|
||||
return "DTLS1 write hello verify request";
|
||||
case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
|
||||
return "TLSv1.3 write encrypted extensions";
|
||||
case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
|
||||
return "TLSv1.3 read encrypted extensions";
|
||||
case TLS_ST_CR_CERT_VRFY:
|
||||
return "TLSv1.3 read server certificate verify";
|
||||
case TLS_ST_SW_CERT_VRFY:
|
||||
return "TLSv1.3 write server certificate verify";
|
||||
case TLS_ST_CR_HELLO_REQ:
|
||||
return "SSLv3/TLS read hello request";
|
||||
case TLS_ST_SW_KEY_UPDATE:
|
||||
return "TLSv1.3 write server key update";
|
||||
case TLS_ST_CW_KEY_UPDATE:
|
||||
return "TLSv1.3 write client key update";
|
||||
case TLS_ST_SR_KEY_UPDATE:
|
||||
return "TLSv1.3 read client key update";
|
||||
case TLS_ST_CR_KEY_UPDATE:
|
||||
return "TLSv1.3 read server key update";
|
||||
case TLS_ST_EARLY_DATA:
|
||||
return "TLSv1.3 early data";
|
||||
case TLS_ST_PENDING_EARLY_DATA_END:
|
||||
return "TLSv1.3 pending early data end";
|
||||
case TLS_ST_CW_END_OF_EARLY_DATA:
|
||||
return "TLSv1.3 write end of early data";
|
||||
case TLS_ST_SR_END_OF_EARLY_DATA:
|
||||
return "TLSv1.3 read end of early data";
|
||||
default:
|
||||
return "unknown state";
|
||||
}
|
||||
}
|
||||
|
||||
const char *SSL_state_string(const SSL *s)
|
||||
{
|
||||
if (ossl_statem_in_error(s))
|
||||
return "SSLERR";
|
||||
|
||||
switch (SSL_get_state(s)) {
|
||||
case TLS_ST_SR_NEXT_PROTO:
|
||||
return "TRNP";
|
||||
case TLS_ST_SW_SESSION_TICKET:
|
||||
return "TWST";
|
||||
case TLS_ST_SW_CERT_STATUS:
|
||||
return "TWCS";
|
||||
case TLS_ST_CR_CERT_STATUS:
|
||||
return "TRCS";
|
||||
case TLS_ST_CR_SESSION_TICKET:
|
||||
return "TRST";
|
||||
case TLS_ST_CW_NEXT_PROTO:
|
||||
return "TWNP";
|
||||
case TLS_ST_BEFORE:
|
||||
return "PINIT ";
|
||||
case TLS_ST_OK:
|
||||
return "SSLOK ";
|
||||
case TLS_ST_CW_CLNT_HELLO:
|
||||
return "TWCH";
|
||||
case TLS_ST_CR_SRVR_HELLO:
|
||||
return "TRSH";
|
||||
case TLS_ST_CR_CERT:
|
||||
return "TRSC";
|
||||
case TLS_ST_CR_KEY_EXCH:
|
||||
return "TRSKE";
|
||||
case TLS_ST_CR_CERT_REQ:
|
||||
return "TRCR";
|
||||
case TLS_ST_CR_SRVR_DONE:
|
||||
return "TRSD";
|
||||
case TLS_ST_CW_CERT:
|
||||
return "TWCC";
|
||||
case TLS_ST_CW_KEY_EXCH:
|
||||
return "TWCKE";
|
||||
case TLS_ST_CW_CERT_VRFY:
|
||||
return "TWCV";
|
||||
case TLS_ST_SW_CHANGE:
|
||||
case TLS_ST_CW_CHANGE:
|
||||
return "TWCCS";
|
||||
case TLS_ST_SW_FINISHED:
|
||||
case TLS_ST_CW_FINISHED:
|
||||
return "TWFIN";
|
||||
case TLS_ST_SR_CHANGE:
|
||||
case TLS_ST_CR_CHANGE:
|
||||
return "TRCCS";
|
||||
case TLS_ST_SR_FINISHED:
|
||||
case TLS_ST_CR_FINISHED:
|
||||
return "TRFIN";
|
||||
case TLS_ST_SW_HELLO_REQ:
|
||||
return "TWHR";
|
||||
case TLS_ST_SR_CLNT_HELLO:
|
||||
return "TRCH";
|
||||
case TLS_ST_SW_SRVR_HELLO:
|
||||
return "TWSH";
|
||||
case TLS_ST_SW_CERT:
|
||||
return "TWSC";
|
||||
case TLS_ST_SW_KEY_EXCH:
|
||||
return "TWSKE";
|
||||
case TLS_ST_SW_CERT_REQ:
|
||||
return "TWCR";
|
||||
case TLS_ST_SW_SRVR_DONE:
|
||||
return "TWSD";
|
||||
case TLS_ST_SR_CERT:
|
||||
return "TRCC";
|
||||
case TLS_ST_SR_KEY_EXCH:
|
||||
return "TRCKE";
|
||||
case TLS_ST_SR_CERT_VRFY:
|
||||
return "TRCV";
|
||||
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
|
||||
return "DRCHV";
|
||||
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
|
||||
return "DWCHV";
|
||||
case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
|
||||
return "TWEE";
|
||||
case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
|
||||
return "TREE";
|
||||
case TLS_ST_CR_CERT_VRFY:
|
||||
return "TRSCV";
|
||||
case TLS_ST_SW_CERT_VRFY:
|
||||
return "TRSCV";
|
||||
case TLS_ST_CR_HELLO_REQ:
|
||||
return "TRHR";
|
||||
case TLS_ST_SW_KEY_UPDATE:
|
||||
return "TWSKU";
|
||||
case TLS_ST_CW_KEY_UPDATE:
|
||||
return "TWCKU";
|
||||
case TLS_ST_SR_KEY_UPDATE:
|
||||
return "TRCKU";
|
||||
case TLS_ST_CR_KEY_UPDATE:
|
||||
return "TRSKU";
|
||||
case TLS_ST_EARLY_DATA:
|
||||
return "TED";
|
||||
case TLS_ST_PENDING_EARLY_DATA_END:
|
||||
return "TPEDE";
|
||||
case TLS_ST_CW_END_OF_EARLY_DATA:
|
||||
return "TWEOED";
|
||||
case TLS_ST_SR_END_OF_EARLY_DATA:
|
||||
return "TWEOED";
|
||||
default:
|
||||
return "UNKWN ";
|
||||
}
|
||||
}
|
||||
|
||||
const char *SSL_alert_type_string_long(int value)
|
||||
{
|
||||
switch (value >> 8) {
|
||||
case SSL3_AL_WARNING:
|
||||
return "warning";
|
||||
case SSL3_AL_FATAL:
|
||||
return "fatal";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char *SSL_alert_type_string(int value)
|
||||
{
|
||||
switch (value >> 8) {
|
||||
case SSL3_AL_WARNING:
|
||||
return "W";
|
||||
case SSL3_AL_FATAL:
|
||||
return "F";
|
||||
default:
|
||||
return "U";
|
||||
}
|
||||
}
|
||||
|
||||
const char *SSL_alert_desc_string(int value)
|
||||
{
|
||||
switch (value & 0xff) {
|
||||
case SSL3_AD_CLOSE_NOTIFY:
|
||||
return "CN";
|
||||
case SSL3_AD_UNEXPECTED_MESSAGE:
|
||||
return "UM";
|
||||
case SSL3_AD_BAD_RECORD_MAC:
|
||||
return "BM";
|
||||
case SSL3_AD_DECOMPRESSION_FAILURE:
|
||||
return "DF";
|
||||
case SSL3_AD_HANDSHAKE_FAILURE:
|
||||
return "HF";
|
||||
case SSL3_AD_NO_CERTIFICATE:
|
||||
return "NC";
|
||||
case SSL3_AD_BAD_CERTIFICATE:
|
||||
return "BC";
|
||||
case SSL3_AD_UNSUPPORTED_CERTIFICATE:
|
||||
return "UC";
|
||||
case SSL3_AD_CERTIFICATE_REVOKED:
|
||||
return "CR";
|
||||
case SSL3_AD_CERTIFICATE_EXPIRED:
|
||||
return "CE";
|
||||
case SSL3_AD_CERTIFICATE_UNKNOWN:
|
||||
return "CU";
|
||||
case SSL3_AD_ILLEGAL_PARAMETER:
|
||||
return "IP";
|
||||
case TLS1_AD_DECRYPTION_FAILED:
|
||||
return "DC";
|
||||
case TLS1_AD_RECORD_OVERFLOW:
|
||||
return "RO";
|
||||
case TLS1_AD_UNKNOWN_CA:
|
||||
return "CA";
|
||||
case TLS1_AD_ACCESS_DENIED:
|
||||
return "AD";
|
||||
case TLS1_AD_DECODE_ERROR:
|
||||
return "DE";
|
||||
case TLS1_AD_DECRYPT_ERROR:
|
||||
return "CY";
|
||||
case TLS1_AD_EXPORT_RESTRICTION:
|
||||
return "ER";
|
||||
case TLS1_AD_PROTOCOL_VERSION:
|
||||
return "PV";
|
||||
case TLS1_AD_INSUFFICIENT_SECURITY:
|
||||
return "IS";
|
||||
case TLS1_AD_INTERNAL_ERROR:
|
||||
return "IE";
|
||||
case TLS1_AD_USER_CANCELLED:
|
||||
return "US";
|
||||
case TLS1_AD_NO_RENEGOTIATION:
|
||||
return "NR";
|
||||
case TLS1_AD_UNSUPPORTED_EXTENSION:
|
||||
return "UE";
|
||||
case TLS1_AD_CERTIFICATE_UNOBTAINABLE:
|
||||
return "CO";
|
||||
case TLS1_AD_UNRECOGNIZED_NAME:
|
||||
return "UN";
|
||||
case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
|
||||
return "BR";
|
||||
case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE:
|
||||
return "BH";
|
||||
case TLS1_AD_UNKNOWN_PSK_IDENTITY:
|
||||
return "UP";
|
||||
default:
|
||||
return "UK";
|
||||
}
|
||||
}
|
||||
|
||||
const char *SSL_alert_desc_string_long(int value)
|
||||
{
|
||||
switch (value & 0xff) {
|
||||
case SSL3_AD_CLOSE_NOTIFY:
|
||||
return "close notify";
|
||||
case SSL3_AD_UNEXPECTED_MESSAGE:
|
||||
return "unexpected_message";
|
||||
case SSL3_AD_BAD_RECORD_MAC:
|
||||
return "bad record mac";
|
||||
case SSL3_AD_DECOMPRESSION_FAILURE:
|
||||
return "decompression failure";
|
||||
case SSL3_AD_HANDSHAKE_FAILURE:
|
||||
return "handshake failure";
|
||||
case SSL3_AD_NO_CERTIFICATE:
|
||||
return "no certificate";
|
||||
case SSL3_AD_BAD_CERTIFICATE:
|
||||
return "bad certificate";
|
||||
case SSL3_AD_UNSUPPORTED_CERTIFICATE:
|
||||
return "unsupported certificate";
|
||||
case SSL3_AD_CERTIFICATE_REVOKED:
|
||||
return "certificate revoked";
|
||||
case SSL3_AD_CERTIFICATE_EXPIRED:
|
||||
return "certificate expired";
|
||||
case SSL3_AD_CERTIFICATE_UNKNOWN:
|
||||
return "certificate unknown";
|
||||
case SSL3_AD_ILLEGAL_PARAMETER:
|
||||
return "illegal parameter";
|
||||
case TLS1_AD_DECRYPTION_FAILED:
|
||||
return "decryption failed";
|
||||
case TLS1_AD_RECORD_OVERFLOW:
|
||||
return "record overflow";
|
||||
case TLS1_AD_UNKNOWN_CA:
|
||||
return "unknown CA";
|
||||
case TLS1_AD_ACCESS_DENIED:
|
||||
return "access denied";
|
||||
case TLS1_AD_DECODE_ERROR:
|
||||
return "decode error";
|
||||
case TLS1_AD_DECRYPT_ERROR:
|
||||
return "decrypt error";
|
||||
case TLS1_AD_EXPORT_RESTRICTION:
|
||||
return "export restriction";
|
||||
case TLS1_AD_PROTOCOL_VERSION:
|
||||
return "protocol version";
|
||||
case TLS1_AD_INSUFFICIENT_SECURITY:
|
||||
return "insufficient security";
|
||||
case TLS1_AD_INTERNAL_ERROR:
|
||||
return "internal error";
|
||||
case TLS1_AD_USER_CANCELLED:
|
||||
return "user canceled";
|
||||
case TLS1_AD_NO_RENEGOTIATION:
|
||||
return "no renegotiation";
|
||||
case TLS1_AD_UNSUPPORTED_EXTENSION:
|
||||
return "unsupported extension";
|
||||
case TLS1_AD_CERTIFICATE_UNOBTAINABLE:
|
||||
return "certificate unobtainable";
|
||||
case TLS1_AD_UNRECOGNIZED_NAME:
|
||||
return "unrecognized name";
|
||||
case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
|
||||
return "bad certificate status response";
|
||||
case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE:
|
||||
return "bad certificate hash value";
|
||||
case TLS1_AD_UNKNOWN_PSK_IDENTITY:
|
||||
return "unknown PSK identity";
|
||||
case TLS1_AD_NO_APPLICATION_PROTOCOL:
|
||||
return "no application protocol";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
203
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_txt.c
vendored
Normal file
203
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_txt.c
vendored
Normal file
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2005 Nokia. All rights reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include "ssl_locl.h"
|
||||
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *x)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
SSLerr(SSL_F_SSL_SESSION_PRINT_FP, ERR_R_BUF_LIB);
|
||||
return 0;
|
||||
}
|
||||
BIO_set_fp(b, fp, BIO_NOCLOSE);
|
||||
ret = SSL_SESSION_print(b, x);
|
||||
BIO_free(b);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
|
||||
{
|
||||
size_t i;
|
||||
const char *s;
|
||||
int istls13;
|
||||
|
||||
if (x == NULL)
|
||||
goto err;
|
||||
istls13 = (x->ssl_version == TLS1_3_VERSION);
|
||||
if (BIO_puts(bp, "SSL-Session:\n") <= 0)
|
||||
goto err;
|
||||
s = ssl_protocol_to_string(x->ssl_version);
|
||||
if (BIO_printf(bp, " Protocol : %s\n", s) <= 0)
|
||||
goto err;
|
||||
|
||||
if (x->cipher == NULL) {
|
||||
if (((x->cipher_id) & 0xff000000) == 0x02000000) {
|
||||
if (BIO_printf(bp, " Cipher : %06lX\n",
|
||||
x->cipher_id & 0xffffff) <= 0)
|
||||
goto err;
|
||||
} else {
|
||||
if (BIO_printf(bp, " Cipher : %04lX\n",
|
||||
x->cipher_id & 0xffff) <= 0)
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (BIO_printf(bp, " Cipher : %s\n",
|
||||
((x->cipher->name == NULL) ? "unknown"
|
||||
: x->cipher->name)) <= 0)
|
||||
goto err;
|
||||
}
|
||||
if (BIO_puts(bp, " Session-ID: ") <= 0)
|
||||
goto err;
|
||||
for (i = 0; i < x->session_id_length; i++) {
|
||||
if (BIO_printf(bp, "%02X", x->session_id[i]) <= 0)
|
||||
goto err;
|
||||
}
|
||||
if (BIO_puts(bp, "\n Session-ID-ctx: ") <= 0)
|
||||
goto err;
|
||||
for (i = 0; i < x->sid_ctx_length; i++) {
|
||||
if (BIO_printf(bp, "%02X", x->sid_ctx[i]) <= 0)
|
||||
goto err;
|
||||
}
|
||||
if (istls13) {
|
||||
if (BIO_puts(bp, "\n Resumption PSK: ") <= 0)
|
||||
goto err;
|
||||
} else if (BIO_puts(bp, "\n Master-Key: ") <= 0)
|
||||
goto err;
|
||||
for (i = 0; i < x->master_key_length; i++) {
|
||||
if (BIO_printf(bp, "%02X", x->master_key[i]) <= 0)
|
||||
goto err;
|
||||
}
|
||||
#ifndef OPENSSL_NO_PSK
|
||||
if (BIO_puts(bp, "\n PSK identity: ") <= 0)
|
||||
goto err;
|
||||
if (BIO_printf(bp, "%s", x->psk_identity ? x->psk_identity : "None") <= 0)
|
||||
goto err;
|
||||
if (BIO_puts(bp, "\n PSK identity hint: ") <= 0)
|
||||
goto err;
|
||||
if (BIO_printf
|
||||
(bp, "%s", x->psk_identity_hint ? x->psk_identity_hint : "None") <= 0)
|
||||
goto err;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
if (BIO_puts(bp, "\n SRP username: ") <= 0)
|
||||
goto err;
|
||||
if (BIO_printf(bp, "%s", x->srp_username ? x->srp_username : "None") <= 0)
|
||||
goto err;
|
||||
#endif
|
||||
if (x->ext.tick_lifetime_hint) {
|
||||
if (BIO_printf(bp,
|
||||
"\n TLS session ticket lifetime hint: %ld (seconds)",
|
||||
x->ext.tick_lifetime_hint) <= 0)
|
||||
goto err;
|
||||
}
|
||||
if (x->ext.tick) {
|
||||
if (BIO_puts(bp, "\n TLS session ticket:\n") <= 0)
|
||||
goto err;
|
||||
/* TODO(size_t): Convert this call */
|
||||
if (BIO_dump_indent
|
||||
(bp, (const char *)x->ext.tick, (int)x->ext.ticklen, 4)
|
||||
<= 0)
|
||||
goto err;
|
||||
}
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
if (x->compress_meth != 0) {
|
||||
SSL_COMP *comp = NULL;
|
||||
|
||||
if (!ssl_cipher_get_evp(x, NULL, NULL, NULL, NULL, &comp, 0))
|
||||
goto err;
|
||||
if (comp == NULL) {
|
||||
if (BIO_printf(bp, "\n Compression: %d", x->compress_meth) <= 0)
|
||||
goto err;
|
||||
} else {
|
||||
if (BIO_printf(bp, "\n Compression: %d (%s)", comp->id,
|
||||
comp->name) <= 0)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (x->time != 0L) {
|
||||
if (BIO_printf(bp, "\n Start Time: %ld", x->time) <= 0)
|
||||
goto err;
|
||||
}
|
||||
if (x->timeout != 0L) {
|
||||
if (BIO_printf(bp, "\n Timeout : %ld (sec)", x->timeout) <= 0)
|
||||
goto err;
|
||||
}
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto err;
|
||||
|
||||
if (BIO_puts(bp, " Verify return code: ") <= 0)
|
||||
goto err;
|
||||
if (BIO_printf(bp, "%ld (%s)\n", x->verify_result,
|
||||
X509_verify_cert_error_string(x->verify_result)) <= 0)
|
||||
goto err;
|
||||
|
||||
if (BIO_printf(bp, " Extended master secret: %s\n",
|
||||
x->flags & SSL_SESS_FLAG_EXTMS ? "yes" : "no") <= 0)
|
||||
goto err;
|
||||
|
||||
if (istls13) {
|
||||
if (BIO_printf(bp, " Max Early Data: %u\n",
|
||||
x->ext.max_early_data) <= 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 1;
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* print session id and master key in NSS keylog format (RSA
|
||||
* Session-ID:<session id> Master-Key:<master key>)
|
||||
*/
|
||||
int SSL_SESSION_print_keylog(BIO *bp, const SSL_SESSION *x)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (x == NULL)
|
||||
goto err;
|
||||
if (x->session_id_length == 0 || x->master_key_length == 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* the RSA prefix is required by the format's definition although there's
|
||||
* nothing RSA-specific in the output, therefore, we don't have to check if
|
||||
* the cipher suite is based on RSA
|
||||
*/
|
||||
if (BIO_puts(bp, "RSA ") <= 0)
|
||||
goto err;
|
||||
|
||||
if (BIO_puts(bp, "Session-ID:") <= 0)
|
||||
goto err;
|
||||
for (i = 0; i < x->session_id_length; i++) {
|
||||
if (BIO_printf(bp, "%02X", x->session_id[i]) <= 0)
|
||||
goto err;
|
||||
}
|
||||
if (BIO_puts(bp, " Master-Key:") <= 0)
|
||||
goto err;
|
||||
for (i = 0; i < x->master_key_length; i++) {
|
||||
if (BIO_printf(bp, "%02X", x->master_key[i]) <= 0)
|
||||
goto err;
|
||||
}
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto err;
|
||||
|
||||
return 1;
|
||||
err:
|
||||
return 0;
|
||||
}
|
24
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_utst.c
vendored
Normal file
24
trunk/3rdparty/openssl-1.1-fit/ssl/ssl_utst.c
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "ssl_locl.h"
|
||||
|
||||
#ifndef OPENSSL_NO_UNIT_TEST
|
||||
|
||||
static const struct openssl_ssl_test_functions ssl_test_functions = {
|
||||
ssl_init_wbio_buffer,
|
||||
ssl3_setup_buffers,
|
||||
};
|
||||
|
||||
const struct openssl_ssl_test_functions *SSL_test_functions(void)
|
||||
{
|
||||
return &ssl_test_functions;
|
||||
}
|
||||
|
||||
#endif
|
63
trunk/3rdparty/openssl-1.1-fit/ssl/statem/README
vendored
Normal file
63
trunk/3rdparty/openssl-1.1-fit/ssl/statem/README
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
State Machine Design
|
||||
====================
|
||||
|
||||
This file provides some guidance on the thinking behind the design of the
|
||||
state machine code to aid future maintenance.
|
||||
|
||||
The state machine code replaces an older state machine present in OpenSSL
|
||||
versions 1.0.2 and below. The new state machine has the following objectives:
|
||||
- Remove duplication of state code between client and server
|
||||
- Remove duplication of state code between TLS and DTLS
|
||||
- Simplify transitions and bring the logic together in a single location
|
||||
so that it is easier to validate
|
||||
- Remove duplication of code between each of the message handling functions
|
||||
- Receive a message first and then work out whether that is a valid
|
||||
transition - not the other way around (the other way causes lots of issues
|
||||
where we are expecting one type of message next but actually get something
|
||||
else)
|
||||
- Separate message flow state from handshake state (in order to better
|
||||
understand each)
|
||||
- message flow state = when to flush buffers; handling restarts in the
|
||||
event of NBIO events; handling the common flow of steps for reading a
|
||||
message and the common flow of steps for writing a message etc
|
||||
- handshake state = what handshake message are we working on now
|
||||
- Control complexity: only the state machine can change state: keep all
|
||||
the state changes local to the state machine component
|
||||
|
||||
The message flow state machine is divided into a reading sub-state machine and a
|
||||
writing sub-state machine. See the source comments in statem.c for a more
|
||||
detailed description of the various states and transitions possible.
|
||||
|
||||
Conceptually the state machine component is designed as follows:
|
||||
|
||||
libssl
|
||||
|
|
||||
---------------------------|-----statem.h--------------------------------------
|
||||
|
|
||||
_______V____________________
|
||||
| |
|
||||
| statem.c |
|
||||
| |
|
||||
| Core state machine code |
|
||||
|____________________________|
|
||||
statem_locl.h ^ ^
|
||||
_________| |_______
|
||||
| |
|
||||
_____________|____________ _____________|____________
|
||||
| | | |
|
||||
| statem_clnt.c | | statem_srvr.c |
|
||||
| | | |
|
||||
| TLS/DTLS client specific | | TLS/DTLS server specific |
|
||||
| state machine code | | state machine code |
|
||||
|__________________________| |__________________________|
|
||||
| |_______________|__ |
|
||||
| ________________| | |
|
||||
| | | |
|
||||
____________V_______V________ ________V______V_______________
|
||||
| | | |
|
||||
| statem_both.c | | statem_dtls.c |
|
||||
| | | |
|
||||
| Non core functions common | | Non core functions common to |
|
||||
| to both servers and clients | | both DTLS servers and clients |
|
||||
|_____________________________| |_______________________________|
|
||||
|
1700
trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions.c
vendored
Normal file
1700
trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
1991
trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_clnt.c
vendored
Normal file
1991
trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_clnt.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
533
trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_cust.c
vendored
Normal file
533
trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_cust.c
vendored
Normal file
|
@ -0,0 +1,533 @@
|
|||
/*
|
||||
* Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* Custom extension utility functions */
|
||||
|
||||
#include <openssl/ct.h>
|
||||
#include "../ssl_locl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include "statem_locl.h"
|
||||
|
||||
typedef struct {
|
||||
void *add_arg;
|
||||
custom_ext_add_cb add_cb;
|
||||
custom_ext_free_cb free_cb;
|
||||
} custom_ext_add_cb_wrap;
|
||||
|
||||
typedef struct {
|
||||
void *parse_arg;
|
||||
custom_ext_parse_cb parse_cb;
|
||||
} custom_ext_parse_cb_wrap;
|
||||
|
||||
/*
|
||||
* Provide thin wrapper callbacks which convert new style arguments to old style
|
||||
*/
|
||||
static int custom_ext_add_old_cb_wrap(SSL *s, unsigned int ext_type,
|
||||
unsigned int context,
|
||||
const unsigned char **out,
|
||||
size_t *outlen, X509 *x, size_t chainidx,
|
||||
int *al, void *add_arg)
|
||||
{
|
||||
custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg;
|
||||
|
||||
if (add_cb_wrap->add_cb == NULL)
|
||||
return 1;
|
||||
|
||||
return add_cb_wrap->add_cb(s, ext_type, out, outlen, al,
|
||||
add_cb_wrap->add_arg);
|
||||
}
|
||||
|
||||
static void custom_ext_free_old_cb_wrap(SSL *s, unsigned int ext_type,
|
||||
unsigned int context,
|
||||
const unsigned char *out, void *add_arg)
|
||||
{
|
||||
custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg;
|
||||
|
||||
if (add_cb_wrap->free_cb == NULL)
|
||||
return;
|
||||
|
||||
add_cb_wrap->free_cb(s, ext_type, out, add_cb_wrap->add_arg);
|
||||
}
|
||||
|
||||
static int custom_ext_parse_old_cb_wrap(SSL *s, unsigned int ext_type,
|
||||
unsigned int context,
|
||||
const unsigned char *in,
|
||||
size_t inlen, X509 *x, size_t chainidx,
|
||||
int *al, void *parse_arg)
|
||||
{
|
||||
custom_ext_parse_cb_wrap *parse_cb_wrap =
|
||||
(custom_ext_parse_cb_wrap *)parse_arg;
|
||||
|
||||
if (parse_cb_wrap->parse_cb == NULL)
|
||||
return 1;
|
||||
|
||||
return parse_cb_wrap->parse_cb(s, ext_type, in, inlen, al,
|
||||
parse_cb_wrap->parse_arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a custom extension from the list. The |role| param is there to
|
||||
* support the legacy API where custom extensions for client and server could
|
||||
* be set independently on the same SSL_CTX. It is set to ENDPOINT_SERVER if we
|
||||
* are trying to find a method relevant to the server, ENDPOINT_CLIENT for the
|
||||
* client, or ENDPOINT_BOTH for either
|
||||
*/
|
||||
custom_ext_method *custom_ext_find(const custom_ext_methods *exts,
|
||||
ENDPOINT role, unsigned int ext_type,
|
||||
size_t *idx)
|
||||
{
|
||||
size_t i;
|
||||
custom_ext_method *meth = exts->meths;
|
||||
|
||||
for (i = 0; i < exts->meths_count; i++, meth++) {
|
||||
if (ext_type == meth->ext_type
|
||||
&& (role == ENDPOINT_BOTH || role == meth->role
|
||||
|| meth->role == ENDPOINT_BOTH)) {
|
||||
if (idx != NULL)
|
||||
*idx = i;
|
||||
return meth;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise custom extensions flags to indicate neither sent nor received.
|
||||
*/
|
||||
void custom_ext_init(custom_ext_methods *exts)
|
||||
{
|
||||
size_t i;
|
||||
custom_ext_method *meth = exts->meths;
|
||||
|
||||
for (i = 0; i < exts->meths_count; i++, meth++)
|
||||
meth->ext_flags = 0;
|
||||
}
|
||||
|
||||
/* Pass received custom extension data to the application for parsing. */
|
||||
int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type,
|
||||
const unsigned char *ext_data, size_t ext_size, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
int al;
|
||||
custom_ext_methods *exts = &s->cert->custext;
|
||||
custom_ext_method *meth;
|
||||
ENDPOINT role = ENDPOINT_BOTH;
|
||||
|
||||
if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0)
|
||||
role = s->server ? ENDPOINT_SERVER : ENDPOINT_CLIENT;
|
||||
|
||||
meth = custom_ext_find(exts, role, ext_type, NULL);
|
||||
/* If not found return success */
|
||||
if (!meth)
|
||||
return 1;
|
||||
|
||||
/* Check if extension is defined for our protocol. If not, skip */
|
||||
if (!extension_is_relevant(s, meth->context, context))
|
||||
return 1;
|
||||
|
||||
if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS)) != 0) {
|
||||
/*
|
||||
* If it's ServerHello or EncryptedExtensions we can't have any
|
||||
* extensions not sent in ClientHello.
|
||||
*/
|
||||
if ((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0) {
|
||||
SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_CUSTOM_EXT_PARSE,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Extensions received in the ClientHello are marked with the
|
||||
* SSL_EXT_FLAG_RECEIVED. This is so we know to add the equivalent
|
||||
* extensions in the ServerHello/EncryptedExtensions message
|
||||
*/
|
||||
if ((context & SSL_EXT_CLIENT_HELLO) != 0)
|
||||
meth->ext_flags |= SSL_EXT_FLAG_RECEIVED;
|
||||
|
||||
/* If no parse function set return success */
|
||||
if (!meth->parse_cb)
|
||||
return 1;
|
||||
|
||||
if (meth->parse_cb(s, ext_type, context, ext_data, ext_size, x, chainidx,
|
||||
&al, meth->parse_arg) <= 0) {
|
||||
SSLfatal(s, al, SSL_F_CUSTOM_EXT_PARSE, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Request custom extension data from the application and add to the return
|
||||
* buffer.
|
||||
*/
|
||||
int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
|
||||
int maxversion)
|
||||
{
|
||||
custom_ext_methods *exts = &s->cert->custext;
|
||||
custom_ext_method *meth;
|
||||
size_t i;
|
||||
int al;
|
||||
|
||||
for (i = 0; i < exts->meths_count; i++) {
|
||||
const unsigned char *out = NULL;
|
||||
size_t outlen = 0;
|
||||
|
||||
meth = exts->meths + i;
|
||||
|
||||
if (!should_add_extension(s, meth->context, context, maxversion))
|
||||
continue;
|
||||
|
||||
if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
|
||||
| SSL_EXT_TLS1_3_CERTIFICATE
|
||||
| SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)) != 0) {
|
||||
/* Only send extensions present in ClientHello. */
|
||||
if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED))
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* We skip it if the callback is absent - except for a ClientHello where
|
||||
* we add an empty extension.
|
||||
*/
|
||||
if ((context & SSL_EXT_CLIENT_HELLO) == 0 && meth->add_cb == NULL)
|
||||
continue;
|
||||
|
||||
if (meth->add_cb != NULL) {
|
||||
int cb_retval = meth->add_cb(s, meth->ext_type, context, &out,
|
||||
&outlen, x, chainidx, &al,
|
||||
meth->add_arg);
|
||||
|
||||
if (cb_retval < 0) {
|
||||
SSLfatal(s, al, SSL_F_CUSTOM_EXT_ADD, SSL_R_CALLBACK_FAILED);
|
||||
return 0; /* error */
|
||||
}
|
||||
if (cb_retval == 0)
|
||||
continue; /* skip this extension */
|
||||
}
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, meth->ext_type)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| (outlen > 0 && !WPACKET_memcpy(pkt, out, outlen))
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
|
||||
/*
|
||||
* We can't send duplicates: code logic should prevent this.
|
||||
*/
|
||||
if (!ossl_assert((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Indicate extension has been sent: this is both a sanity check to
|
||||
* ensure we don't send duplicate extensions and indicates that it
|
||||
* is not an error if the extension is present in ServerHello.
|
||||
*/
|
||||
meth->ext_flags |= SSL_EXT_FLAG_SENT;
|
||||
}
|
||||
if (meth->free_cb != NULL)
|
||||
meth->free_cb(s, meth->ext_type, context, out, meth->add_arg);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy the flags from src to dst for any extensions that exist in both */
|
||||
int custom_exts_copy_flags(custom_ext_methods *dst,
|
||||
const custom_ext_methods *src)
|
||||
{
|
||||
size_t i;
|
||||
custom_ext_method *methsrc = src->meths;
|
||||
|
||||
for (i = 0; i < src->meths_count; i++, methsrc++) {
|
||||
custom_ext_method *methdst = custom_ext_find(dst, methsrc->role,
|
||||
methsrc->ext_type, NULL);
|
||||
|
||||
if (methdst == NULL)
|
||||
continue;
|
||||
|
||||
methdst->ext_flags = methsrc->ext_flags;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy table of custom extensions */
|
||||
int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src)
|
||||
{
|
||||
size_t i;
|
||||
int err = 0;
|
||||
|
||||
if (src->meths_count > 0) {
|
||||
dst->meths =
|
||||
OPENSSL_memdup(src->meths,
|
||||
sizeof(*src->meths) * src->meths_count);
|
||||
if (dst->meths == NULL)
|
||||
return 0;
|
||||
dst->meths_count = src->meths_count;
|
||||
|
||||
for (i = 0; i < src->meths_count; i++) {
|
||||
custom_ext_method *methsrc = src->meths + i;
|
||||
custom_ext_method *methdst = dst->meths + i;
|
||||
|
||||
if (methsrc->add_cb != custom_ext_add_old_cb_wrap)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* We have found an old style API wrapper. We need to copy the
|
||||
* arguments too.
|
||||
*/
|
||||
|
||||
if (err) {
|
||||
methdst->add_arg = NULL;
|
||||
methdst->parse_arg = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
methdst->add_arg = OPENSSL_memdup(methsrc->add_arg,
|
||||
sizeof(custom_ext_add_cb_wrap));
|
||||
methdst->parse_arg = OPENSSL_memdup(methsrc->parse_arg,
|
||||
sizeof(custom_ext_parse_cb_wrap));
|
||||
|
||||
if (methdst->add_arg == NULL || methdst->parse_arg == NULL)
|
||||
err = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (err) {
|
||||
custom_exts_free(dst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void custom_exts_free(custom_ext_methods *exts)
|
||||
{
|
||||
size_t i;
|
||||
custom_ext_method *meth;
|
||||
|
||||
for (i = 0, meth = exts->meths; i < exts->meths_count; i++, meth++) {
|
||||
if (meth->add_cb != custom_ext_add_old_cb_wrap)
|
||||
continue;
|
||||
|
||||
/* Old style API wrapper. Need to free the arguments too */
|
||||
OPENSSL_free(meth->add_arg);
|
||||
OPENSSL_free(meth->parse_arg);
|
||||
}
|
||||
OPENSSL_free(exts->meths);
|
||||
}
|
||||
|
||||
/* Return true if a client custom extension exists, false otherwise */
|
||||
int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx, unsigned int ext_type)
|
||||
{
|
||||
return custom_ext_find(&ctx->cert->custext, ENDPOINT_CLIENT, ext_type,
|
||||
NULL) != NULL;
|
||||
}
|
||||
|
||||
static int add_custom_ext_intern(SSL_CTX *ctx, ENDPOINT role,
|
||||
unsigned int ext_type,
|
||||
unsigned int context,
|
||||
SSL_custom_ext_add_cb_ex add_cb,
|
||||
SSL_custom_ext_free_cb_ex free_cb,
|
||||
void *add_arg,
|
||||
SSL_custom_ext_parse_cb_ex parse_cb,
|
||||
void *parse_arg)
|
||||
{
|
||||
custom_ext_methods *exts = &ctx->cert->custext;
|
||||
custom_ext_method *meth, *tmp;
|
||||
|
||||
/*
|
||||
* Check application error: if add_cb is not set free_cb will never be
|
||||
* called.
|
||||
*/
|
||||
if (add_cb == NULL && free_cb != NULL)
|
||||
return 0;
|
||||
|
||||
#ifndef OPENSSL_NO_CT
|
||||
/*
|
||||
* We don't want applications registering callbacks for SCT extensions
|
||||
* whilst simultaneously using the built-in SCT validation features, as
|
||||
* these two things may not play well together.
|
||||
*/
|
||||
if (ext_type == TLSEXT_TYPE_signed_certificate_timestamp
|
||||
&& (context & SSL_EXT_CLIENT_HELLO) != 0
|
||||
&& SSL_CTX_ct_is_enabled(ctx))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Don't add if extension supported internally, but make exception
|
||||
* for extension types that previously were not supported, but now are.
|
||||
*/
|
||||
if (SSL_extension_supported(ext_type)
|
||||
&& ext_type != TLSEXT_TYPE_signed_certificate_timestamp)
|
||||
return 0;
|
||||
|
||||
/* Extension type must fit in 16 bits */
|
||||
if (ext_type > 0xffff)
|
||||
return 0;
|
||||
/* Search for duplicate */
|
||||
if (custom_ext_find(exts, role, ext_type, NULL))
|
||||
return 0;
|
||||
tmp = OPENSSL_realloc(exts->meths,
|
||||
(exts->meths_count + 1) * sizeof(custom_ext_method));
|
||||
if (tmp == NULL)
|
||||
return 0;
|
||||
|
||||
exts->meths = tmp;
|
||||
meth = exts->meths + exts->meths_count;
|
||||
memset(meth, 0, sizeof(*meth));
|
||||
meth->role = role;
|
||||
meth->context = context;
|
||||
meth->parse_cb = parse_cb;
|
||||
meth->add_cb = add_cb;
|
||||
meth->free_cb = free_cb;
|
||||
meth->ext_type = ext_type;
|
||||
meth->add_arg = add_arg;
|
||||
meth->parse_arg = parse_arg;
|
||||
exts->meths_count++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int add_old_custom_ext(SSL_CTX *ctx, ENDPOINT role,
|
||||
unsigned int ext_type,
|
||||
unsigned int context,
|
||||
custom_ext_add_cb add_cb,
|
||||
custom_ext_free_cb free_cb,
|
||||
void *add_arg,
|
||||
custom_ext_parse_cb parse_cb, void *parse_arg)
|
||||
{
|
||||
custom_ext_add_cb_wrap *add_cb_wrap
|
||||
= OPENSSL_malloc(sizeof(*add_cb_wrap));
|
||||
custom_ext_parse_cb_wrap *parse_cb_wrap
|
||||
= OPENSSL_malloc(sizeof(*parse_cb_wrap));
|
||||
int ret;
|
||||
|
||||
if (add_cb_wrap == NULL || parse_cb_wrap == NULL) {
|
||||
OPENSSL_free(add_cb_wrap);
|
||||
OPENSSL_free(parse_cb_wrap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
add_cb_wrap->add_arg = add_arg;
|
||||
add_cb_wrap->add_cb = add_cb;
|
||||
add_cb_wrap->free_cb = free_cb;
|
||||
parse_cb_wrap->parse_arg = parse_arg;
|
||||
parse_cb_wrap->parse_cb = parse_cb;
|
||||
|
||||
ret = add_custom_ext_intern(ctx, role, ext_type,
|
||||
context,
|
||||
custom_ext_add_old_cb_wrap,
|
||||
custom_ext_free_old_cb_wrap,
|
||||
add_cb_wrap,
|
||||
custom_ext_parse_old_cb_wrap,
|
||||
parse_cb_wrap);
|
||||
|
||||
if (!ret) {
|
||||
OPENSSL_free(add_cb_wrap);
|
||||
OPENSSL_free(parse_cb_wrap);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Application level functions to add the old custom extension callbacks */
|
||||
int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
|
||||
custom_ext_add_cb add_cb,
|
||||
custom_ext_free_cb free_cb,
|
||||
void *add_arg,
|
||||
custom_ext_parse_cb parse_cb, void *parse_arg)
|
||||
{
|
||||
return add_old_custom_ext(ctx, ENDPOINT_CLIENT, ext_type,
|
||||
SSL_EXT_TLS1_2_AND_BELOW_ONLY
|
||||
| SSL_EXT_CLIENT_HELLO
|
||||
| SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_IGNORE_ON_RESUMPTION,
|
||||
add_cb, free_cb, add_arg, parse_cb, parse_arg);
|
||||
}
|
||||
|
||||
int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
|
||||
custom_ext_add_cb add_cb,
|
||||
custom_ext_free_cb free_cb,
|
||||
void *add_arg,
|
||||
custom_ext_parse_cb parse_cb, void *parse_arg)
|
||||
{
|
||||
return add_old_custom_ext(ctx, ENDPOINT_SERVER, ext_type,
|
||||
SSL_EXT_TLS1_2_AND_BELOW_ONLY
|
||||
| SSL_EXT_CLIENT_HELLO
|
||||
| SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_IGNORE_ON_RESUMPTION,
|
||||
add_cb, free_cb, add_arg, parse_cb, parse_arg);
|
||||
}
|
||||
|
||||
int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
|
||||
unsigned int context,
|
||||
SSL_custom_ext_add_cb_ex add_cb,
|
||||
SSL_custom_ext_free_cb_ex free_cb,
|
||||
void *add_arg,
|
||||
SSL_custom_ext_parse_cb_ex parse_cb, void *parse_arg)
|
||||
{
|
||||
return add_custom_ext_intern(ctx, ENDPOINT_BOTH, ext_type, context, add_cb,
|
||||
free_cb, add_arg, parse_cb, parse_arg);
|
||||
}
|
||||
|
||||
int SSL_extension_supported(unsigned int ext_type)
|
||||
{
|
||||
switch (ext_type) {
|
||||
/* Internally supported extensions. */
|
||||
case TLSEXT_TYPE_application_layer_protocol_negotiation:
|
||||
#ifndef OPENSSL_NO_EC
|
||||
case TLSEXT_TYPE_ec_point_formats:
|
||||
case TLSEXT_TYPE_supported_groups:
|
||||
case TLSEXT_TYPE_key_share:
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
case TLSEXT_TYPE_next_proto_neg:
|
||||
#endif
|
||||
case TLSEXT_TYPE_padding:
|
||||
case TLSEXT_TYPE_renegotiate:
|
||||
case TLSEXT_TYPE_max_fragment_length:
|
||||
case TLSEXT_TYPE_server_name:
|
||||
case TLSEXT_TYPE_session_ticket:
|
||||
case TLSEXT_TYPE_signature_algorithms:
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
case TLSEXT_TYPE_srp:
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
case TLSEXT_TYPE_status_request:
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_CT
|
||||
case TLSEXT_TYPE_signed_certificate_timestamp:
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
case TLSEXT_TYPE_use_srtp:
|
||||
#endif
|
||||
case TLSEXT_TYPE_encrypt_then_mac:
|
||||
case TLSEXT_TYPE_supported_versions:
|
||||
case TLSEXT_TYPE_extended_master_secret:
|
||||
case TLSEXT_TYPE_psk_kex_modes:
|
||||
case TLSEXT_TYPE_cookie:
|
||||
case TLSEXT_TYPE_early_data:
|
||||
case TLSEXT_TYPE_certificate_authorities:
|
||||
case TLSEXT_TYPE_psk:
|
||||
case TLSEXT_TYPE_post_handshake_auth:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
1959
trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_srvr.c
vendored
Normal file
1959
trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_srvr.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
972
trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem.c
vendored
Normal file
972
trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem.c
vendored
Normal file
|
@ -0,0 +1,972 @@
|
|||
/*
|
||||
* Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/rand.h>
|
||||
#include "../ssl_locl.h"
|
||||
#include "statem_locl.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* This file implements the SSL/TLS/DTLS state machines.
|
||||
*
|
||||
* There are two primary state machines:
|
||||
*
|
||||
* 1) Message flow state machine
|
||||
* 2) Handshake state machine
|
||||
*
|
||||
* The Message flow state machine controls the reading and sending of messages
|
||||
* including handling of non-blocking IO events, flushing of the underlying
|
||||
* write BIO, handling unexpected messages, etc. It is itself broken into two
|
||||
* separate sub-state machines which control reading and writing respectively.
|
||||
*
|
||||
* The Handshake state machine keeps track of the current SSL/TLS handshake
|
||||
* state. Transitions of the handshake state are the result of events that
|
||||
* occur within the Message flow state machine.
|
||||
*
|
||||
* Overall it looks like this:
|
||||
*
|
||||
* --------------------------------------------- -------------------
|
||||
* | | | |
|
||||
* | Message flow state machine | | |
|
||||
* | | | |
|
||||
* | -------------------- -------------------- | Transition | Handshake state |
|
||||
* | | MSG_FLOW_READING | | MSG_FLOW_WRITING | | Event | machine |
|
||||
* | | sub-state | | sub-state | |----------->| |
|
||||
* | | machine for | | machine for | | | |
|
||||
* | | reading messages | | writing messages | | | |
|
||||
* | -------------------- -------------------- | | |
|
||||
* | | | |
|
||||
* --------------------------------------------- -------------------
|
||||
*
|
||||
*/
|
||||
|
||||
/* Sub state machine return values */
|
||||
typedef enum {
|
||||
/* Something bad happened or NBIO */
|
||||
SUB_STATE_ERROR,
|
||||
/* Sub state finished go to the next sub state */
|
||||
SUB_STATE_FINISHED,
|
||||
/* Sub state finished and handshake was completed */
|
||||
SUB_STATE_END_HANDSHAKE
|
||||
} SUB_STATE_RETURN;
|
||||
|
||||
static int state_machine(SSL *s, int server);
|
||||
static void init_read_state_machine(SSL *s);
|
||||
static SUB_STATE_RETURN read_state_machine(SSL *s);
|
||||
static void init_write_state_machine(SSL *s);
|
||||
static SUB_STATE_RETURN write_state_machine(SSL *s);
|
||||
|
||||
OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl)
|
||||
{
|
||||
return ssl->statem.hand_state;
|
||||
}
|
||||
|
||||
int SSL_in_init(const SSL *s)
|
||||
{
|
||||
return s->statem.in_init;
|
||||
}
|
||||
|
||||
int SSL_is_init_finished(const SSL *s)
|
||||
{
|
||||
return !(s->statem.in_init) && (s->statem.hand_state == TLS_ST_OK);
|
||||
}
|
||||
|
||||
int SSL_in_before(const SSL *s)
|
||||
{
|
||||
/*
|
||||
* Historically being "in before" meant before anything had happened. In the
|
||||
* current code though we remain in the "before" state for a while after we
|
||||
* have started the handshake process (e.g. as a server waiting for the
|
||||
* first message to arrive). There "in before" is taken to mean "in before"
|
||||
* and not started any handshake process yet.
|
||||
*/
|
||||
return (s->statem.hand_state == TLS_ST_BEFORE)
|
||||
&& (s->statem.state == MSG_FLOW_UNINITED);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the state machine state and reset back to MSG_FLOW_UNINITED
|
||||
*/
|
||||
void ossl_statem_clear(SSL *s)
|
||||
{
|
||||
s->statem.state = MSG_FLOW_UNINITED;
|
||||
s->statem.hand_state = TLS_ST_BEFORE;
|
||||
s->statem.in_init = 1;
|
||||
s->statem.no_cert_verify = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the state machine up ready for a renegotiation handshake
|
||||
*/
|
||||
void ossl_statem_set_renegotiate(SSL *s)
|
||||
{
|
||||
s->statem.in_init = 1;
|
||||
s->statem.request_state = TLS_ST_SW_HELLO_REQ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the state machine into an error state and send an alert if appropriate.
|
||||
* This is a permanent error for the current connection.
|
||||
*/
|
||||
void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
|
||||
int line)
|
||||
{
|
||||
ERR_put_error(ERR_LIB_SSL, func, reason, file, line);
|
||||
/* We shouldn't call SSLfatal() twice. Once is enough */
|
||||
if (s->statem.in_init && s->statem.state == MSG_FLOW_ERROR)
|
||||
return;
|
||||
s->statem.in_init = 1;
|
||||
s->statem.state = MSG_FLOW_ERROR;
|
||||
if (al != SSL_AD_NO_ALERT
|
||||
&& s->statem.enc_write_state != ENC_WRITE_STATE_INVALID)
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
}
|
||||
|
||||
/*
|
||||
* This macro should only be called if we are already expecting to be in
|
||||
* a fatal error state. We verify that we are, and set it if not (this would
|
||||
* indicate a bug).
|
||||
*/
|
||||
#define check_fatal(s, f) \
|
||||
do { \
|
||||
if (!ossl_assert((s)->statem.in_init \
|
||||
&& (s)->statem.state == MSG_FLOW_ERROR)) \
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, (f), \
|
||||
SSL_R_MISSING_FATAL); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Discover whether the current connection is in the error state.
|
||||
*
|
||||
* Valid return values are:
|
||||
* 1: Yes
|
||||
* 0: No
|
||||
*/
|
||||
int ossl_statem_in_error(const SSL *s)
|
||||
{
|
||||
if (s->statem.state == MSG_FLOW_ERROR)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ossl_statem_set_in_init(SSL *s, int init)
|
||||
{
|
||||
s->statem.in_init = init;
|
||||
}
|
||||
|
||||
int ossl_statem_get_in_handshake(SSL *s)
|
||||
{
|
||||
return s->statem.in_handshake;
|
||||
}
|
||||
|
||||
void ossl_statem_set_in_handshake(SSL *s, int inhand)
|
||||
{
|
||||
if (inhand)
|
||||
s->statem.in_handshake++;
|
||||
else
|
||||
s->statem.in_handshake--;
|
||||
}
|
||||
|
||||
/* Are we in a sensible state to skip over unreadable early data? */
|
||||
int ossl_statem_skip_early_data(SSL *s)
|
||||
{
|
||||
if (s->ext.early_data != SSL_EARLY_DATA_REJECTED)
|
||||
return 0;
|
||||
|
||||
if (!s->server
|
||||
|| s->statem.hand_state != TLS_ST_EARLY_DATA
|
||||
|| s->hello_retry_request == SSL_HRR_COMPLETE)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when we are in SSL_read*(), SSL_write*(), or SSL_accept()
|
||||
* /SSL_connect()/SSL_do_handshake(). Used to test whether we are in an early
|
||||
* data state and whether we should attempt to move the handshake on if so.
|
||||
* |sending| is 1 if we are attempting to send data (SSL_write*()), 0 if we are
|
||||
* attempting to read data (SSL_read*()), or -1 if we are in SSL_do_handshake()
|
||||
* or similar.
|
||||
*/
|
||||
void ossl_statem_check_finish_init(SSL *s, int sending)
|
||||
{
|
||||
if (sending == -1) {
|
||||
if (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
|
||||
|| s->statem.hand_state == TLS_ST_EARLY_DATA) {
|
||||
ossl_statem_set_in_init(s, 1);
|
||||
if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
|
||||
/*
|
||||
* SSL_connect() or SSL_do_handshake() has been called directly.
|
||||
* We don't allow any more writing of early data.
|
||||
*/
|
||||
s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
|
||||
}
|
||||
}
|
||||
} else if (!s->server) {
|
||||
if ((sending && (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
|
||||
|| s->statem.hand_state == TLS_ST_EARLY_DATA)
|
||||
&& s->early_data_state != SSL_EARLY_DATA_WRITING)
|
||||
|| (!sending && s->statem.hand_state == TLS_ST_EARLY_DATA)) {
|
||||
ossl_statem_set_in_init(s, 1);
|
||||
/*
|
||||
* SSL_write() has been called directly. We don't allow any more
|
||||
* writing of early data.
|
||||
*/
|
||||
if (sending && s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY)
|
||||
s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
|
||||
}
|
||||
} else {
|
||||
if (s->early_data_state == SSL_EARLY_DATA_FINISHED_READING
|
||||
&& s->statem.hand_state == TLS_ST_EARLY_DATA)
|
||||
ossl_statem_set_in_init(s, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ossl_statem_set_hello_verify_done(SSL *s)
|
||||
{
|
||||
s->statem.state = MSG_FLOW_UNINITED;
|
||||
s->statem.in_init = 1;
|
||||
/*
|
||||
* This will get reset (briefly) back to TLS_ST_BEFORE when we enter
|
||||
* state_machine() because |state| is MSG_FLOW_UNINITED, but until then any
|
||||
* calls to SSL_in_before() will return false. Also calls to
|
||||
* SSL_state_string() and SSL_state_string_long() will return something
|
||||
* sensible.
|
||||
*/
|
||||
s->statem.hand_state = TLS_ST_SR_CLNT_HELLO;
|
||||
}
|
||||
|
||||
int ossl_statem_connect(SSL *s)
|
||||
{
|
||||
return state_machine(s, 0);
|
||||
}
|
||||
|
||||
int ossl_statem_accept(SSL *s)
|
||||
{
|
||||
return state_machine(s, 1);
|
||||
}
|
||||
|
||||
typedef void (*info_cb) (const SSL *, int, int);
|
||||
|
||||
static info_cb get_callback(SSL *s)
|
||||
{
|
||||
if (s->info_callback != NULL)
|
||||
return s->info_callback;
|
||||
else if (s->ctx->info_callback != NULL)
|
||||
return s->ctx->info_callback;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The main message flow state machine. We start in the MSG_FLOW_UNINITED or
|
||||
* MSG_FLOW_FINISHED state and finish in MSG_FLOW_FINISHED. Valid states and
|
||||
* transitions are as follows:
|
||||
*
|
||||
* MSG_FLOW_UNINITED MSG_FLOW_FINISHED
|
||||
* | |
|
||||
* +-----------------------+
|
||||
* v
|
||||
* MSG_FLOW_WRITING <---> MSG_FLOW_READING
|
||||
* |
|
||||
* V
|
||||
* MSG_FLOW_FINISHED
|
||||
* |
|
||||
* V
|
||||
* [SUCCESS]
|
||||
*
|
||||
* We may exit at any point due to an error or NBIO event. If an NBIO event
|
||||
* occurs then we restart at the point we left off when we are recalled.
|
||||
* MSG_FLOW_WRITING and MSG_FLOW_READING have sub-state machines associated with them.
|
||||
*
|
||||
* In addition to the above there is also the MSG_FLOW_ERROR state. We can move
|
||||
* into that state at any point in the event that an irrecoverable error occurs.
|
||||
*
|
||||
* Valid return values are:
|
||||
* 1: Success
|
||||
* <=0: NBIO or error
|
||||
*/
|
||||
static int state_machine(SSL *s, int server)
|
||||
{
|
||||
BUF_MEM *buf = NULL;
|
||||
void (*cb) (const SSL *ssl, int type, int val) = NULL;
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
int ret = -1;
|
||||
int ssret;
|
||||
|
||||
if (st->state == MSG_FLOW_ERROR) {
|
||||
/* Shouldn't have been called if we're already in the error state */
|
||||
return -1;
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
clear_sys_error();
|
||||
|
||||
cb = get_callback(s);
|
||||
|
||||
st->in_handshake++;
|
||||
if (!SSL_in_init(s) || SSL_in_before(s)) {
|
||||
/*
|
||||
* If we are stateless then we already called SSL_clear() - don't do
|
||||
* it again and clear the STATELESS flag itself.
|
||||
*/
|
||||
if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0 && !SSL_clear(s))
|
||||
return -1;
|
||||
}
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
|
||||
/*
|
||||
* Notify SCTP BIO socket to enter handshake mode and prevent stream
|
||||
* identifier other than 0.
|
||||
*/
|
||||
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
|
||||
st->in_handshake, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialise state machine */
|
||||
if (st->state == MSG_FLOW_UNINITED
|
||||
|| st->state == MSG_FLOW_FINISHED) {
|
||||
if (st->state == MSG_FLOW_UNINITED) {
|
||||
st->hand_state = TLS_ST_BEFORE;
|
||||
st->request_state = TLS_ST_BEFORE;
|
||||
}
|
||||
|
||||
s->server = server;
|
||||
if (cb != NULL) {
|
||||
if (SSL_IS_FIRST_HANDSHAKE(s) || !SSL_IS_TLS13(s))
|
||||
cb(s, SSL_CB_HANDSHAKE_START, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fatal errors in this block don't send an alert because we have
|
||||
* failed to even initialise properly. Sending an alert is probably
|
||||
* doomed to failure.
|
||||
*/
|
||||
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
|
||||
(server || (s->version & 0xff00) != (DTLS1_BAD_VER & 0xff00))) {
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if ((s->version >> 8) != SSL3_VERSION_MAJOR) {
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (s->init_buf == NULL) {
|
||||
if ((buf = BUF_MEM_new()) == NULL) {
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
s->init_buf = buf;
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (!ssl3_setup_buffers(s)) {
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
s->init_num = 0;
|
||||
|
||||
/*
|
||||
* Should have been reset by tls_process_finished, too.
|
||||
*/
|
||||
s->s3->change_cipher_spec = 0;
|
||||
|
||||
/*
|
||||
* Ok, we now need to push on a buffering BIO ...but not with
|
||||
* SCTP
|
||||
*/
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
if (!SSL_IS_DTLS(s) || !BIO_dgram_is_sctp(SSL_get_wbio(s)))
|
||||
#endif
|
||||
if (!ssl_init_wbio_buffer(s)) {
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((SSL_in_before(s))
|
||||
|| s->renegotiate) {
|
||||
if (!tls_setup_handshake(s)) {
|
||||
/* SSLfatal() already called */
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (SSL_IS_FIRST_HANDSHAKE(s))
|
||||
st->read_state_first_init = 1;
|
||||
}
|
||||
|
||||
st->state = MSG_FLOW_WRITING;
|
||||
init_write_state_machine(s);
|
||||
}
|
||||
|
||||
while (st->state != MSG_FLOW_FINISHED) {
|
||||
if (st->state == MSG_FLOW_READING) {
|
||||
ssret = read_state_machine(s);
|
||||
if (ssret == SUB_STATE_FINISHED) {
|
||||
st->state = MSG_FLOW_WRITING;
|
||||
init_write_state_machine(s);
|
||||
} else {
|
||||
/* NBIO or error */
|
||||
goto end;
|
||||
}
|
||||
} else if (st->state == MSG_FLOW_WRITING) {
|
||||
ssret = write_state_machine(s);
|
||||
if (ssret == SUB_STATE_FINISHED) {
|
||||
st->state = MSG_FLOW_READING;
|
||||
init_read_state_machine(s);
|
||||
} else if (ssret == SUB_STATE_END_HANDSHAKE) {
|
||||
st->state = MSG_FLOW_FINISHED;
|
||||
} else {
|
||||
/* NBIO or error */
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
/* Error */
|
||||
check_fatal(s, SSL_F_STATE_MACHINE);
|
||||
SSLerr(SSL_F_STATE_MACHINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
st->in_handshake--;
|
||||
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
|
||||
/*
|
||||
* Notify SCTP BIO socket to leave handshake mode and allow stream
|
||||
* identifier other than 0.
|
||||
*/
|
||||
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
|
||||
st->in_handshake, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
BUF_MEM_free(buf);
|
||||
if (cb != NULL) {
|
||||
if (server)
|
||||
cb(s, SSL_CB_ACCEPT_EXIT, ret);
|
||||
else
|
||||
cb(s, SSL_CB_CONNECT_EXIT, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the MSG_FLOW_READING sub-state machine
|
||||
*/
|
||||
static void init_read_state_machine(SSL *s)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
st->read_state = READ_STATE_HEADER;
|
||||
}
|
||||
|
||||
static int grow_init_buf(SSL *s, size_t size) {
|
||||
|
||||
size_t msg_offset = (char *)s->init_msg - s->init_buf->data;
|
||||
|
||||
if (!BUF_MEM_grow_clean(s->init_buf, (int)size))
|
||||
return 0;
|
||||
|
||||
if (size < msg_offset)
|
||||
return 0;
|
||||
|
||||
s->init_msg = s->init_buf->data + msg_offset;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function implements the sub-state machine when the message flow is in
|
||||
* MSG_FLOW_READING. The valid sub-states and transitions are:
|
||||
*
|
||||
* READ_STATE_HEADER <--+<-------------+
|
||||
* | | |
|
||||
* v | |
|
||||
* READ_STATE_BODY -----+-->READ_STATE_POST_PROCESS
|
||||
* | |
|
||||
* +----------------------------+
|
||||
* v
|
||||
* [SUB_STATE_FINISHED]
|
||||
*
|
||||
* READ_STATE_HEADER has the responsibility for reading in the message header
|
||||
* and transitioning the state of the handshake state machine.
|
||||
*
|
||||
* READ_STATE_BODY reads in the rest of the message and then subsequently
|
||||
* processes it.
|
||||
*
|
||||
* READ_STATE_POST_PROCESS is an optional step that may occur if some post
|
||||
* processing activity performed on the message may block.
|
||||
*
|
||||
* Any of the above states could result in an NBIO event occurring in which case
|
||||
* control returns to the calling application. When this function is recalled we
|
||||
* will resume in the same state where we left off.
|
||||
*/
|
||||
static SUB_STATE_RETURN read_state_machine(SSL *s)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
int ret, mt;
|
||||
size_t len = 0;
|
||||
int (*transition) (SSL *s, int mt);
|
||||
PACKET pkt;
|
||||
MSG_PROCESS_RETURN(*process_message) (SSL *s, PACKET *pkt);
|
||||
WORK_STATE(*post_process_message) (SSL *s, WORK_STATE wst);
|
||||
size_t (*max_message_size) (SSL *s);
|
||||
void (*cb) (const SSL *ssl, int type, int val) = NULL;
|
||||
|
||||
cb = get_callback(s);
|
||||
|
||||
if (s->server) {
|
||||
transition = ossl_statem_server_read_transition;
|
||||
process_message = ossl_statem_server_process_message;
|
||||
max_message_size = ossl_statem_server_max_message_size;
|
||||
post_process_message = ossl_statem_server_post_process_message;
|
||||
} else {
|
||||
transition = ossl_statem_client_read_transition;
|
||||
process_message = ossl_statem_client_process_message;
|
||||
max_message_size = ossl_statem_client_max_message_size;
|
||||
post_process_message = ossl_statem_client_post_process_message;
|
||||
}
|
||||
|
||||
if (st->read_state_first_init) {
|
||||
s->first_packet = 1;
|
||||
st->read_state_first_init = 0;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
switch (st->read_state) {
|
||||
case READ_STATE_HEADER:
|
||||
/* Get the state the peer wants to move to */
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
/*
|
||||
* In DTLS we get the whole message in one go - header and body
|
||||
*/
|
||||
ret = dtls_get_message(s, &mt, &len);
|
||||
} else {
|
||||
ret = tls_get_message_header(s, &mt);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
/* Could be non-blocking IO */
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
|
||||
if (cb != NULL) {
|
||||
/* Notify callback of an impending state change */
|
||||
if (s->server)
|
||||
cb(s, SSL_CB_ACCEPT_LOOP, 1);
|
||||
else
|
||||
cb(s, SSL_CB_CONNECT_LOOP, 1);
|
||||
}
|
||||
/*
|
||||
* Validate that we are allowed to move to the new state and move
|
||||
* to that state if so
|
||||
*/
|
||||
if (!transition(s, mt))
|
||||
return SUB_STATE_ERROR;
|
||||
|
||||
if (s->s3->tmp.message_size > max_message_size(s)) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_READ_STATE_MACHINE,
|
||||
SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
|
||||
/* dtls_get_message already did this */
|
||||
if (!SSL_IS_DTLS(s)
|
||||
&& s->s3->tmp.message_size > 0
|
||||
&& !grow_init_buf(s, s->s3->tmp.message_size
|
||||
+ SSL3_HM_HEADER_LENGTH)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
|
||||
ERR_R_BUF_LIB);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
|
||||
st->read_state = READ_STATE_BODY;
|
||||
/* Fall through */
|
||||
|
||||
case READ_STATE_BODY:
|
||||
if (!SSL_IS_DTLS(s)) {
|
||||
/* We already got this above for DTLS */
|
||||
ret = tls_get_message_body(s, &len);
|
||||
if (ret == 0) {
|
||||
/* Could be non-blocking IO */
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
s->first_packet = 0;
|
||||
if (!PACKET_buf_init(&pkt, s->init_msg, len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
ret = process_message(s, &pkt);
|
||||
|
||||
/* Discard the packet data */
|
||||
s->init_num = 0;
|
||||
|
||||
switch (ret) {
|
||||
case MSG_PROCESS_ERROR:
|
||||
check_fatal(s, SSL_F_READ_STATE_MACHINE);
|
||||
return SUB_STATE_ERROR;
|
||||
|
||||
case MSG_PROCESS_FINISHED_READING:
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
dtls1_stop_timer(s);
|
||||
}
|
||||
return SUB_STATE_FINISHED;
|
||||
|
||||
case MSG_PROCESS_CONTINUE_PROCESSING:
|
||||
st->read_state = READ_STATE_POST_PROCESS;
|
||||
st->read_state_work = WORK_MORE_A;
|
||||
break;
|
||||
|
||||
default:
|
||||
st->read_state = READ_STATE_HEADER;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case READ_STATE_POST_PROCESS:
|
||||
st->read_state_work = post_process_message(s, st->read_state_work);
|
||||
switch (st->read_state_work) {
|
||||
case WORK_ERROR:
|
||||
check_fatal(s, SSL_F_READ_STATE_MACHINE);
|
||||
/* Fall through */
|
||||
case WORK_MORE_A:
|
||||
case WORK_MORE_B:
|
||||
case WORK_MORE_C:
|
||||
return SUB_STATE_ERROR;
|
||||
|
||||
case WORK_FINISHED_CONTINUE:
|
||||
st->read_state = READ_STATE_HEADER;
|
||||
break;
|
||||
|
||||
case WORK_FINISHED_STOP:
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
dtls1_stop_timer(s);
|
||||
}
|
||||
return SUB_STATE_FINISHED;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a previously constructed message to the peer.
|
||||
*/
|
||||
static int statem_do_write(SSL *s)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
if (st->hand_state == TLS_ST_CW_CHANGE
|
||||
|| st->hand_state == TLS_ST_SW_CHANGE) {
|
||||
if (SSL_IS_DTLS(s))
|
||||
return dtls1_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC);
|
||||
else
|
||||
return ssl3_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC);
|
||||
} else {
|
||||
return ssl_do_write(s);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the MSG_FLOW_WRITING sub-state machine
|
||||
*/
|
||||
static void init_write_state_machine(SSL *s)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
st->write_state = WRITE_STATE_TRANSITION;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function implements the sub-state machine when the message flow is in
|
||||
* MSG_FLOW_WRITING. The valid sub-states and transitions are:
|
||||
*
|
||||
* +-> WRITE_STATE_TRANSITION ------> [SUB_STATE_FINISHED]
|
||||
* | |
|
||||
* | v
|
||||
* | WRITE_STATE_PRE_WORK -----> [SUB_STATE_END_HANDSHAKE]
|
||||
* | |
|
||||
* | v
|
||||
* | WRITE_STATE_SEND
|
||||
* | |
|
||||
* | v
|
||||
* | WRITE_STATE_POST_WORK
|
||||
* | |
|
||||
* +-------------+
|
||||
*
|
||||
* WRITE_STATE_TRANSITION transitions the state of the handshake state machine
|
||||
|
||||
* WRITE_STATE_PRE_WORK performs any work necessary to prepare the later
|
||||
* sending of the message. This could result in an NBIO event occurring in
|
||||
* which case control returns to the calling application. When this function
|
||||
* is recalled we will resume in the same state where we left off.
|
||||
*
|
||||
* WRITE_STATE_SEND sends the message and performs any work to be done after
|
||||
* sending.
|
||||
*
|
||||
* WRITE_STATE_POST_WORK performs any work necessary after the sending of the
|
||||
* message has been completed. As for WRITE_STATE_PRE_WORK this could also
|
||||
* result in an NBIO event.
|
||||
*/
|
||||
static SUB_STATE_RETURN write_state_machine(SSL *s)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
int ret;
|
||||
WRITE_TRAN(*transition) (SSL *s);
|
||||
WORK_STATE(*pre_work) (SSL *s, WORK_STATE wst);
|
||||
WORK_STATE(*post_work) (SSL *s, WORK_STATE wst);
|
||||
int (*get_construct_message_f) (SSL *s, WPACKET *pkt,
|
||||
int (**confunc) (SSL *s, WPACKET *pkt),
|
||||
int *mt);
|
||||
void (*cb) (const SSL *ssl, int type, int val) = NULL;
|
||||
int (*confunc) (SSL *s, WPACKET *pkt);
|
||||
int mt;
|
||||
WPACKET pkt;
|
||||
|
||||
cb = get_callback(s);
|
||||
|
||||
if (s->server) {
|
||||
transition = ossl_statem_server_write_transition;
|
||||
pre_work = ossl_statem_server_pre_work;
|
||||
post_work = ossl_statem_server_post_work;
|
||||
get_construct_message_f = ossl_statem_server_construct_message;
|
||||
} else {
|
||||
transition = ossl_statem_client_write_transition;
|
||||
pre_work = ossl_statem_client_pre_work;
|
||||
post_work = ossl_statem_client_post_work;
|
||||
get_construct_message_f = ossl_statem_client_construct_message;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
switch (st->write_state) {
|
||||
case WRITE_STATE_TRANSITION:
|
||||
if (cb != NULL) {
|
||||
/* Notify callback of an impending state change */
|
||||
if (s->server)
|
||||
cb(s, SSL_CB_ACCEPT_LOOP, 1);
|
||||
else
|
||||
cb(s, SSL_CB_CONNECT_LOOP, 1);
|
||||
}
|
||||
switch (transition(s)) {
|
||||
case WRITE_TRAN_CONTINUE:
|
||||
st->write_state = WRITE_STATE_PRE_WORK;
|
||||
st->write_state_work = WORK_MORE_A;
|
||||
break;
|
||||
|
||||
case WRITE_TRAN_FINISHED:
|
||||
return SUB_STATE_FINISHED;
|
||||
break;
|
||||
|
||||
case WRITE_TRAN_ERROR:
|
||||
check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case WRITE_STATE_PRE_WORK:
|
||||
switch (st->write_state_work = pre_work(s, st->write_state_work)) {
|
||||
case WORK_ERROR:
|
||||
check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
|
||||
/* Fall through */
|
||||
case WORK_MORE_A:
|
||||
case WORK_MORE_B:
|
||||
case WORK_MORE_C:
|
||||
return SUB_STATE_ERROR;
|
||||
|
||||
case WORK_FINISHED_CONTINUE:
|
||||
st->write_state = WRITE_STATE_SEND;
|
||||
break;
|
||||
|
||||
case WORK_FINISHED_STOP:
|
||||
return SUB_STATE_END_HANDSHAKE;
|
||||
}
|
||||
if (!get_construct_message_f(s, &pkt, &confunc, &mt)) {
|
||||
/* SSLfatal() already called */
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
if (mt == SSL3_MT_DUMMY) {
|
||||
/* Skip construction and sending. This isn't a "real" state */
|
||||
st->write_state = WRITE_STATE_POST_WORK;
|
||||
st->write_state_work = WORK_MORE_A;
|
||||
break;
|
||||
}
|
||||
if (!WPACKET_init(&pkt, s->init_buf)
|
||||
|| !ssl_set_handshake_header(s, &pkt, mt)) {
|
||||
WPACKET_cleanup(&pkt);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
if (confunc != NULL && !confunc(s, &pkt)) {
|
||||
WPACKET_cleanup(&pkt);
|
||||
check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
if (!ssl_close_construct_packet(s, &pkt, mt)
|
||||
|| !WPACKET_finish(&pkt)) {
|
||||
WPACKET_cleanup(&pkt);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
|
||||
/* Fall through */
|
||||
|
||||
case WRITE_STATE_SEND:
|
||||
if (SSL_IS_DTLS(s) && st->use_timer) {
|
||||
dtls1_start_timer(s);
|
||||
}
|
||||
ret = statem_do_write(s);
|
||||
if (ret <= 0) {
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
st->write_state = WRITE_STATE_POST_WORK;
|
||||
st->write_state_work = WORK_MORE_A;
|
||||
/* Fall through */
|
||||
|
||||
case WRITE_STATE_POST_WORK:
|
||||
switch (st->write_state_work = post_work(s, st->write_state_work)) {
|
||||
case WORK_ERROR:
|
||||
check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
|
||||
/* Fall through */
|
||||
case WORK_MORE_A:
|
||||
case WORK_MORE_B:
|
||||
case WORK_MORE_C:
|
||||
return SUB_STATE_ERROR;
|
||||
|
||||
case WORK_FINISHED_CONTINUE:
|
||||
st->write_state = WRITE_STATE_TRANSITION;
|
||||
break;
|
||||
|
||||
case WORK_FINISHED_STOP:
|
||||
return SUB_STATE_END_HANDSHAKE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush the write BIO
|
||||
*/
|
||||
int statem_flush(SSL *s)
|
||||
{
|
||||
s->rwstate = SSL_WRITING;
|
||||
if (BIO_flush(s->wbio) <= 0) {
|
||||
return 0;
|
||||
}
|
||||
s->rwstate = SSL_NOTHING;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by the record layer to determine whether application data is
|
||||
* allowed to be received in the current handshake state or not.
|
||||
*
|
||||
* Return values are:
|
||||
* 1: Yes (application data allowed)
|
||||
* 0: No (application data not allowed)
|
||||
*/
|
||||
int ossl_statem_app_data_allowed(SSL *s)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
if (st->state == MSG_FLOW_UNINITED)
|
||||
return 0;
|
||||
|
||||
if (!s->s3->in_read_app_data || (s->s3->total_renegotiations == 0))
|
||||
return 0;
|
||||
|
||||
if (s->server) {
|
||||
/*
|
||||
* If we're a server and we haven't got as far as writing our
|
||||
* ServerHello yet then we allow app data
|
||||
*/
|
||||
if (st->hand_state == TLS_ST_BEFORE
|
||||
|| st->hand_state == TLS_ST_SR_CLNT_HELLO)
|
||||
return 1;
|
||||
} else {
|
||||
/*
|
||||
* If we're a client and we haven't read the ServerHello yet then we
|
||||
* allow app data
|
||||
*/
|
||||
if (st->hand_state == TLS_ST_CW_CLNT_HELLO)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns 1 if TLS exporter is ready to export keying
|
||||
* material, or 0 if otherwise.
|
||||
*/
|
||||
int ossl_statem_export_allowed(SSL *s)
|
||||
{
|
||||
return s->s3->previous_server_finished_len != 0
|
||||
&& s->statem.hand_state != TLS_ST_SW_FINISHED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 1 if early TLS exporter is ready to export keying material,
|
||||
* or 0 if otherwise.
|
||||
*/
|
||||
int ossl_statem_export_early_allowed(SSL *s)
|
||||
{
|
||||
/*
|
||||
* The early exporter secret is only present on the server if we
|
||||
* have accepted early_data. It is present on the client as long
|
||||
* as we have sent early_data.
|
||||
*/
|
||||
return s->ext.early_data == SSL_EARLY_DATA_ACCEPTED
|
||||
|| (!s->server && s->ext.early_data != SSL_EARLY_DATA_NOT_SENT);
|
||||
}
|
157
trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem.h
vendored
Normal file
157
trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem.h
vendored
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* These enums should be considered PRIVATE to the state machine. No *
|
||||
* non-state machine code should need to use these *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* Valid return codes used for functions performing work prior to or after
|
||||
* sending or receiving a message
|
||||
*/
|
||||
typedef enum {
|
||||
/* Something went wrong */
|
||||
WORK_ERROR,
|
||||
/* We're done working and there shouldn't be anything else to do after */
|
||||
WORK_FINISHED_STOP,
|
||||
/* We're done working move onto the next thing */
|
||||
WORK_FINISHED_CONTINUE,
|
||||
/* We're working on phase A */
|
||||
WORK_MORE_A,
|
||||
/* We're working on phase B */
|
||||
WORK_MORE_B,
|
||||
/* We're working on phase C */
|
||||
WORK_MORE_C
|
||||
} WORK_STATE;
|
||||
|
||||
/* Write transition return codes */
|
||||
typedef enum {
|
||||
/* Something went wrong */
|
||||
WRITE_TRAN_ERROR,
|
||||
/* A transition was successfully completed and we should continue */
|
||||
WRITE_TRAN_CONTINUE,
|
||||
/* There is no more write work to be done */
|
||||
WRITE_TRAN_FINISHED
|
||||
} WRITE_TRAN;
|
||||
|
||||
/* Message flow states */
|
||||
typedef enum {
|
||||
/* No handshake in progress */
|
||||
MSG_FLOW_UNINITED,
|
||||
/* A permanent error with this connection */
|
||||
MSG_FLOW_ERROR,
|
||||
/* We are reading messages */
|
||||
MSG_FLOW_READING,
|
||||
/* We are writing messages */
|
||||
MSG_FLOW_WRITING,
|
||||
/* Handshake has finished */
|
||||
MSG_FLOW_FINISHED
|
||||
} MSG_FLOW_STATE;
|
||||
|
||||
/* Read states */
|
||||
typedef enum {
|
||||
READ_STATE_HEADER,
|
||||
READ_STATE_BODY,
|
||||
READ_STATE_POST_PROCESS
|
||||
} READ_STATE;
|
||||
|
||||
/* Write states */
|
||||
typedef enum {
|
||||
WRITE_STATE_TRANSITION,
|
||||
WRITE_STATE_PRE_WORK,
|
||||
WRITE_STATE_SEND,
|
||||
WRITE_STATE_POST_WORK
|
||||
} WRITE_STATE;
|
||||
|
||||
typedef enum {
|
||||
/* The enc_write_ctx can be used normally */
|
||||
ENC_WRITE_STATE_VALID,
|
||||
/* The enc_write_ctx cannot be used */
|
||||
ENC_WRITE_STATE_INVALID,
|
||||
/* Write alerts in plaintext, but otherwise use the enc_write_ctx */
|
||||
ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
|
||||
} ENC_WRITE_STATES;
|
||||
|
||||
typedef enum {
|
||||
/* The enc_read_ctx can be used normally */
|
||||
ENC_READ_STATE_VALID,
|
||||
/* We may receive encrypted or plaintext alerts */
|
||||
ENC_READ_STATE_ALLOW_PLAIN_ALERTS
|
||||
} ENC_READ_STATES;
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* This structure should be considered "opaque" to anything outside of the *
|
||||
* state machine. No non-state machine code should be accessing the members *
|
||||
* of this structure. *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
struct ossl_statem_st {
|
||||
MSG_FLOW_STATE state;
|
||||
WRITE_STATE write_state;
|
||||
WORK_STATE write_state_work;
|
||||
READ_STATE read_state;
|
||||
WORK_STATE read_state_work;
|
||||
OSSL_HANDSHAKE_STATE hand_state;
|
||||
/* The handshake state requested by an API call (e.g. HelloRequest) */
|
||||
OSSL_HANDSHAKE_STATE request_state;
|
||||
int in_init;
|
||||
int read_state_first_init;
|
||||
/* true when we are actually in SSL_accept() or SSL_connect() */
|
||||
int in_handshake;
|
||||
/*
|
||||
* True when are processing a "real" handshake that needs cleaning up (not
|
||||
* just a HelloRequest or similar).
|
||||
*/
|
||||
int cleanuphand;
|
||||
/* Should we skip the CertificateVerify message? */
|
||||
unsigned int no_cert_verify;
|
||||
int use_timer;
|
||||
ENC_WRITE_STATES enc_write_state;
|
||||
ENC_READ_STATES enc_read_state;
|
||||
};
|
||||
typedef struct ossl_statem_st OSSL_STATEM;
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* The following macros/functions represent the libssl internal API to the *
|
||||
* state machine. Any libssl code may call these functions/macros *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
__owur int ossl_statem_accept(SSL *s);
|
||||
__owur int ossl_statem_connect(SSL *s);
|
||||
void ossl_statem_clear(SSL *s);
|
||||
void ossl_statem_set_renegotiate(SSL *s);
|
||||
void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
|
||||
int line);
|
||||
# define SSL_AD_NO_ALERT -1
|
||||
# ifndef OPENSSL_NO_ERR
|
||||
# define SSLfatal(s, al, f, r) ossl_statem_fatal((s), (al), (f), (r), \
|
||||
OPENSSL_FILE, OPENSSL_LINE)
|
||||
# else
|
||||
# define SSLfatal(s, al, f, r) ossl_statem_fatal((s), (al), (f), (r), NULL, 0)
|
||||
# endif
|
||||
|
||||
int ossl_statem_in_error(const SSL *s);
|
||||
void ossl_statem_set_in_init(SSL *s, int init);
|
||||
int ossl_statem_get_in_handshake(SSL *s);
|
||||
void ossl_statem_set_in_handshake(SSL *s, int inhand);
|
||||
__owur int ossl_statem_skip_early_data(SSL *s);
|
||||
void ossl_statem_check_finish_init(SSL *s, int send);
|
||||
void ossl_statem_set_hello_verify_done(SSL *s);
|
||||
__owur int ossl_statem_app_data_allowed(SSL *s);
|
||||
__owur int ossl_statem_export_allowed(SSL *s);
|
||||
__owur int ossl_statem_export_early_allowed(SSL *s);
|
||||
|
||||
/* Flush the write BIO */
|
||||
int statem_flush(SSL *s);
|
3851
trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_clnt.c
vendored
Normal file
3851
trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_clnt.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
1281
trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_dtls.c
vendored
Normal file
1281
trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_dtls.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
2403
trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_lib.c
vendored
Normal file
2403
trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_lib.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
420
trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_locl.h
vendored
Normal file
420
trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_locl.h
vendored
Normal file
|
@ -0,0 +1,420 @@
|
|||
/*
|
||||
* Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* The following definitions are PRIVATE to the state machine. They should *
|
||||
* NOT be used outside of the state machine. *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
/* Max message length definitions */
|
||||
|
||||
/* The spec allows for a longer length than this, but we limit it */
|
||||
#define HELLO_VERIFY_REQUEST_MAX_LENGTH 258
|
||||
#define END_OF_EARLY_DATA_MAX_LENGTH 0
|
||||
#define SERVER_HELLO_MAX_LENGTH 20000
|
||||
#define HELLO_RETRY_REQUEST_MAX_LENGTH 20000
|
||||
#define ENCRYPTED_EXTENSIONS_MAX_LENGTH 20000
|
||||
#define SERVER_KEY_EXCH_MAX_LENGTH 102400
|
||||
#define SERVER_HELLO_DONE_MAX_LENGTH 0
|
||||
#define KEY_UPDATE_MAX_LENGTH 1
|
||||
#define CCS_MAX_LENGTH 1
|
||||
/* Max should actually be 36 but we are generous */
|
||||
#define FINISHED_MAX_LENGTH 64
|
||||
|
||||
/* Dummy message type */
|
||||
#define SSL3_MT_DUMMY -1
|
||||
|
||||
extern const unsigned char hrrrandom[];
|
||||
|
||||
/* Message processing return codes */
|
||||
typedef enum {
|
||||
/* Something bad happened */
|
||||
MSG_PROCESS_ERROR,
|
||||
/* We've finished reading - swap to writing */
|
||||
MSG_PROCESS_FINISHED_READING,
|
||||
/*
|
||||
* We've completed the main processing of this message but there is some
|
||||
* post processing to be done.
|
||||
*/
|
||||
MSG_PROCESS_CONTINUE_PROCESSING,
|
||||
/* We've finished this message - read the next message */
|
||||
MSG_PROCESS_CONTINUE_READING
|
||||
} MSG_PROCESS_RETURN;
|
||||
|
||||
typedef int (*confunc_f) (SSL *s, WPACKET *pkt);
|
||||
|
||||
int ssl3_take_mac(SSL *s);
|
||||
int check_in_list(SSL *s, uint16_t group_id, const uint16_t *groups,
|
||||
size_t num_groups, int checkallow);
|
||||
int create_synthetic_message_hash(SSL *s, const unsigned char *hashval,
|
||||
size_t hashlen, const unsigned char *hrr,
|
||||
size_t hrrlen);
|
||||
int parse_ca_names(SSL *s, PACKET *pkt);
|
||||
const STACK_OF(X509_NAME) *get_ca_names(SSL *s);
|
||||
int construct_ca_names(SSL *s, const STACK_OF(X509_NAME) *ca_sk, WPACKET *pkt);
|
||||
size_t construct_key_exchange_tbs(SSL *s, unsigned char **ptbs,
|
||||
const void *param, size_t paramlen);
|
||||
|
||||
/*
|
||||
* TLS/DTLS client state machine functions
|
||||
*/
|
||||
int ossl_statem_client_read_transition(SSL *s, int mt);
|
||||
WRITE_TRAN ossl_statem_client_write_transition(SSL *s);
|
||||
WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst);
|
||||
WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst);
|
||||
int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt,
|
||||
confunc_f *confunc, int *mt);
|
||||
size_t ossl_statem_client_max_message_size(SSL *s);
|
||||
MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt);
|
||||
WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst);
|
||||
|
||||
/*
|
||||
* TLS/DTLS server state machine functions
|
||||
*/
|
||||
int ossl_statem_server_read_transition(SSL *s, int mt);
|
||||
WRITE_TRAN ossl_statem_server_write_transition(SSL *s);
|
||||
WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst);
|
||||
WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst);
|
||||
int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt,
|
||||
confunc_f *confunc,int *mt);
|
||||
size_t ossl_statem_server_max_message_size(SSL *s);
|
||||
MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt);
|
||||
WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst);
|
||||
|
||||
/* Functions for getting new message data */
|
||||
__owur int tls_get_message_header(SSL *s, int *mt);
|
||||
__owur int tls_get_message_body(SSL *s, size_t *len);
|
||||
__owur int dtls_get_message(SSL *s, int *mt, size_t *len);
|
||||
|
||||
/* Message construction and processing functions */
|
||||
__owur int tls_process_initial_server_flight(SSL *s);
|
||||
__owur MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt);
|
||||
__owur int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt);
|
||||
__owur int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt);
|
||||
|
||||
__owur int tls_construct_finished(SSL *s, WPACKET *pkt);
|
||||
__owur int tls_construct_key_update(SSL *s, WPACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt);
|
||||
__owur WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs,
|
||||
int stop);
|
||||
__owur WORK_STATE dtls_wait_for_dry(SSL *s);
|
||||
|
||||
/* some client-only functions */
|
||||
__owur int tls_construct_client_hello(SSL *s, WPACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt);
|
||||
__owur int tls_process_cert_status_body(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt);
|
||||
__owur int tls_construct_cert_verify(SSL *s, WPACKET *pkt);
|
||||
__owur WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst);
|
||||
__owur int tls_construct_client_certificate(SSL *s, WPACKET *pkt);
|
||||
__owur int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
|
||||
__owur int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt);
|
||||
__owur int tls_client_key_exchange_post_work(SSL *s);
|
||||
__owur int tls_construct_cert_status_body(SSL *s, WPACKET *pkt);
|
||||
__owur int tls_construct_cert_status(SSL *s, WPACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt);
|
||||
__owur int ssl3_check_cert_and_algorithm(SSL *s);
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
__owur int tls_construct_next_proto(SSL *s, WPACKET *pkt);
|
||||
#endif
|
||||
__owur MSG_PROCESS_RETURN tls_process_hello_req(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt);
|
||||
__owur int tls_construct_end_of_early_data(SSL *s, WPACKET *pkt);
|
||||
|
||||
/* some server-only functions */
|
||||
__owur MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt);
|
||||
__owur WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst);
|
||||
__owur int tls_construct_server_hello(SSL *s, WPACKET *pkt);
|
||||
__owur int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt);
|
||||
__owur int tls_construct_server_certificate(SSL *s, WPACKET *pkt);
|
||||
__owur int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt);
|
||||
__owur int tls_construct_certificate_request(SSL *s, WPACKET *pkt);
|
||||
__owur int tls_construct_server_done(SSL *s, WPACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt);
|
||||
__owur WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst);
|
||||
__owur MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt);
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
__owur MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt);
|
||||
#endif
|
||||
__owur int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt);
|
||||
MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt);
|
||||
|
||||
|
||||
/* Extension processing */
|
||||
|
||||
typedef enum ext_return_en {
|
||||
EXT_RETURN_FAIL,
|
||||
EXT_RETURN_SENT,
|
||||
EXT_RETURN_NOT_SENT
|
||||
} EXT_RETURN;
|
||||
|
||||
__owur int tls_validate_all_contexts(SSL *s, unsigned int thisctx,
|
||||
RAW_EXTENSION *exts);
|
||||
__owur int extension_is_relevant(SSL *s, unsigned int extctx,
|
||||
unsigned int thisctx);
|
||||
__owur int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
|
||||
RAW_EXTENSION **res, size_t *len, int init);
|
||||
__owur int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context,
|
||||
RAW_EXTENSION *exts, X509 *x, size_t chainidx);
|
||||
__owur int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts,
|
||||
X509 *x, size_t chainidx, int fin);
|
||||
__owur int should_add_extension(SSL *s, unsigned int extctx,
|
||||
unsigned int thisctx, int max_version);
|
||||
__owur int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
|
||||
__owur int tls_psk_do_binder(SSL *s, const EVP_MD *md,
|
||||
const unsigned char *msgstart,
|
||||
size_t binderoffset, const unsigned char *binderin,
|
||||
unsigned char *binderout,
|
||||
SSL_SESSION *sess, int sign, int external);
|
||||
|
||||
/* Server Extension processing */
|
||||
int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidxl);
|
||||
#endif
|
||||
int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
int tls_parse_ctos_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_ctos_post_handshake_auth(SSL *, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
|
||||
EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#ifndef OPENSSL_NO_EC
|
||||
EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
/*
|
||||
* Not in public headers as this is not an official extension. Only used when
|
||||
* SSL_OP_CRYPTOPRO_TLSEXT_BUG is set.
|
||||
*/
|
||||
#define TLSEXT_TYPE_cryptopro_bug 0xfde8
|
||||
EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
|
||||
/* Client Extension processing */
|
||||
EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_EC
|
||||
EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
EXT_RETURN tls_construct_ctos_etm(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_CT
|
||||
EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
|
||||
int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_CT
|
||||
int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
|
||||
int tls_handle_alpn(SSL *s);
|
||||
|
||||
int tls13_save_handshake_digest_for_pha(SSL *s);
|
||||
int tls13_restore_handshake_digest_for_pha(SSL *s);
|
4272
trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_srvr.c
vendored
Normal file
4272
trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_srvr.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
678
trunk/3rdparty/openssl-1.1-fit/ssl/t1_enc.c
vendored
Normal file
678
trunk/3rdparty/openssl-1.1-fit/ssl/t1_enc.c
vendored
Normal file
|
@ -0,0 +1,678 @@
|
|||
/*
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2005 Nokia. All rights reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "ssl_locl.h"
|
||||
#include <openssl/comp.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/kdf.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
/* seed1 through seed5 are concatenated */
|
||||
static int tls1_PRF(SSL *s,
|
||||
const void *seed1, size_t seed1_len,
|
||||
const void *seed2, size_t seed2_len,
|
||||
const void *seed3, size_t seed3_len,
|
||||
const void *seed4, size_t seed4_len,
|
||||
const void *seed5, size_t seed5_len,
|
||||
const unsigned char *sec, size_t slen,
|
||||
unsigned char *out, size_t olen, int fatal)
|
||||
{
|
||||
const EVP_MD *md = ssl_prf_md(s);
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (md == NULL) {
|
||||
/* Should never happen */
|
||||
if (fatal)
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_PRF,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
else
|
||||
SSLerr(SSL_F_TLS1_PRF, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL);
|
||||
if (pctx == NULL || EVP_PKEY_derive_init(pctx) <= 0
|
||||
|| EVP_PKEY_CTX_set_tls1_prf_md(pctx, md) <= 0
|
||||
|| EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, (int)slen) <= 0
|
||||
|| EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed1, (int)seed1_len) <= 0
|
||||
|| EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed2, (int)seed2_len) <= 0
|
||||
|| EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed3, (int)seed3_len) <= 0
|
||||
|| EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed4, (int)seed4_len) <= 0
|
||||
|| EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed5, (int)seed5_len) <= 0
|
||||
|| EVP_PKEY_derive(pctx, out, &olen) <= 0) {
|
||||
if (fatal)
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_PRF,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
else
|
||||
SSLerr(SSL_F_TLS1_PRF, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tls1_generate_key_block(SSL *s, unsigned char *km, size_t num)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Calls SSLfatal() as required */
|
||||
ret = tls1_PRF(s,
|
||||
TLS_MD_KEY_EXPANSION_CONST,
|
||||
TLS_MD_KEY_EXPANSION_CONST_SIZE, s->s3->server_random,
|
||||
SSL3_RANDOM_SIZE, s->s3->client_random, SSL3_RANDOM_SIZE,
|
||||
NULL, 0, NULL, 0, s->session->master_key,
|
||||
s->session->master_key_length, km, num, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tls1_change_cipher_state(SSL *s, int which)
|
||||
{
|
||||
unsigned char *p, *mac_secret;
|
||||
unsigned char *ms, *key, *iv;
|
||||
EVP_CIPHER_CTX *dd;
|
||||
const EVP_CIPHER *c;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
const SSL_COMP *comp;
|
||||
#endif
|
||||
const EVP_MD *m;
|
||||
int mac_type;
|
||||
size_t *mac_secret_size;
|
||||
EVP_MD_CTX *mac_ctx;
|
||||
EVP_PKEY *mac_key;
|
||||
size_t n, i, j, k, cl;
|
||||
int reuse_dd = 0;
|
||||
|
||||
c = s->s3->tmp.new_sym_enc;
|
||||
m = s->s3->tmp.new_hash;
|
||||
mac_type = s->s3->tmp.new_mac_pkey_type;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
comp = s->s3->tmp.new_compression;
|
||||
#endif
|
||||
|
||||
if (which & SSL3_CC_READ) {
|
||||
if (s->ext.use_etm)
|
||||
s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_READ;
|
||||
else
|
||||
s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_READ;
|
||||
|
||||
if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
|
||||
s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM;
|
||||
else
|
||||
s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM;
|
||||
|
||||
if (s->enc_read_ctx != NULL) {
|
||||
reuse_dd = 1;
|
||||
} else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
} else {
|
||||
/*
|
||||
* make sure it's initialised in case we exit later with an error
|
||||
*/
|
||||
EVP_CIPHER_CTX_reset(s->enc_read_ctx);
|
||||
}
|
||||
dd = s->enc_read_ctx;
|
||||
mac_ctx = ssl_replace_hash(&s->read_hash, NULL);
|
||||
if (mac_ctx == NULL)
|
||||
goto err;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
COMP_CTX_free(s->expand);
|
||||
s->expand = NULL;
|
||||
if (comp != NULL) {
|
||||
s->expand = COMP_CTX_new(comp->method);
|
||||
if (s->expand == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS1_CHANGE_CIPHER_STATE,
|
||||
SSL_R_COMPRESSION_LIBRARY_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* this is done by dtls1_reset_seq_numbers for DTLS
|
||||
*/
|
||||
if (!SSL_IS_DTLS(s))
|
||||
RECORD_LAYER_reset_read_sequence(&s->rlayer);
|
||||
mac_secret = &(s->s3->read_mac_secret[0]);
|
||||
mac_secret_size = &(s->s3->read_mac_secret_size);
|
||||
} else {
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
|
||||
if (s->ext.use_etm)
|
||||
s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE;
|
||||
else
|
||||
s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE;
|
||||
|
||||
if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
|
||||
s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM;
|
||||
else
|
||||
s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM;
|
||||
if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s)) {
|
||||
reuse_dd = 1;
|
||||
} else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
dd = s->enc_write_ctx;
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
mac_ctx = EVP_MD_CTX_new();
|
||||
if (mac_ctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS1_CHANGE_CIPHER_STATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
s->write_hash = mac_ctx;
|
||||
} else {
|
||||
mac_ctx = ssl_replace_hash(&s->write_hash, NULL);
|
||||
if (mac_ctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS1_CHANGE_CIPHER_STATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
COMP_CTX_free(s->compress);
|
||||
s->compress = NULL;
|
||||
if (comp != NULL) {
|
||||
s->compress = COMP_CTX_new(comp->method);
|
||||
if (s->compress == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS1_CHANGE_CIPHER_STATE,
|
||||
SSL_R_COMPRESSION_LIBRARY_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* this is done by dtls1_reset_seq_numbers for DTLS
|
||||
*/
|
||||
if (!SSL_IS_DTLS(s))
|
||||
RECORD_LAYER_reset_write_sequence(&s->rlayer);
|
||||
mac_secret = &(s->s3->write_mac_secret[0]);
|
||||
mac_secret_size = &(s->s3->write_mac_secret_size);
|
||||
}
|
||||
|
||||
if (reuse_dd)
|
||||
EVP_CIPHER_CTX_reset(dd);
|
||||
|
||||
p = s->s3->tmp.key_block;
|
||||
i = *mac_secret_size = s->s3->tmp.new_mac_secret_size;
|
||||
|
||||
/* TODO(size_t): convert me */
|
||||
cl = EVP_CIPHER_key_length(c);
|
||||
j = cl;
|
||||
/* Was j=(exp)?5:EVP_CIPHER_key_length(c); */
|
||||
/* If GCM/CCM mode only part of IV comes from PRF */
|
||||
if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE)
|
||||
k = EVP_GCM_TLS_FIXED_IV_LEN;
|
||||
else if (EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE)
|
||||
k = EVP_CCM_TLS_FIXED_IV_LEN;
|
||||
else
|
||||
k = EVP_CIPHER_iv_length(c);
|
||||
if ((which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
|
||||
(which == SSL3_CHANGE_CIPHER_SERVER_READ)) {
|
||||
ms = &(p[0]);
|
||||
n = i + i;
|
||||
key = &(p[n]);
|
||||
n += j + j;
|
||||
iv = &(p[n]);
|
||||
n += k + k;
|
||||
} else {
|
||||
n = i;
|
||||
ms = &(p[n]);
|
||||
n += i + j;
|
||||
key = &(p[n]);
|
||||
n += j + k;
|
||||
iv = &(p[n]);
|
||||
n += k;
|
||||
}
|
||||
|
||||
if (n > s->s3->tmp.key_block_length) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(mac_secret, ms, i);
|
||||
|
||||
if (!(EVP_CIPHER_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER)) {
|
||||
/* TODO(size_t): Convert this function */
|
||||
mac_key = EVP_PKEY_new_mac_key(mac_type, NULL, mac_secret,
|
||||
(int)*mac_secret_size);
|
||||
if (mac_key == NULL
|
||||
|| EVP_DigestSignInit(mac_ctx, NULL, m, NULL, mac_key) <= 0) {
|
||||
EVP_PKEY_free(mac_key);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
EVP_PKEY_free(mac_key);
|
||||
}
|
||||
#ifdef SSL_DEBUG
|
||||
printf("which = %04X\nmac key=", which);
|
||||
{
|
||||
size_t z;
|
||||
for (z = 0; z < i; z++)
|
||||
printf("%02X%c", ms[z], ((z + 1) % 16) ? ' ' : '\n');
|
||||
}
|
||||
#endif
|
||||
|
||||
if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) {
|
||||
if (!EVP_CipherInit_ex(dd, c, NULL, key, NULL, (which & SSL3_CC_WRITE))
|
||||
|| !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, (int)k,
|
||||
iv)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
} else if (EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE) {
|
||||
int taglen;
|
||||
if (s->s3->tmp.
|
||||
new_cipher->algorithm_enc & (SSL_AES128CCM8 | SSL_AES256CCM8))
|
||||
taglen = EVP_CCM8_TLS_TAG_LEN;
|
||||
else
|
||||
taglen = EVP_CCM_TLS_TAG_LEN;
|
||||
if (!EVP_CipherInit_ex(dd, c, NULL, NULL, NULL, (which & SSL3_CC_WRITE))
|
||||
|| !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)
|
||||
|| !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_TAG, taglen, NULL)
|
||||
|| !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_CCM_SET_IV_FIXED, (int)k, iv)
|
||||
|| !EVP_CipherInit_ex(dd, NULL, NULL, key, NULL, -1)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE))) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */
|
||||
if ((EVP_CIPHER_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size
|
||||
&& !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_MAC_KEY,
|
||||
(int)*mac_secret_size, mac_secret)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
|
||||
|
||||
#ifdef SSL_DEBUG
|
||||
printf("which = %04X\nkey=", which);
|
||||
{
|
||||
int z;
|
||||
for (z = 0; z < EVP_CIPHER_key_length(c); z++)
|
||||
printf("%02X%c", key[z], ((z + 1) % 16) ? ' ' : '\n');
|
||||
}
|
||||
printf("\niv=");
|
||||
{
|
||||
size_t z;
|
||||
for (z = 0; z < k; z++)
|
||||
printf("%02X%c", iv[z], ((z + 1) % 16) ? ' ' : '\n');
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls1_setup_key_block(SSL *s)
|
||||
{
|
||||
unsigned char *p;
|
||||
const EVP_CIPHER *c;
|
||||
const EVP_MD *hash;
|
||||
SSL_COMP *comp;
|
||||
int mac_type = NID_undef;
|
||||
size_t num, mac_secret_size = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (s->s3->tmp.key_block_length != 0)
|
||||
return 1;
|
||||
|
||||
if (!ssl_cipher_get_evp(s->session, &c, &hash, &mac_type, &mac_secret_size,
|
||||
&comp, s->ext.use_etm)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_SETUP_KEY_BLOCK,
|
||||
SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->s3->tmp.new_sym_enc = c;
|
||||
s->s3->tmp.new_hash = hash;
|
||||
s->s3->tmp.new_mac_pkey_type = mac_type;
|
||||
s->s3->tmp.new_mac_secret_size = mac_secret_size;
|
||||
num = EVP_CIPHER_key_length(c) + mac_secret_size + EVP_CIPHER_iv_length(c);
|
||||
num *= 2;
|
||||
|
||||
ssl3_cleanup_key_block(s);
|
||||
|
||||
if ((p = OPENSSL_malloc(num)) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_SETUP_KEY_BLOCK,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->s3->tmp.key_block_length = num;
|
||||
s->s3->tmp.key_block = p;
|
||||
|
||||
#ifdef SSL_DEBUG
|
||||
printf("client random\n");
|
||||
{
|
||||
int z;
|
||||
for (z = 0; z < SSL3_RANDOM_SIZE; z++)
|
||||
printf("%02X%c", s->s3->client_random[z],
|
||||
((z + 1) % 16) ? ' ' : '\n');
|
||||
}
|
||||
printf("server random\n");
|
||||
{
|
||||
int z;
|
||||
for (z = 0; z < SSL3_RANDOM_SIZE; z++)
|
||||
printf("%02X%c", s->s3->server_random[z],
|
||||
((z + 1) % 16) ? ' ' : '\n');
|
||||
}
|
||||
printf("master key\n");
|
||||
{
|
||||
size_t z;
|
||||
for (z = 0; z < s->session->master_key_length; z++)
|
||||
printf("%02X%c", s->session->master_key[z],
|
||||
((z + 1) % 16) ? ' ' : '\n');
|
||||
}
|
||||
#endif
|
||||
if (!tls1_generate_key_block(s, p, num)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
#ifdef SSL_DEBUG
|
||||
printf("\nkey block\n");
|
||||
{
|
||||
size_t z;
|
||||
for (z = 0; z < num; z++)
|
||||
printf("%02X%c", p[z], ((z + 1) % 16) ? ' ' : '\n');
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)
|
||||
&& s->method->version <= TLS1_VERSION) {
|
||||
/*
|
||||
* enable vulnerability countermeasure for CBC ciphers with known-IV
|
||||
* problem (http://www.openssl.org/~bodo/tls-cbc.txt)
|
||||
*/
|
||||
s->s3->need_empty_fragments = 1;
|
||||
|
||||
if (s->session->cipher != NULL) {
|
||||
if (s->session->cipher->algorithm_enc == SSL_eNULL)
|
||||
s->s3->need_empty_fragments = 0;
|
||||
|
||||
#ifndef OPENSSL_NO_RC4
|
||||
if (s->session->cipher->algorithm_enc == SSL_RC4)
|
||||
s->s3->need_empty_fragments = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t tls1_final_finish_mac(SSL *s, const char *str, size_t slen,
|
||||
unsigned char *out)
|
||||
{
|
||||
size_t hashlen;
|
||||
unsigned char hash[EVP_MAX_MD_SIZE];
|
||||
|
||||
if (!ssl3_digest_cached_records(s, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!tls1_PRF(s, str, slen, hash, hashlen, NULL, 0, NULL, 0, NULL, 0,
|
||||
s->session->master_key, s->session->master_key_length,
|
||||
out, TLS1_FINISH_MAC_LENGTH, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_cleanse(hash, hashlen);
|
||||
return TLS1_FINISH_MAC_LENGTH;
|
||||
}
|
||||
|
||||
int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
|
||||
size_t len, size_t *secret_size)
|
||||
{
|
||||
if (s->session->flags & SSL_SESS_FLAG_EXTMS) {
|
||||
unsigned char hash[EVP_MAX_MD_SIZE * 2];
|
||||
size_t hashlen;
|
||||
/*
|
||||
* Digest cached records keeping record buffer (if present): this wont
|
||||
* affect client auth because we're freezing the buffer at the same
|
||||
* point (after client key exchange and before certificate verify)
|
||||
*/
|
||||
if (!ssl3_digest_cached_records(s, 1)
|
||||
|| !ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
#ifdef SSL_DEBUG
|
||||
fprintf(stderr, "Handshake hashes:\n");
|
||||
BIO_dump_fp(stderr, (char *)hash, hashlen);
|
||||
#endif
|
||||
if (!tls1_PRF(s,
|
||||
TLS_MD_EXTENDED_MASTER_SECRET_CONST,
|
||||
TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE,
|
||||
hash, hashlen,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
NULL, 0, p, len, out,
|
||||
SSL3_MASTER_SECRET_SIZE, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_cleanse(hash, hashlen);
|
||||
} else {
|
||||
if (!tls1_PRF(s,
|
||||
TLS_MD_MASTER_SECRET_CONST,
|
||||
TLS_MD_MASTER_SECRET_CONST_SIZE,
|
||||
s->s3->client_random, SSL3_RANDOM_SIZE,
|
||||
NULL, 0,
|
||||
s->s3->server_random, SSL3_RANDOM_SIZE,
|
||||
NULL, 0, p, len, out,
|
||||
SSL3_MASTER_SECRET_SIZE, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#ifdef SSL_DEBUG
|
||||
fprintf(stderr, "Premaster Secret:\n");
|
||||
BIO_dump_fp(stderr, (char *)p, len);
|
||||
fprintf(stderr, "Client Random:\n");
|
||||
BIO_dump_fp(stderr, (char *)s->s3->client_random, SSL3_RANDOM_SIZE);
|
||||
fprintf(stderr, "Server Random:\n");
|
||||
BIO_dump_fp(stderr, (char *)s->s3->server_random, SSL3_RANDOM_SIZE);
|
||||
fprintf(stderr, "Master Secret:\n");
|
||||
BIO_dump_fp(stderr, (char *)s->session->master_key,
|
||||
SSL3_MASTER_SECRET_SIZE);
|
||||
#endif
|
||||
|
||||
*secret_size = SSL3_MASTER_SECRET_SIZE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
|
||||
const char *label, size_t llen,
|
||||
const unsigned char *context,
|
||||
size_t contextlen, int use_context)
|
||||
{
|
||||
unsigned char *val = NULL;
|
||||
size_t vallen = 0, currentvalpos;
|
||||
int rv;
|
||||
|
||||
/*
|
||||
* construct PRF arguments we construct the PRF argument ourself rather
|
||||
* than passing separate values into the TLS PRF to ensure that the
|
||||
* concatenation of values does not create a prohibited label.
|
||||
*/
|
||||
vallen = llen + SSL3_RANDOM_SIZE * 2;
|
||||
if (use_context) {
|
||||
vallen += 2 + contextlen;
|
||||
}
|
||||
|
||||
val = OPENSSL_malloc(vallen);
|
||||
if (val == NULL)
|
||||
goto err2;
|
||||
currentvalpos = 0;
|
||||
memcpy(val + currentvalpos, (unsigned char *)label, llen);
|
||||
currentvalpos += llen;
|
||||
memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE);
|
||||
currentvalpos += SSL3_RANDOM_SIZE;
|
||||
memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE);
|
||||
currentvalpos += SSL3_RANDOM_SIZE;
|
||||
|
||||
if (use_context) {
|
||||
val[currentvalpos] = (contextlen >> 8) & 0xff;
|
||||
currentvalpos++;
|
||||
val[currentvalpos] = contextlen & 0xff;
|
||||
currentvalpos++;
|
||||
if ((contextlen > 0) || (context != NULL)) {
|
||||
memcpy(val + currentvalpos, context, contextlen);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* disallow prohibited labels note that SSL3_RANDOM_SIZE > max(prohibited
|
||||
* label len) = 15, so size of val > max(prohibited label len) = 15 and
|
||||
* the comparisons won't have buffer overflow
|
||||
*/
|
||||
if (memcmp(val, TLS_MD_CLIENT_FINISH_CONST,
|
||||
TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0)
|
||||
goto err1;
|
||||
if (memcmp(val, TLS_MD_SERVER_FINISH_CONST,
|
||||
TLS_MD_SERVER_FINISH_CONST_SIZE) == 0)
|
||||
goto err1;
|
||||
if (memcmp(val, TLS_MD_MASTER_SECRET_CONST,
|
||||
TLS_MD_MASTER_SECRET_CONST_SIZE) == 0)
|
||||
goto err1;
|
||||
if (memcmp(val, TLS_MD_EXTENDED_MASTER_SECRET_CONST,
|
||||
TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE) == 0)
|
||||
goto err1;
|
||||
if (memcmp(val, TLS_MD_KEY_EXPANSION_CONST,
|
||||
TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0)
|
||||
goto err1;
|
||||
|
||||
rv = tls1_PRF(s,
|
||||
val, vallen,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
s->session->master_key, s->session->master_key_length,
|
||||
out, olen, 0);
|
||||
|
||||
goto ret;
|
||||
err1:
|
||||
SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
|
||||
rv = 0;
|
||||
goto ret;
|
||||
err2:
|
||||
SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, ERR_R_MALLOC_FAILURE);
|
||||
rv = 0;
|
||||
ret:
|
||||
OPENSSL_clear_free(val, vallen);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int tls1_alert_code(int code)
|
||||
{
|
||||
switch (code) {
|
||||
case SSL_AD_CLOSE_NOTIFY:
|
||||
return SSL3_AD_CLOSE_NOTIFY;
|
||||
case SSL_AD_UNEXPECTED_MESSAGE:
|
||||
return SSL3_AD_UNEXPECTED_MESSAGE;
|
||||
case SSL_AD_BAD_RECORD_MAC:
|
||||
return SSL3_AD_BAD_RECORD_MAC;
|
||||
case SSL_AD_DECRYPTION_FAILED:
|
||||
return TLS1_AD_DECRYPTION_FAILED;
|
||||
case SSL_AD_RECORD_OVERFLOW:
|
||||
return TLS1_AD_RECORD_OVERFLOW;
|
||||
case SSL_AD_DECOMPRESSION_FAILURE:
|
||||
return SSL3_AD_DECOMPRESSION_FAILURE;
|
||||
case SSL_AD_HANDSHAKE_FAILURE:
|
||||
return SSL3_AD_HANDSHAKE_FAILURE;
|
||||
case SSL_AD_NO_CERTIFICATE:
|
||||
return -1;
|
||||
case SSL_AD_BAD_CERTIFICATE:
|
||||
return SSL3_AD_BAD_CERTIFICATE;
|
||||
case SSL_AD_UNSUPPORTED_CERTIFICATE:
|
||||
return SSL3_AD_UNSUPPORTED_CERTIFICATE;
|
||||
case SSL_AD_CERTIFICATE_REVOKED:
|
||||
return SSL3_AD_CERTIFICATE_REVOKED;
|
||||
case SSL_AD_CERTIFICATE_EXPIRED:
|
||||
return SSL3_AD_CERTIFICATE_EXPIRED;
|
||||
case SSL_AD_CERTIFICATE_UNKNOWN:
|
||||
return SSL3_AD_CERTIFICATE_UNKNOWN;
|
||||
case SSL_AD_ILLEGAL_PARAMETER:
|
||||
return SSL3_AD_ILLEGAL_PARAMETER;
|
||||
case SSL_AD_UNKNOWN_CA:
|
||||
return TLS1_AD_UNKNOWN_CA;
|
||||
case SSL_AD_ACCESS_DENIED:
|
||||
return TLS1_AD_ACCESS_DENIED;
|
||||
case SSL_AD_DECODE_ERROR:
|
||||
return TLS1_AD_DECODE_ERROR;
|
||||
case SSL_AD_DECRYPT_ERROR:
|
||||
return TLS1_AD_DECRYPT_ERROR;
|
||||
case SSL_AD_EXPORT_RESTRICTION:
|
||||
return TLS1_AD_EXPORT_RESTRICTION;
|
||||
case SSL_AD_PROTOCOL_VERSION:
|
||||
return TLS1_AD_PROTOCOL_VERSION;
|
||||
case SSL_AD_INSUFFICIENT_SECURITY:
|
||||
return TLS1_AD_INSUFFICIENT_SECURITY;
|
||||
case SSL_AD_INTERNAL_ERROR:
|
||||
return TLS1_AD_INTERNAL_ERROR;
|
||||
case SSL_AD_USER_CANCELLED:
|
||||
return TLS1_AD_USER_CANCELLED;
|
||||
case SSL_AD_NO_RENEGOTIATION:
|
||||
return TLS1_AD_NO_RENEGOTIATION;
|
||||
case SSL_AD_UNSUPPORTED_EXTENSION:
|
||||
return TLS1_AD_UNSUPPORTED_EXTENSION;
|
||||
case SSL_AD_CERTIFICATE_UNOBTAINABLE:
|
||||
return TLS1_AD_CERTIFICATE_UNOBTAINABLE;
|
||||
case SSL_AD_UNRECOGNIZED_NAME:
|
||||
return TLS1_AD_UNRECOGNIZED_NAME;
|
||||
case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
|
||||
return TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
|
||||
case SSL_AD_BAD_CERTIFICATE_HASH_VALUE:
|
||||
return TLS1_AD_BAD_CERTIFICATE_HASH_VALUE;
|
||||
case SSL_AD_UNKNOWN_PSK_IDENTITY:
|
||||
return TLS1_AD_UNKNOWN_PSK_IDENTITY;
|
||||
case SSL_AD_INAPPROPRIATE_FALLBACK:
|
||||
return TLS1_AD_INAPPROPRIATE_FALLBACK;
|
||||
case SSL_AD_NO_APPLICATION_PROTOCOL:
|
||||
return TLS1_AD_NO_APPLICATION_PROTOCOL;
|
||||
case SSL_AD_CERTIFICATE_REQUIRED:
|
||||
return SSL_AD_HANDSHAKE_FAILURE;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
2792
trunk/3rdparty/openssl-1.1-fit/ssl/t1_lib.c
vendored
Normal file
2792
trunk/3rdparty/openssl-1.1-fit/ssl/t1_lib.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
1566
trunk/3rdparty/openssl-1.1-fit/ssl/t1_trce.c
vendored
Normal file
1566
trunk/3rdparty/openssl-1.1-fit/ssl/t1_trce.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
833
trunk/3rdparty/openssl-1.1-fit/ssl/tls13_enc.c
vendored
Normal file
833
trunk/3rdparty/openssl-1.1-fit/ssl/tls13_enc.c
vendored
Normal file
|
@ -0,0 +1,833 @@
|
|||
/*
|
||||
* Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "ssl_locl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/kdf.h>
|
||||
|
||||
#define TLS13_MAX_LABEL_LEN 249
|
||||
|
||||
/* Always filled with zeros */
|
||||
static const unsigned char default_zeros[EVP_MAX_MD_SIZE];
|
||||
|
||||
/*
|
||||
* Given a |secret|; a |label| of length |labellen|; and |data| of length
|
||||
* |datalen| (e.g. typically a hash of the handshake messages), derive a new
|
||||
* secret |outlen| bytes long and store it in the location pointed to be |out|.
|
||||
* The |data| value may be zero length. Any errors will be treated as fatal if
|
||||
* |fatal| is set. Returns 1 on success 0 on failure.
|
||||
*/
|
||||
int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret,
|
||||
const unsigned char *label, size_t labellen,
|
||||
const unsigned char *data, size_t datalen,
|
||||
unsigned char *out, size_t outlen, int fatal)
|
||||
{
|
||||
static const unsigned char label_prefix[] = "tls13 ";
|
||||
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
|
||||
int ret;
|
||||
size_t hkdflabellen;
|
||||
size_t hashlen;
|
||||
/*
|
||||
* 2 bytes for length of derived secret + 1 byte for length of combined
|
||||
* prefix and label + bytes for the label itself + 1 byte length of hash
|
||||
* + bytes for the hash itself
|
||||
*/
|
||||
unsigned char hkdflabel[sizeof(uint16_t) + sizeof(uint8_t) +
|
||||
+ (sizeof(label_prefix) - 1) + TLS13_MAX_LABEL_LEN
|
||||
+ 1 + EVP_MAX_MD_SIZE];
|
||||
WPACKET pkt;
|
||||
|
||||
if (pctx == NULL)
|
||||
return 0;
|
||||
|
||||
if (labellen > TLS13_MAX_LABEL_LEN) {
|
||||
if (fatal) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
} else {
|
||||
/*
|
||||
* Probably we have been called from SSL_export_keying_material(),
|
||||
* or SSL_export_keying_material_early().
|
||||
*/
|
||||
SSLerr(SSL_F_TLS13_HKDF_EXPAND, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
|
||||
}
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
hashlen = EVP_MD_size(md);
|
||||
|
||||
if (!WPACKET_init_static_len(&pkt, hkdflabel, sizeof(hkdflabel), 0)
|
||||
|| !WPACKET_put_bytes_u16(&pkt, outlen)
|
||||
|| !WPACKET_start_sub_packet_u8(&pkt)
|
||||
|| !WPACKET_memcpy(&pkt, label_prefix, sizeof(label_prefix) - 1)
|
||||
|| !WPACKET_memcpy(&pkt, label, labellen)
|
||||
|| !WPACKET_close(&pkt)
|
||||
|| !WPACKET_sub_memcpy_u8(&pkt, data, (data == NULL) ? 0 : datalen)
|
||||
|| !WPACKET_get_total_written(&pkt, &hkdflabellen)
|
||||
|| !WPACKET_finish(&pkt)) {
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
WPACKET_cleanup(&pkt);
|
||||
if (fatal)
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
else
|
||||
SSLerr(SSL_F_TLS13_HKDF_EXPAND, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = EVP_PKEY_derive_init(pctx) <= 0
|
||||
|| EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY)
|
||||
<= 0
|
||||
|| EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0
|
||||
|| EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, hashlen) <= 0
|
||||
|| EVP_PKEY_CTX_add1_hkdf_info(pctx, hkdflabel, hkdflabellen) <= 0
|
||||
|| EVP_PKEY_derive(pctx, out, &outlen) <= 0;
|
||||
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
|
||||
if (ret != 0) {
|
||||
if (fatal)
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
else
|
||||
SSLerr(SSL_F_TLS13_HKDF_EXPAND, ERR_R_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a |secret| generate a |key| of length |keylen| bytes. Returns 1 on
|
||||
* success 0 on failure.
|
||||
*/
|
||||
int tls13_derive_key(SSL *s, const EVP_MD *md, const unsigned char *secret,
|
||||
unsigned char *key, size_t keylen)
|
||||
{
|
||||
static const unsigned char keylabel[] = "key";
|
||||
|
||||
return tls13_hkdf_expand(s, md, secret, keylabel, sizeof(keylabel) - 1,
|
||||
NULL, 0, key, keylen, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a |secret| generate an |iv| of length |ivlen| bytes. Returns 1 on
|
||||
* success 0 on failure.
|
||||
*/
|
||||
int tls13_derive_iv(SSL *s, const EVP_MD *md, const unsigned char *secret,
|
||||
unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
static const unsigned char ivlabel[] = "iv";
|
||||
|
||||
return tls13_hkdf_expand(s, md, secret, ivlabel, sizeof(ivlabel) - 1,
|
||||
NULL, 0, iv, ivlen, 1);
|
||||
}
|
||||
|
||||
int tls13_derive_finishedkey(SSL *s, const EVP_MD *md,
|
||||
const unsigned char *secret,
|
||||
unsigned char *fin, size_t finlen)
|
||||
{
|
||||
static const unsigned char finishedlabel[] = "finished";
|
||||
|
||||
return tls13_hkdf_expand(s, md, secret, finishedlabel,
|
||||
sizeof(finishedlabel) - 1, NULL, 0, fin, finlen, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the previous secret |prevsecret| and a new input secret |insecret| of
|
||||
* length |insecretlen|, generate a new secret and store it in the location
|
||||
* pointed to by |outsecret|. Returns 1 on success 0 on failure.
|
||||
*/
|
||||
int tls13_generate_secret(SSL *s, const EVP_MD *md,
|
||||
const unsigned char *prevsecret,
|
||||
const unsigned char *insecret,
|
||||
size_t insecretlen,
|
||||
unsigned char *outsecret)
|
||||
{
|
||||
size_t mdlen, prevsecretlen;
|
||||
int mdleni;
|
||||
int ret;
|
||||
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
|
||||
static const char derived_secret_label[] = "derived";
|
||||
unsigned char preextractsec[EVP_MAX_MD_SIZE];
|
||||
|
||||
if (pctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mdleni = EVP_MD_size(md);
|
||||
/* Ensure cast to size_t is safe */
|
||||
if (!ossl_assert(mdleni >= 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
mdlen = (size_t)mdleni;
|
||||
|
||||
if (insecret == NULL) {
|
||||
insecret = default_zeros;
|
||||
insecretlen = mdlen;
|
||||
}
|
||||
if (prevsecret == NULL) {
|
||||
prevsecret = default_zeros;
|
||||
prevsecretlen = 0;
|
||||
} else {
|
||||
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
|
||||
unsigned char hash[EVP_MAX_MD_SIZE];
|
||||
|
||||
/* The pre-extract derive step uses a hash of no messages */
|
||||
if (mctx == NULL
|
||||
|| EVP_DigestInit_ex(mctx, md, NULL) <= 0
|
||||
|| EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
EVP_MD_CTX_free(mctx);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return 0;
|
||||
}
|
||||
EVP_MD_CTX_free(mctx);
|
||||
|
||||
/* Generate the pre-extract secret */
|
||||
if (!tls13_hkdf_expand(s, md, prevsecret,
|
||||
(unsigned char *)derived_secret_label,
|
||||
sizeof(derived_secret_label) - 1, hash, mdlen,
|
||||
preextractsec, mdlen, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
prevsecret = preextractsec;
|
||||
prevsecretlen = mdlen;
|
||||
}
|
||||
|
||||
ret = EVP_PKEY_derive_init(pctx) <= 0
|
||||
|| EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY)
|
||||
<= 0
|
||||
|| EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0
|
||||
|| EVP_PKEY_CTX_set1_hkdf_key(pctx, insecret, insecretlen) <= 0
|
||||
|| EVP_PKEY_CTX_set1_hkdf_salt(pctx, prevsecret, prevsecretlen)
|
||||
<= 0
|
||||
|| EVP_PKEY_derive(pctx, outsecret, &mdlen)
|
||||
<= 0;
|
||||
|
||||
if (ret != 0)
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
if (prevsecret == preextractsec)
|
||||
OPENSSL_cleanse(preextractsec, mdlen);
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an input secret |insecret| of length |insecretlen| generate the
|
||||
* handshake secret. This requires the early secret to already have been
|
||||
* generated. Returns 1 on success 0 on failure.
|
||||
*/
|
||||
int tls13_generate_handshake_secret(SSL *s, const unsigned char *insecret,
|
||||
size_t insecretlen)
|
||||
{
|
||||
/* Calls SSLfatal() if required */
|
||||
return tls13_generate_secret(s, ssl_handshake_md(s), s->early_secret,
|
||||
insecret, insecretlen,
|
||||
(unsigned char *)&s->handshake_secret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the handshake secret |prev| of length |prevlen| generate the master
|
||||
* secret and store its length in |*secret_size|. Returns 1 on success 0 on
|
||||
* failure.
|
||||
*/
|
||||
int tls13_generate_master_secret(SSL *s, unsigned char *out,
|
||||
unsigned char *prev, size_t prevlen,
|
||||
size_t *secret_size)
|
||||
{
|
||||
const EVP_MD *md = ssl_handshake_md(s);
|
||||
|
||||
*secret_size = EVP_MD_size(md);
|
||||
/* Calls SSLfatal() if required */
|
||||
return tls13_generate_secret(s, md, prev, NULL, 0, out);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates the mac for the Finished message. Returns the length of the MAC or
|
||||
* 0 on error.
|
||||
*/
|
||||
size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
|
||||
unsigned char *out)
|
||||
{
|
||||
const EVP_MD *md = ssl_handshake_md(s);
|
||||
unsigned char hash[EVP_MAX_MD_SIZE];
|
||||
size_t hashlen, ret = 0;
|
||||
EVP_PKEY *key = NULL;
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
|
||||
if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (str == s->method->ssl3_enc->server_finished_label) {
|
||||
key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
|
||||
s->server_finished_secret, hashlen);
|
||||
} else if (SSL_IS_FIRST_HANDSHAKE(s)) {
|
||||
key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
|
||||
s->client_finished_secret, hashlen);
|
||||
} else {
|
||||
unsigned char finsecret[EVP_MAX_MD_SIZE];
|
||||
|
||||
if (!tls13_derive_finishedkey(s, ssl_handshake_md(s),
|
||||
s->client_app_traffic_secret,
|
||||
finsecret, hashlen))
|
||||
goto err;
|
||||
|
||||
key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finsecret,
|
||||
hashlen);
|
||||
OPENSSL_cleanse(finsecret, sizeof(finsecret));
|
||||
}
|
||||
|
||||
if (key == NULL
|
||||
|| ctx == NULL
|
||||
|| EVP_DigestSignInit(ctx, NULL, md, NULL, key) <= 0
|
||||
|| EVP_DigestSignUpdate(ctx, hash, hashlen) <= 0
|
||||
|| EVP_DigestSignFinal(ctx, out, &hashlen) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_FINAL_FINISH_MAC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = hashlen;
|
||||
err:
|
||||
EVP_PKEY_free(key);
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* There isn't really a key block in TLSv1.3, but we still need this function
|
||||
* for initialising the cipher and hash. Returns 1 on success or 0 on failure.
|
||||
*/
|
||||
int tls13_setup_key_block(SSL *s)
|
||||
{
|
||||
const EVP_CIPHER *c;
|
||||
const EVP_MD *hash;
|
||||
|
||||
s->session->cipher = s->s3->tmp.new_cipher;
|
||||
if (!ssl_cipher_get_evp(s->session, &c, &hash, NULL, NULL, NULL, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_SETUP_KEY_BLOCK,
|
||||
SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->s3->tmp.new_sym_enc = c;
|
||||
s->s3->tmp.new_hash = hash;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int derive_secret_key_and_iv(SSL *s, int sending, const EVP_MD *md,
|
||||
const EVP_CIPHER *ciph,
|
||||
const unsigned char *insecret,
|
||||
const unsigned char *hash,
|
||||
const unsigned char *label,
|
||||
size_t labellen, unsigned char *secret,
|
||||
unsigned char *iv, EVP_CIPHER_CTX *ciph_ctx)
|
||||
{
|
||||
unsigned char key[EVP_MAX_KEY_LENGTH];
|
||||
size_t ivlen, keylen, taglen;
|
||||
int hashleni = EVP_MD_size(md);
|
||||
size_t hashlen;
|
||||
|
||||
/* Ensure cast to size_t is safe */
|
||||
if (!ossl_assert(hashleni >= 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DERIVE_SECRET_KEY_AND_IV,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
hashlen = (size_t)hashleni;
|
||||
|
||||
if (!tls13_hkdf_expand(s, md, insecret, label, labellen, hash, hashlen,
|
||||
secret, hashlen, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* TODO(size_t): convert me */
|
||||
keylen = EVP_CIPHER_key_length(ciph);
|
||||
if (EVP_CIPHER_mode(ciph) == EVP_CIPH_CCM_MODE) {
|
||||
uint32_t algenc;
|
||||
|
||||
ivlen = EVP_CCM_TLS_IV_LEN;
|
||||
if (s->s3->tmp.new_cipher == NULL) {
|
||||
/* We've not selected a cipher yet - we must be doing early data */
|
||||
algenc = s->session->cipher->algorithm_enc;
|
||||
} else {
|
||||
algenc = s->s3->tmp.new_cipher->algorithm_enc;
|
||||
}
|
||||
if (algenc & (SSL_AES128CCM8 | SSL_AES256CCM8))
|
||||
taglen = EVP_CCM8_TLS_TAG_LEN;
|
||||
else
|
||||
taglen = EVP_CCM_TLS_TAG_LEN;
|
||||
} else {
|
||||
ivlen = EVP_CIPHER_iv_length(ciph);
|
||||
taglen = 0;
|
||||
}
|
||||
|
||||
if (!tls13_derive_key(s, md, secret, key, keylen)
|
||||
|| !tls13_derive_iv(s, md, secret, iv, ivlen)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_CipherInit_ex(ciph_ctx, ciph, NULL, NULL, NULL, sending) <= 0
|
||||
|| !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL)
|
||||
|| (taglen != 0 && !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG,
|
||||
taglen, NULL))
|
||||
|| EVP_CipherInit_ex(ciph_ctx, NULL, NULL, key, NULL, -1) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DERIVE_SECRET_KEY_AND_IV,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 1;
|
||||
err:
|
||||
OPENSSL_cleanse(key, sizeof(key));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls13_change_cipher_state(SSL *s, int which)
|
||||
{
|
||||
static const unsigned char client_early_traffic[] = "c e traffic";
|
||||
static const unsigned char client_handshake_traffic[] = "c hs traffic";
|
||||
static const unsigned char client_application_traffic[] = "c ap traffic";
|
||||
static const unsigned char server_handshake_traffic[] = "s hs traffic";
|
||||
static const unsigned char server_application_traffic[] = "s ap traffic";
|
||||
static const unsigned char exporter_master_secret[] = "exp master";
|
||||
static const unsigned char resumption_master_secret[] = "res master";
|
||||
static const unsigned char early_exporter_master_secret[] = "e exp master";
|
||||
unsigned char *iv;
|
||||
unsigned char secret[EVP_MAX_MD_SIZE];
|
||||
unsigned char hashval[EVP_MAX_MD_SIZE];
|
||||
unsigned char *hash = hashval;
|
||||
unsigned char *insecret;
|
||||
unsigned char *finsecret = NULL;
|
||||
const char *log_label = NULL;
|
||||
EVP_CIPHER_CTX *ciph_ctx;
|
||||
size_t finsecretlen = 0;
|
||||
const unsigned char *label;
|
||||
size_t labellen, hashlen = 0;
|
||||
int ret = 0;
|
||||
const EVP_MD *md = NULL;
|
||||
const EVP_CIPHER *cipher = NULL;
|
||||
|
||||
if (which & SSL3_CC_READ) {
|
||||
if (s->enc_read_ctx != NULL) {
|
||||
EVP_CIPHER_CTX_reset(s->enc_read_ctx);
|
||||
} else {
|
||||
s->enc_read_ctx = EVP_CIPHER_CTX_new();
|
||||
if (s->enc_read_ctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
ciph_ctx = s->enc_read_ctx;
|
||||
iv = s->read_iv;
|
||||
|
||||
RECORD_LAYER_reset_read_sequence(&s->rlayer);
|
||||
} else {
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
|
||||
if (s->enc_write_ctx != NULL) {
|
||||
EVP_CIPHER_CTX_reset(s->enc_write_ctx);
|
||||
} else {
|
||||
s->enc_write_ctx = EVP_CIPHER_CTX_new();
|
||||
if (s->enc_write_ctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
ciph_ctx = s->enc_write_ctx;
|
||||
iv = s->write_iv;
|
||||
|
||||
RECORD_LAYER_reset_write_sequence(&s->rlayer);
|
||||
}
|
||||
|
||||
if (((which & SSL3_CC_CLIENT) && (which & SSL3_CC_WRITE))
|
||||
|| ((which & SSL3_CC_SERVER) && (which & SSL3_CC_READ))) {
|
||||
if (which & SSL3_CC_EARLY) {
|
||||
EVP_MD_CTX *mdctx = NULL;
|
||||
long handlen;
|
||||
void *hdata;
|
||||
unsigned int hashlenui;
|
||||
const SSL_CIPHER *sslcipher = SSL_SESSION_get0_cipher(s->session);
|
||||
|
||||
insecret = s->early_secret;
|
||||
label = client_early_traffic;
|
||||
labellen = sizeof(client_early_traffic) - 1;
|
||||
log_label = CLIENT_EARLY_LABEL;
|
||||
|
||||
handlen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
|
||||
if (handlen <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS13_CHANGE_CIPHER_STATE,
|
||||
SSL_R_BAD_HANDSHAKE_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
|
||||
&& s->max_early_data > 0
|
||||
&& s->session->ext.max_early_data == 0) {
|
||||
/*
|
||||
* If we are attempting to send early data, and we've decided to
|
||||
* actually do it but max_early_data in s->session is 0 then we
|
||||
* must be using an external PSK.
|
||||
*/
|
||||
if (!ossl_assert(s->psksession != NULL
|
||||
&& s->max_early_data ==
|
||||
s->psksession->ext.max_early_data)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS13_CHANGE_CIPHER_STATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
sslcipher = SSL_SESSION_get0_cipher(s->psksession);
|
||||
}
|
||||
if (sslcipher == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS13_CHANGE_CIPHER_STATE, SSL_R_BAD_PSK);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to calculate the handshake digest using the digest from
|
||||
* the session. We haven't yet selected our ciphersuite so we can't
|
||||
* use ssl_handshake_md().
|
||||
*/
|
||||
mdctx = EVP_MD_CTX_new();
|
||||
if (mdctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
cipher = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(sslcipher));
|
||||
md = ssl_md(sslcipher->algorithm2);
|
||||
if (md == NULL || !EVP_DigestInit_ex(mdctx, md, NULL)
|
||||
|| !EVP_DigestUpdate(mdctx, hdata, handlen)
|
||||
|| !EVP_DigestFinal_ex(mdctx, hashval, &hashlenui)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
|
||||
EVP_MD_CTX_free(mdctx);
|
||||
goto err;
|
||||
}
|
||||
hashlen = hashlenui;
|
||||
EVP_MD_CTX_free(mdctx);
|
||||
|
||||
if (!tls13_hkdf_expand(s, md, insecret,
|
||||
early_exporter_master_secret,
|
||||
sizeof(early_exporter_master_secret) - 1,
|
||||
hashval, hashlen,
|
||||
s->early_exporter_master_secret, hashlen,
|
||||
1)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ssl_log_secret(s, EARLY_EXPORTER_SECRET_LABEL,
|
||||
s->early_exporter_master_secret, hashlen)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else if (which & SSL3_CC_HANDSHAKE) {
|
||||
insecret = s->handshake_secret;
|
||||
finsecret = s->client_finished_secret;
|
||||
finsecretlen = EVP_MD_size(ssl_handshake_md(s));
|
||||
label = client_handshake_traffic;
|
||||
labellen = sizeof(client_handshake_traffic) - 1;
|
||||
log_label = CLIENT_HANDSHAKE_LABEL;
|
||||
/*
|
||||
* The handshake hash used for the server read/client write handshake
|
||||
* traffic secret is the same as the hash for the server
|
||||
* write/client read handshake traffic secret. However, if we
|
||||
* processed early data then we delay changing the server
|
||||
* read/client write cipher state until later, and the handshake
|
||||
* hashes have moved on. Therefore we use the value saved earlier
|
||||
* when we did the server write/client read change cipher state.
|
||||
*/
|
||||
hash = s->handshake_traffic_hash;
|
||||
} else {
|
||||
insecret = s->master_secret;
|
||||
label = client_application_traffic;
|
||||
labellen = sizeof(client_application_traffic) - 1;
|
||||
log_label = CLIENT_APPLICATION_LABEL;
|
||||
/*
|
||||
* For this we only use the handshake hashes up until the server
|
||||
* Finished hash. We do not include the client's Finished, which is
|
||||
* what ssl_handshake_hash() would give us. Instead we use the
|
||||
* previously saved value.
|
||||
*/
|
||||
hash = s->server_finished_hash;
|
||||
}
|
||||
} else {
|
||||
/* Early data never applies to client-read/server-write */
|
||||
if (which & SSL3_CC_HANDSHAKE) {
|
||||
insecret = s->handshake_secret;
|
||||
finsecret = s->server_finished_secret;
|
||||
finsecretlen = EVP_MD_size(ssl_handshake_md(s));
|
||||
label = server_handshake_traffic;
|
||||
labellen = sizeof(server_handshake_traffic) - 1;
|
||||
log_label = SERVER_HANDSHAKE_LABEL;
|
||||
} else {
|
||||
insecret = s->master_secret;
|
||||
label = server_application_traffic;
|
||||
labellen = sizeof(server_application_traffic) - 1;
|
||||
log_label = SERVER_APPLICATION_LABEL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(which & SSL3_CC_EARLY)) {
|
||||
md = ssl_handshake_md(s);
|
||||
cipher = s->s3->tmp.new_sym_enc;
|
||||
if (!ssl3_digest_cached_records(s, 1)
|
||||
|| !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) {
|
||||
/* SSLfatal() already called */;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the hash of handshakes up to now for use when we calculate the
|
||||
* client application traffic secret
|
||||
*/
|
||||
if (label == server_application_traffic)
|
||||
memcpy(s->server_finished_hash, hashval, hashlen);
|
||||
|
||||
if (label == server_handshake_traffic)
|
||||
memcpy(s->handshake_traffic_hash, hashval, hashlen);
|
||||
|
||||
if (label == client_application_traffic) {
|
||||
/*
|
||||
* We also create the resumption master secret, but this time use the
|
||||
* hash for the whole handshake including the Client Finished
|
||||
*/
|
||||
if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret,
|
||||
resumption_master_secret,
|
||||
sizeof(resumption_master_secret) - 1,
|
||||
hashval, hashlen, s->resumption_master_secret,
|
||||
hashlen, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, md, cipher,
|
||||
insecret, hash, label, labellen, secret, iv,
|
||||
ciph_ctx)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (label == server_application_traffic) {
|
||||
memcpy(s->server_app_traffic_secret, secret, hashlen);
|
||||
/* Now we create the exporter master secret */
|
||||
if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret,
|
||||
exporter_master_secret,
|
||||
sizeof(exporter_master_secret) - 1,
|
||||
hash, hashlen, s->exporter_master_secret,
|
||||
hashlen, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ssl_log_secret(s, EXPORTER_SECRET_LABEL, s->exporter_master_secret,
|
||||
hashlen)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else if (label == client_application_traffic)
|
||||
memcpy(s->client_app_traffic_secret, secret, hashlen);
|
||||
|
||||
if (!ssl_log_secret(s, log_label, secret, hashlen)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (finsecret != NULL
|
||||
&& !tls13_derive_finishedkey(s, ssl_handshake_md(s), secret,
|
||||
finsecret, finsecretlen)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!s->server && label == client_early_traffic)
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_WRITE_PLAIN_ALERTS;
|
||||
else
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
|
||||
ret = 1;
|
||||
err:
|
||||
OPENSSL_cleanse(secret, sizeof(secret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tls13_update_key(SSL *s, int sending)
|
||||
{
|
||||
static const unsigned char application_traffic[] = "traffic upd";
|
||||
const EVP_MD *md = ssl_handshake_md(s);
|
||||
size_t hashlen = EVP_MD_size(md);
|
||||
unsigned char *insecret, *iv;
|
||||
unsigned char secret[EVP_MAX_MD_SIZE];
|
||||
EVP_CIPHER_CTX *ciph_ctx;
|
||||
int ret = 0;
|
||||
|
||||
if (s->server == sending)
|
||||
insecret = s->server_app_traffic_secret;
|
||||
else
|
||||
insecret = s->client_app_traffic_secret;
|
||||
|
||||
if (sending) {
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
|
||||
iv = s->write_iv;
|
||||
ciph_ctx = s->enc_write_ctx;
|
||||
RECORD_LAYER_reset_write_sequence(&s->rlayer);
|
||||
} else {
|
||||
iv = s->read_iv;
|
||||
ciph_ctx = s->enc_read_ctx;
|
||||
RECORD_LAYER_reset_read_sequence(&s->rlayer);
|
||||
}
|
||||
|
||||
if (!derive_secret_key_and_iv(s, sending, ssl_handshake_md(s),
|
||||
s->s3->tmp.new_sym_enc, insecret, NULL,
|
||||
application_traffic,
|
||||
sizeof(application_traffic) - 1, secret, iv,
|
||||
ciph_ctx)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(insecret, secret, hashlen);
|
||||
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
|
||||
ret = 1;
|
||||
err:
|
||||
OPENSSL_cleanse(secret, sizeof(secret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tls13_alert_code(int code)
|
||||
{
|
||||
/* There are 2 additional alerts in TLSv1.3 compared to TLSv1.2 */
|
||||
if (code == SSL_AD_MISSING_EXTENSION || code == SSL_AD_CERTIFICATE_REQUIRED)
|
||||
return code;
|
||||
|
||||
return tls1_alert_code(code);
|
||||
}
|
||||
|
||||
int tls13_export_keying_material(SSL *s, unsigned char *out, size_t olen,
|
||||
const char *label, size_t llen,
|
||||
const unsigned char *context,
|
||||
size_t contextlen, int use_context)
|
||||
{
|
||||
unsigned char exportsecret[EVP_MAX_MD_SIZE];
|
||||
static const unsigned char exporterlabel[] = "exporter";
|
||||
unsigned char hash[EVP_MAX_MD_SIZE], data[EVP_MAX_MD_SIZE];
|
||||
const EVP_MD *md = ssl_handshake_md(s);
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
unsigned int hashsize, datalen;
|
||||
int ret = 0;
|
||||
|
||||
if (ctx == NULL || !ossl_statem_export_allowed(s))
|
||||
goto err;
|
||||
|
||||
if (!use_context)
|
||||
contextlen = 0;
|
||||
|
||||
if (EVP_DigestInit_ex(ctx, md, NULL) <= 0
|
||||
|| EVP_DigestUpdate(ctx, context, contextlen) <= 0
|
||||
|| EVP_DigestFinal_ex(ctx, hash, &hashsize) <= 0
|
||||
|| EVP_DigestInit_ex(ctx, md, NULL) <= 0
|
||||
|| EVP_DigestFinal_ex(ctx, data, &datalen) <= 0
|
||||
|| !tls13_hkdf_expand(s, md, s->exporter_master_secret,
|
||||
(const unsigned char *)label, llen,
|
||||
data, datalen, exportsecret, hashsize, 0)
|
||||
|| !tls13_hkdf_expand(s, md, exportsecret, exporterlabel,
|
||||
sizeof(exporterlabel) - 1, hash, hashsize,
|
||||
out, olen, 0))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tls13_export_keying_material_early(SSL *s, unsigned char *out, size_t olen,
|
||||
const char *label, size_t llen,
|
||||
const unsigned char *context,
|
||||
size_t contextlen)
|
||||
{
|
||||
static const unsigned char exporterlabel[] = "exporter";
|
||||
unsigned char exportsecret[EVP_MAX_MD_SIZE];
|
||||
unsigned char hash[EVP_MAX_MD_SIZE], data[EVP_MAX_MD_SIZE];
|
||||
const EVP_MD *md;
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
unsigned int hashsize, datalen;
|
||||
int ret = 0;
|
||||
const SSL_CIPHER *sslcipher;
|
||||
|
||||
if (ctx == NULL || !ossl_statem_export_early_allowed(s))
|
||||
goto err;
|
||||
|
||||
if (!s->server && s->max_early_data > 0
|
||||
&& s->session->ext.max_early_data == 0)
|
||||
sslcipher = SSL_SESSION_get0_cipher(s->psksession);
|
||||
else
|
||||
sslcipher = SSL_SESSION_get0_cipher(s->session);
|
||||
|
||||
md = ssl_md(sslcipher->algorithm2);
|
||||
|
||||
/*
|
||||
* Calculate the hash value and store it in |data|. The reason why
|
||||
* the empty string is used is that the definition of TLS-Exporter
|
||||
* is like so:
|
||||
*
|
||||
* TLS-Exporter(label, context_value, key_length) =
|
||||
* HKDF-Expand-Label(Derive-Secret(Secret, label, ""),
|
||||
* "exporter", Hash(context_value), key_length)
|
||||
*
|
||||
* Derive-Secret(Secret, Label, Messages) =
|
||||
* HKDF-Expand-Label(Secret, Label,
|
||||
* Transcript-Hash(Messages), Hash.length)
|
||||
*
|
||||
* Here Transcript-Hash is the cipher suite hash algorithm.
|
||||
*/
|
||||
if (EVP_DigestInit_ex(ctx, md, NULL) <= 0
|
||||
|| EVP_DigestUpdate(ctx, context, contextlen) <= 0
|
||||
|| EVP_DigestFinal_ex(ctx, hash, &hashsize) <= 0
|
||||
|| EVP_DigestInit_ex(ctx, md, NULL) <= 0
|
||||
|| EVP_DigestFinal_ex(ctx, data, &datalen) <= 0
|
||||
|| !tls13_hkdf_expand(s, md, s->early_exporter_master_secret,
|
||||
(const unsigned char *)label, llen,
|
||||
data, datalen, exportsecret, hashsize, 0)
|
||||
|| !tls13_hkdf_expand(s, md, exportsecret, exporterlabel,
|
||||
sizeof(exporterlabel) - 1, hash, hashsize,
|
||||
out, olen, 0))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
456
trunk/3rdparty/openssl-1.1-fit/ssl/tls_srp.c
vendored
Normal file
456
trunk/3rdparty/openssl-1.1-fit/ssl/tls_srp.c
vendored
Normal file
|
@ -0,0 +1,456 @@
|
|||
/*
|
||||
* Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright (c) 2004, EdelKey Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*
|
||||
* Originally written by Christophe Renou and Peter Sylvester,
|
||||
* for the EdelKey project.
|
||||
*/
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
#include "ssl_locl.h"
|
||||
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
# include <openssl/srp.h>
|
||||
|
||||
int SSL_CTX_SRP_CTX_free(struct ssl_ctx_st *ctx)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
OPENSSL_free(ctx->srp_ctx.login);
|
||||
OPENSSL_free(ctx->srp_ctx.info);
|
||||
BN_free(ctx->srp_ctx.N);
|
||||
BN_free(ctx->srp_ctx.g);
|
||||
BN_free(ctx->srp_ctx.s);
|
||||
BN_free(ctx->srp_ctx.B);
|
||||
BN_free(ctx->srp_ctx.A);
|
||||
BN_free(ctx->srp_ctx.a);
|
||||
BN_free(ctx->srp_ctx.b);
|
||||
BN_free(ctx->srp_ctx.v);
|
||||
memset(&ctx->srp_ctx, 0, sizeof(ctx->srp_ctx));
|
||||
ctx->srp_ctx.strength = SRP_MINIMAL_N;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SSL_SRP_CTX_free(struct ssl_st *s)
|
||||
{
|
||||
if (s == NULL)
|
||||
return 0;
|
||||
OPENSSL_free(s->srp_ctx.login);
|
||||
OPENSSL_free(s->srp_ctx.info);
|
||||
BN_free(s->srp_ctx.N);
|
||||
BN_free(s->srp_ctx.g);
|
||||
BN_free(s->srp_ctx.s);
|
||||
BN_free(s->srp_ctx.B);
|
||||
BN_free(s->srp_ctx.A);
|
||||
BN_free(s->srp_ctx.a);
|
||||
BN_free(s->srp_ctx.b);
|
||||
BN_free(s->srp_ctx.v);
|
||||
memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
|
||||
s->srp_ctx.strength = SRP_MINIMAL_N;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SSL_SRP_CTX_init(struct ssl_st *s)
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
|
||||
if ((s == NULL) || ((ctx = s->ctx) == NULL))
|
||||
return 0;
|
||||
|
||||
memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
|
||||
|
||||
s->srp_ctx.SRP_cb_arg = ctx->srp_ctx.SRP_cb_arg;
|
||||
/* set client Hello login callback */
|
||||
s->srp_ctx.TLS_ext_srp_username_callback =
|
||||
ctx->srp_ctx.TLS_ext_srp_username_callback;
|
||||
/* set SRP N/g param callback for verification */
|
||||
s->srp_ctx.SRP_verify_param_callback =
|
||||
ctx->srp_ctx.SRP_verify_param_callback;
|
||||
/* set SRP client passwd callback */
|
||||
s->srp_ctx.SRP_give_srp_client_pwd_callback =
|
||||
ctx->srp_ctx.SRP_give_srp_client_pwd_callback;
|
||||
|
||||
s->srp_ctx.strength = ctx->srp_ctx.strength;
|
||||
|
||||
if (((ctx->srp_ctx.N != NULL) &&
|
||||
((s->srp_ctx.N = BN_dup(ctx->srp_ctx.N)) == NULL)) ||
|
||||
((ctx->srp_ctx.g != NULL) &&
|
||||
((s->srp_ctx.g = BN_dup(ctx->srp_ctx.g)) == NULL)) ||
|
||||
((ctx->srp_ctx.s != NULL) &&
|
||||
((s->srp_ctx.s = BN_dup(ctx->srp_ctx.s)) == NULL)) ||
|
||||
((ctx->srp_ctx.B != NULL) &&
|
||||
((s->srp_ctx.B = BN_dup(ctx->srp_ctx.B)) == NULL)) ||
|
||||
((ctx->srp_ctx.A != NULL) &&
|
||||
((s->srp_ctx.A = BN_dup(ctx->srp_ctx.A)) == NULL)) ||
|
||||
((ctx->srp_ctx.a != NULL) &&
|
||||
((s->srp_ctx.a = BN_dup(ctx->srp_ctx.a)) == NULL)) ||
|
||||
((ctx->srp_ctx.v != NULL) &&
|
||||
((s->srp_ctx.v = BN_dup(ctx->srp_ctx.v)) == NULL)) ||
|
||||
((ctx->srp_ctx.b != NULL) &&
|
||||
((s->srp_ctx.b = BN_dup(ctx->srp_ctx.b)) == NULL))) {
|
||||
SSLerr(SSL_F_SSL_SRP_CTX_INIT, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
if ((ctx->srp_ctx.login != NULL) &&
|
||||
((s->srp_ctx.login = OPENSSL_strdup(ctx->srp_ctx.login)) == NULL)) {
|
||||
SSLerr(SSL_F_SSL_SRP_CTX_INIT, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if ((ctx->srp_ctx.info != NULL) &&
|
||||
((s->srp_ctx.info = BUF_strdup(ctx->srp_ctx.info)) == NULL)) {
|
||||
SSLerr(SSL_F_SSL_SRP_CTX_INIT, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
s->srp_ctx.srp_Mask = ctx->srp_ctx.srp_Mask;
|
||||
|
||||
return 1;
|
||||
err:
|
||||
OPENSSL_free(s->srp_ctx.login);
|
||||
OPENSSL_free(s->srp_ctx.info);
|
||||
BN_free(s->srp_ctx.N);
|
||||
BN_free(s->srp_ctx.g);
|
||||
BN_free(s->srp_ctx.s);
|
||||
BN_free(s->srp_ctx.B);
|
||||
BN_free(s->srp_ctx.A);
|
||||
BN_free(s->srp_ctx.a);
|
||||
BN_free(s->srp_ctx.b);
|
||||
BN_free(s->srp_ctx.v);
|
||||
memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SSL_CTX_SRP_CTX_init(struct ssl_ctx_st *ctx)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
|
||||
memset(&ctx->srp_ctx, 0, sizeof(ctx->srp_ctx));
|
||||
ctx->srp_ctx.strength = SRP_MINIMAL_N;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* server side */
|
||||
int SSL_srp_server_param_with_username(SSL *s, int *ad)
|
||||
{
|
||||
unsigned char b[SSL_MAX_MASTER_KEY_LENGTH];
|
||||
int al;
|
||||
|
||||
*ad = SSL_AD_UNKNOWN_PSK_IDENTITY;
|
||||
if ((s->srp_ctx.TLS_ext_srp_username_callback != NULL) &&
|
||||
((al =
|
||||
s->srp_ctx.TLS_ext_srp_username_callback(s, ad,
|
||||
s->srp_ctx.SRP_cb_arg)) !=
|
||||
SSL_ERROR_NONE))
|
||||
return al;
|
||||
|
||||
*ad = SSL_AD_INTERNAL_ERROR;
|
||||
if ((s->srp_ctx.N == NULL) ||
|
||||
(s->srp_ctx.g == NULL) ||
|
||||
(s->srp_ctx.s == NULL) || (s->srp_ctx.v == NULL))
|
||||
return SSL3_AL_FATAL;
|
||||
|
||||
if (RAND_priv_bytes(b, sizeof(b)) <= 0)
|
||||
return SSL3_AL_FATAL;
|
||||
s->srp_ctx.b = BN_bin2bn(b, sizeof(b), NULL);
|
||||
OPENSSL_cleanse(b, sizeof(b));
|
||||
|
||||
/* Calculate: B = (kv + g^b) % N */
|
||||
|
||||
return ((s->srp_ctx.B =
|
||||
SRP_Calc_B(s->srp_ctx.b, s->srp_ctx.N, s->srp_ctx.g,
|
||||
s->srp_ctx.v)) !=
|
||||
NULL) ? SSL_ERROR_NONE : SSL3_AL_FATAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the server just has the raw password, make up a verifier entry on the
|
||||
* fly
|
||||
*/
|
||||
int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
|
||||
const char *grp)
|
||||
{
|
||||
SRP_gN *GN = SRP_get_default_gN(grp);
|
||||
if (GN == NULL)
|
||||
return -1;
|
||||
s->srp_ctx.N = BN_dup(GN->N);
|
||||
s->srp_ctx.g = BN_dup(GN->g);
|
||||
BN_clear_free(s->srp_ctx.v);
|
||||
s->srp_ctx.v = NULL;
|
||||
BN_clear_free(s->srp_ctx.s);
|
||||
s->srp_ctx.s = NULL;
|
||||
if (!SRP_create_verifier_BN
|
||||
(user, pass, &s->srp_ctx.s, &s->srp_ctx.v, GN->N, GN->g))
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
|
||||
BIGNUM *sa, BIGNUM *v, char *info)
|
||||
{
|
||||
if (N != NULL) {
|
||||
if (s->srp_ctx.N != NULL) {
|
||||
if (!BN_copy(s->srp_ctx.N, N)) {
|
||||
BN_free(s->srp_ctx.N);
|
||||
s->srp_ctx.N = NULL;
|
||||
}
|
||||
} else
|
||||
s->srp_ctx.N = BN_dup(N);
|
||||
}
|
||||
if (g != NULL) {
|
||||
if (s->srp_ctx.g != NULL) {
|
||||
if (!BN_copy(s->srp_ctx.g, g)) {
|
||||
BN_free(s->srp_ctx.g);
|
||||
s->srp_ctx.g = NULL;
|
||||
}
|
||||
} else
|
||||
s->srp_ctx.g = BN_dup(g);
|
||||
}
|
||||
if (sa != NULL) {
|
||||
if (s->srp_ctx.s != NULL) {
|
||||
if (!BN_copy(s->srp_ctx.s, sa)) {
|
||||
BN_free(s->srp_ctx.s);
|
||||
s->srp_ctx.s = NULL;
|
||||
}
|
||||
} else
|
||||
s->srp_ctx.s = BN_dup(sa);
|
||||
}
|
||||
if (v != NULL) {
|
||||
if (s->srp_ctx.v != NULL) {
|
||||
if (!BN_copy(s->srp_ctx.v, v)) {
|
||||
BN_free(s->srp_ctx.v);
|
||||
s->srp_ctx.v = NULL;
|
||||
}
|
||||
} else
|
||||
s->srp_ctx.v = BN_dup(v);
|
||||
}
|
||||
if (info != NULL) {
|
||||
if (s->srp_ctx.info)
|
||||
OPENSSL_free(s->srp_ctx.info);
|
||||
if ((s->srp_ctx.info = BUF_strdup(info)) == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(s->srp_ctx.N) ||
|
||||
!(s->srp_ctx.g) || !(s->srp_ctx.s) || !(s->srp_ctx.v))
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int srp_generate_server_master_secret(SSL *s)
|
||||
{
|
||||
BIGNUM *K = NULL, *u = NULL;
|
||||
int ret = -1, tmp_len = 0;
|
||||
unsigned char *tmp = NULL;
|
||||
|
||||
if (!SRP_Verify_A_mod_N(s->srp_ctx.A, s->srp_ctx.N))
|
||||
goto err;
|
||||
if ((u = SRP_Calc_u(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N)) == NULL)
|
||||
goto err;
|
||||
if ((K = SRP_Calc_server_key(s->srp_ctx.A, s->srp_ctx.v, u, s->srp_ctx.b,
|
||||
s->srp_ctx.N)) == NULL)
|
||||
goto err;
|
||||
|
||||
tmp_len = BN_num_bytes(K);
|
||||
if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
BN_bn2bin(K, tmp);
|
||||
/* Calls SSLfatal() as required */
|
||||
ret = ssl_generate_master_secret(s, tmp, tmp_len, 1);
|
||||
err:
|
||||
BN_clear_free(K);
|
||||
BN_clear_free(u);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* client side */
|
||||
int srp_generate_client_master_secret(SSL *s)
|
||||
{
|
||||
BIGNUM *x = NULL, *u = NULL, *K = NULL;
|
||||
int ret = -1, tmp_len = 0;
|
||||
char *passwd = NULL;
|
||||
unsigned char *tmp = NULL;
|
||||
|
||||
/*
|
||||
* Checks if b % n == 0
|
||||
*/
|
||||
if (SRP_Verify_B_mod_N(s->srp_ctx.B, s->srp_ctx.N) == 0
|
||||
|| (u = SRP_Calc_u(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N))
|
||||
== NULL
|
||||
|| s->srp_ctx.SRP_give_srp_client_pwd_callback == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if ((passwd = s->srp_ctx.SRP_give_srp_client_pwd_callback(s,
|
||||
s->srp_ctx.SRP_cb_arg))
|
||||
== NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET,
|
||||
SSL_R_CALLBACK_FAILED);
|
||||
goto err;
|
||||
}
|
||||
if ((x = SRP_Calc_x(s->srp_ctx.s, s->srp_ctx.login, passwd)) == NULL
|
||||
|| (K = SRP_Calc_client_key(s->srp_ctx.N, s->srp_ctx.B,
|
||||
s->srp_ctx.g, x,
|
||||
s->srp_ctx.a, u)) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
tmp_len = BN_num_bytes(K);
|
||||
if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
BN_bn2bin(K, tmp);
|
||||
/* Calls SSLfatal() as required */
|
||||
ret = ssl_generate_master_secret(s, tmp, tmp_len, 1);
|
||||
err:
|
||||
BN_clear_free(K);
|
||||
BN_clear_free(x);
|
||||
if (passwd != NULL)
|
||||
OPENSSL_clear_free(passwd, strlen(passwd));
|
||||
BN_clear_free(u);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int srp_verify_server_param(SSL *s)
|
||||
{
|
||||
SRP_CTX *srp = &s->srp_ctx;
|
||||
/*
|
||||
* Sanity check parameters: we can quickly check B % N == 0 by checking B
|
||||
* != 0 since B < N
|
||||
*/
|
||||
if (BN_ucmp(srp->g, srp->N) >= 0 || BN_ucmp(srp->B, srp->N) >= 0
|
||||
|| BN_is_zero(srp->B)) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SRP_VERIFY_SERVER_PARAM,
|
||||
SSL_R_BAD_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (BN_num_bits(srp->N) < srp->strength) {
|
||||
SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_F_SRP_VERIFY_SERVER_PARAM,
|
||||
SSL_R_INSUFFICIENT_SECURITY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (srp->SRP_verify_param_callback) {
|
||||
if (srp->SRP_verify_param_callback(s, srp->SRP_cb_arg) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY,
|
||||
SSL_F_SRP_VERIFY_SERVER_PARAM,
|
||||
SSL_R_CALLBACK_FAILED);
|
||||
return 0;
|
||||
}
|
||||
} else if (!SRP_check_known_gN_param(srp->g, srp->N)) {
|
||||
SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_F_SRP_VERIFY_SERVER_PARAM,
|
||||
SSL_R_INSUFFICIENT_SECURITY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SRP_Calc_A_param(SSL *s)
|
||||
{
|
||||
unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH];
|
||||
|
||||
if (RAND_priv_bytes(rnd, sizeof(rnd)) <= 0)
|
||||
return 0;
|
||||
s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a);
|
||||
OPENSSL_cleanse(rnd, sizeof(rnd));
|
||||
|
||||
if (!(s->srp_ctx.A = SRP_Calc_A(s->srp_ctx.a, s->srp_ctx.N, s->srp_ctx.g)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BIGNUM *SSL_get_srp_g(SSL *s)
|
||||
{
|
||||
if (s->srp_ctx.g != NULL)
|
||||
return s->srp_ctx.g;
|
||||
return s->ctx->srp_ctx.g;
|
||||
}
|
||||
|
||||
BIGNUM *SSL_get_srp_N(SSL *s)
|
||||
{
|
||||
if (s->srp_ctx.N != NULL)
|
||||
return s->srp_ctx.N;
|
||||
return s->ctx->srp_ctx.N;
|
||||
}
|
||||
|
||||
char *SSL_get_srp_username(SSL *s)
|
||||
{
|
||||
if (s->srp_ctx.login != NULL)
|
||||
return s->srp_ctx.login;
|
||||
return s->ctx->srp_ctx.login;
|
||||
}
|
||||
|
||||
char *SSL_get_srp_userinfo(SSL *s)
|
||||
{
|
||||
if (s->srp_ctx.info != NULL)
|
||||
return s->srp_ctx.info;
|
||||
return s->ctx->srp_ctx.info;
|
||||
}
|
||||
|
||||
# define tls1_ctx_ctrl ssl3_ctx_ctrl
|
||||
# define tls1_ctx_callback_ctrl ssl3_ctx_callback_ctrl
|
||||
|
||||
int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name)
|
||||
{
|
||||
return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_USERNAME, 0, name);
|
||||
}
|
||||
|
||||
int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password)
|
||||
{
|
||||
return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD, 0, password);
|
||||
}
|
||||
|
||||
int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength)
|
||||
{
|
||||
return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH, strength,
|
||||
NULL);
|
||||
}
|
||||
|
||||
int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx,
|
||||
int (*cb) (SSL *, void *))
|
||||
{
|
||||
return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_SRP_VERIFY_PARAM_CB,
|
||||
(void (*)(void))cb);
|
||||
}
|
||||
|
||||
int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg)
|
||||
{
|
||||
return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_SRP_ARG, 0, arg);
|
||||
}
|
||||
|
||||
int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
|
||||
int (*cb) (SSL *, int *, void *))
|
||||
{
|
||||
return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB,
|
||||
(void (*)(void))cb);
|
||||
}
|
||||
|
||||
int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx,
|
||||
char *(*cb) (SSL *, void *))
|
||||
{
|
||||
return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB,
|
||||
(void (*)(void))cb);
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue