early-access version 2698

This commit is contained in:
pineappleEA
2022-04-24 22:29:35 +02:00
parent c96f949832
commit caa0c2911b
486 changed files with 37806 additions and 14362 deletions

View File

@@ -7,6 +7,7 @@ set(
tls_conninfo.c
tls_keypair.c
tls_server.c
tls_signer.c
tls_ocsp.c
tls_peer.c
tls_util.c
@@ -29,16 +30,28 @@ else()
add_definitions(-DTLS_DEFAULT_CA_FILE=\"${CMAKE_INSTALL_PREFIX}/etc/ssl/cert.pem\")
endif()
add_library(tls ${TLS_SRC})
target_include_directories(tls
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/tls.sym DESTINATION
${CMAKE_CURRENT_BINARY_DIR})
if(LIBTLS_EXTRA_EXPORT)
list(SORT LIBTLS_EXTRA_EXPORT)
foreach(SYM IN LISTS LIBTLS_EXTRA_EXPORT)
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/tls.sym "${SYM}\n")
endforeach()
endif()
add_library(tls_obj OBJECT ${TLS_SRC})
target_include_directories(tls_obj
PRIVATE
.
../include/compat
PUBLIC
../include)
export_symbol(tls ${CMAKE_CURRENT_SOURCE_DIR}/tls.sym)
target_link_libraries(tls ssl crypto ${PLATFORM_LIBS})
add_library(tls $<TARGET_OBJECTS:tls_obj> $<TARGET_OBJECTS:ssl_obj>
$<TARGET_OBJECTS:crypto_obj>)
export_symbol(tls ${CMAKE_CURRENT_BINARY_DIR}/tls.sym)
target_link_libraries(tls ${PLATFORM_LIBS})
if (WIN32)
set(TLS_POSTFIX -${TLS_MAJOR_VERSION})
endif()
@@ -56,3 +69,11 @@ if(ENABLE_LIBRESSL_INSTALL)
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
endif(ENABLE_LIBRESSL_INSTALL)
# build static library for regression test
if(BUILD_SHARED_LIBS)
add_library(tls-static STATIC $<TARGET_OBJECTS:tls_obj>
$<TARGET_OBJECTS:ssl_obj> $<TARGET_OBJECTS:crypto_obj>)
target_link_libraries(tls-static ${PLATFORM_LIBS})
endif()

View File

@@ -1 +1 @@
20:1:0
25:0:0

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tls.c,v 1.85 2020/05/24 15:12:54 jsing Exp $ */
/* $OpenBSD: tls.c,v 1.94 2022/02/08 19:13:50 tb Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
@@ -326,12 +326,131 @@ tls_cert_pubkey_hash(X509 *cert, char **hash)
return (rv);
}
static int
tls_keypair_to_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY **pkey)
{
BIO *bio = NULL;
X509 *x509 = NULL;
char *mem;
size_t len;
int ret = -1;
*pkey = NULL;
if (ctx->config->use_fake_private_key) {
mem = keypair->cert_mem;
len = keypair->cert_len;
} else {
mem = keypair->key_mem;
len = keypair->key_len;
}
if (mem == NULL)
return (0);
if (len > INT_MAX) {
tls_set_errorx(ctx, ctx->config->use_fake_private_key ?
"cert too long" : "key too long");
goto err;
}
if ((bio = BIO_new_mem_buf(mem, len)) == NULL) {
tls_set_errorx(ctx, "failed to create buffer");
goto err;
}
if (ctx->config->use_fake_private_key) {
if ((x509 = PEM_read_bio_X509(bio, NULL, tls_password_cb,
NULL)) == NULL) {
tls_set_errorx(ctx, "failed to read X509 certificate");
goto err;
}
if ((*pkey = X509_get_pubkey(x509)) == NULL) {
tls_set_errorx(ctx, "failed to retrieve pubkey");
goto err;
}
} else {
if ((*pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb,
NULL)) == NULL) {
tls_set_errorx(ctx, "failed to read private key");
goto err;
}
}
ret = 0;
err:
BIO_free(bio);
X509_free(x509);
return (ret);
}
static int
tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *pkey)
{
RSA_METHOD *rsa_method;
ECDSA_METHOD *ecdsa_method;
RSA *rsa = NULL;
EC_KEY *eckey = NULL;
int ret = -1;
/* Only install the pubkey hash if fake private keys are used. */
if (!ctx->config->skip_private_key_check)
return (0);
if (keypair->pubkey_hash == NULL) {
tls_set_errorx(ctx, "public key hash not set");
goto err;
}
switch (EVP_PKEY_id(pkey)) {
case EVP_PKEY_RSA:
if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL ||
RSA_set_ex_data(rsa, 0, keypair->pubkey_hash) == 0) {
tls_set_errorx(ctx, "RSA key setup failure");
goto err;
}
if (ctx->config->sign_cb == NULL)
break;
if ((rsa_method = tls_signer_rsa_method()) == NULL ||
RSA_set_ex_data(rsa, 1, ctx->config) == 0 ||
RSA_set_method(rsa, rsa_method) == 0) {
tls_set_errorx(ctx, "failed to setup RSA key");
goto err;
}
break;
case EVP_PKEY_EC:
if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) == NULL ||
ECDSA_set_ex_data(eckey, 0, keypair->pubkey_hash) == 0) {
tls_set_errorx(ctx, "EC key setup failure");
goto err;
}
if (ctx->config->sign_cb == NULL)
break;
if ((ecdsa_method = tls_signer_ecdsa_method()) == NULL ||
ECDSA_set_ex_data(eckey, 1, ctx->config) == 0 ||
ECDSA_set_method(eckey, ecdsa_method) == 0) {
tls_set_errorx(ctx, "failed to setup EC key");
goto err;
}
break;
default:
tls_set_errorx(ctx, "incorrect key type");
goto err;
}
ret = 0;
err:
RSA_free(rsa);
EC_KEY_free(eckey);
return (ret);
}
int
tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx,
struct tls_keypair *keypair, int required)
{
EVP_PKEY *pkey = NULL;
BIO *bio = NULL;
if (!required &&
keypair->cert_mem == NULL &&
@@ -351,38 +470,15 @@ tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx,
}
}
if (keypair->key_mem != NULL) {
if (keypair->key_len > INT_MAX) {
tls_set_errorx(ctx, "key too long");
if (tls_keypair_to_pkey(ctx, keypair, &pkey) == -1)
goto err;
if (pkey != NULL) {
if (tls_keypair_setup_pkey(ctx, keypair, pkey) == -1)
goto err;
}
if ((bio = BIO_new_mem_buf(keypair->key_mem,
keypair->key_len)) == NULL) {
tls_set_errorx(ctx, "failed to create buffer");
goto err;
}
if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb,
NULL)) == NULL) {
tls_set_errorx(ctx, "failed to read private key");
goto err;
}
if (keypair->pubkey_hash != NULL) {
RSA *rsa;
/* XXX only RSA for now for relayd privsep */
if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) {
RSA_set_ex_data(rsa, 0, keypair->pubkey_hash);
RSA_free(rsa);
}
}
if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) {
tls_set_errorx(ctx, "failed to load private key");
goto err;
}
BIO_free(bio);
bio = NULL;
EVP_PKEY_free(pkey);
pkey = NULL;
}
@@ -397,9 +493,8 @@ tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx,
err:
EVP_PKEY_free(pkey);
BIO_free(bio);
return (1);
return (-1);
}
int
@@ -444,7 +539,7 @@ tls_configure_ssl(struct tls *ctx, SSL_CTX *ssl_ctx)
}
if (ctx->config->verify_time == 0) {
X509_VERIFY_PARAM_set_flags(ssl_ctx->param,
X509_VERIFY_PARAM_set_flags(SSL_CTX_get0_param(ssl_ctx),
X509_V_FLAG_NO_CHECK_TIME);
}
@@ -552,9 +647,8 @@ tls_configure_ssl_verify(struct tls *ctx, SSL_CTX *ssl_ctx, int verify)
tls_set_error(ctx, "failed to add crl");
goto err;
}
xi->crl = NULL;
}
X509_VERIFY_PARAM_set_flags(store->param,
X509_STORE_set_flags(store,
X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
}
@@ -670,7 +764,7 @@ tls_ssl_error(struct tls *ctx, SSL *ssl_conn, int ssl_ret, const char *prefix)
case SSL_ERROR_WANT_ACCEPT:
case SSL_ERROR_WANT_X509_LOOKUP:
default:
tls_set_ssl_errorx(ctx, "%s failed (%i)", prefix, ssl_err);
tls_set_ssl_errorx(ctx, "%s failed (%d)", prefix, ssl_err);
return (-1);
}
}

View File

@@ -45,6 +45,7 @@ tls_config_set_session_lifetime
tls_config_set_session_fd
tls_config_set_verify_depth
tls_config_skip_private_key_check
tls_config_use_fake_private_key
tls_config_verify
tls_config_verify_client
tls_config_verify_client_optional

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tls_bio_cb.c,v 1.19 2017/01/12 16:18:39 jsing Exp $ */
/* $OpenBSD: tls_bio_cb.c,v 1.20 2022/01/10 23:39:48 tb Exp $ */
/*
* Copyright (c) 2016 Tobias Pape <tobias@netshed.de>
*
@@ -29,19 +29,41 @@ static int bio_cb_read(BIO *bio, char *buf, int size);
static int bio_cb_puts(BIO *bio, const char *str);
static long bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr);
static BIO_METHOD bio_cb_method = {
.type = BIO_TYPE_MEM,
.name = "libtls_callbacks",
.bwrite = bio_cb_write,
.bread = bio_cb_read,
.bputs = bio_cb_puts,
.ctrl = bio_cb_ctrl,
};
static BIO_METHOD *bio_cb_method;
static pthread_mutex_t bio_cb_method_lock = PTHREAD_MUTEX_INITIALIZER;
static void
bio_cb_method_init(void)
{
BIO_METHOD *bio_method;
if (bio_cb_method != NULL)
return;
bio_method = BIO_meth_new(BIO_TYPE_MEM, "libtls_callbacks");
if (bio_method == NULL)
return;
BIO_meth_set_write(bio_method, bio_cb_write);
BIO_meth_set_read(bio_method, bio_cb_read);
BIO_meth_set_puts(bio_method, bio_cb_puts);
BIO_meth_set_ctrl(bio_method, bio_cb_ctrl);
bio_cb_method = bio_method;
}
static BIO_METHOD *
bio_s_cb(void)
{
return (&bio_cb_method);
if (bio_cb_method != NULL)
return (bio_cb_method);
pthread_mutex_lock(&bio_cb_method_lock);
bio_cb_method_init();
pthread_mutex_unlock(&bio_cb_method_lock);
return (bio_cb_method);
}
static int
@@ -57,10 +79,10 @@ bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr)
switch (cmd) {
case BIO_CTRL_GET_CLOSE:
ret = (long)bio->shutdown;
ret = (long)BIO_get_shutdown(bio);
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
BIO_set_shutdown(bio, (int)num);
break;
case BIO_CTRL_DUP:
case BIO_CTRL_FLUSH:
@@ -69,7 +91,7 @@ bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr)
case BIO_CTRL_GET:
case BIO_CTRL_SET:
default:
ret = BIO_ctrl(bio->next_bio, cmd, num, ptr);
ret = BIO_ctrl(BIO_next(bio), cmd, num, ptr);
}
return (ret);
@@ -78,7 +100,7 @@ bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr)
static int
bio_cb_write(BIO *bio, const char *buf, int num)
{
struct tls *ctx = bio->ptr;
struct tls *ctx = BIO_get_data(bio);
int rv;
BIO_clear_retry_flags(bio);
@@ -96,7 +118,7 @@ bio_cb_write(BIO *bio, const char *buf, int num)
static int
bio_cb_read(BIO *bio, char *buf, int size)
{
struct tls *ctx = bio->ptr;
struct tls *ctx = BIO_get_data(bio);
int rv;
BIO_clear_retry_flags(bio);
@@ -115,8 +137,9 @@ int
tls_set_cbs(struct tls *ctx, tls_read_cb read_cb, tls_write_cb write_cb,
void *cb_arg)
{
int rv = -1;
const BIO_METHOD *bio_cb;
BIO *bio;
int rv = -1;
if (read_cb == NULL || write_cb == NULL) {
tls_set_errorx(ctx, "no callbacks provided");
@@ -127,12 +150,16 @@ tls_set_cbs(struct tls *ctx, tls_read_cb read_cb, tls_write_cb write_cb,
ctx->write_cb = write_cb;
ctx->cb_arg = cb_arg;
if ((bio = BIO_new(bio_s_cb())) == NULL) {
if ((bio_cb = bio_s_cb()) == NULL) {
tls_set_errorx(ctx, "failed to create callback method");
goto err;
}
if ((bio = BIO_new(bio_cb)) == NULL) {
tls_set_errorx(ctx, "failed to create callback i/o");
goto err;
}
bio->ptr = ctx;
bio->init = 1;
BIO_set_data(bio, ctx);
BIO_set_init(bio, 1);
SSL_set_bio(ctx->ssl_conn, bio, bio);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tls_client.c,v 1.45 2018/03/19 16:34:47 jsing Exp $ */
/* $OpenBSD: tls_client.c,v 1.48 2021/10/21 08:38:11 tb Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
@@ -74,11 +74,8 @@ tls_connect_servername(struct tls *ctx, const char *host, const char *port,
goto err;
}
/*
* If port is NULL try to extract a port from the specified host,
* otherwise use the default.
*/
if ((p = (char *)port) == NULL) {
/* If port is NULL, try to extract a port from the specified host. */
if (port == NULL) {
ret = tls_host_port(host, &hs, &ps);
if (ret == -1) {
tls_set_errorx(ctx, "memory allocation failure");
@@ -279,6 +276,7 @@ static int
tls_connect_common(struct tls *ctx, const char *servername)
{
union tls_addr addrbuf;
size_t servername_len;
int rv = -1;
if ((ctx->flags & TLS_CLIENT) == 0) {
@@ -291,6 +289,17 @@ tls_connect_common(struct tls *ctx, const char *servername)
tls_set_errorx(ctx, "out of memory");
goto err;
}
/*
* If there's a trailing dot, remove it. While an FQDN includes
* the terminating dot representing the zero-length label of
* the root (RFC 8499, section 2), the SNI explicitly does not
* include it (RFC 6066, section 3).
*/
servername_len = strlen(ctx->servername);
if (servername_len > 0 &&
ctx->servername[servername_len - 1] == '.')
ctx->servername[servername_len - 1] = '\0';
}
if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
@@ -306,7 +315,7 @@ tls_connect_common(struct tls *ctx, const char *servername)
goto err;
if (ctx->config->verify_name) {
if (servername == NULL) {
if (ctx->servername == NULL) {
tls_set_errorx(ctx, "server name not specified");
goto err;
}
@@ -350,13 +359,14 @@ tls_connect_common(struct tls *ctx, const char *servername)
}
/*
* RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not
* RFC 6066 (SNI): Literal IPv4 and IPv6 addresses are not
* permitted in "HostName".
*/
if (servername != NULL &&
inet_pton(AF_INET, servername, &addrbuf) != 1 &&
inet_pton(AF_INET6, servername, &addrbuf) != 1) {
if (SSL_set_tlsext_host_name(ctx->ssl_conn, servername) == 0) {
if (ctx->servername != NULL &&
inet_pton(AF_INET, ctx->servername, &addrbuf) != 1 &&
inet_pton(AF_INET6, ctx->servername, &addrbuf) != 1) {
if (SSL_set_tlsext_host_name(ctx->ssl_conn,
ctx->servername) == 0) {
tls_set_errorx(ctx, "server name indication failure");
goto err;
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tls_config.c,v 1.58 2020/01/20 08:39:21 jsing Exp $ */
/* $OpenBSD: tls_config.c,v 1.65 2022/01/25 21:51:24 eric Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
@@ -179,6 +179,8 @@ tls_config_free(struct tls_config *config)
free((char *)config->crl_mem);
free(config->ecdhecurves);
pthread_mutex_destroy(&config->mutex);
free(config);
}
@@ -351,7 +353,8 @@ tls_config_add_keypair_file_internal(struct tls_config *config,
return (-1);
if (tls_keypair_set_cert_file(keypair, &config->error, cert_file) != 0)
goto err;
if (tls_keypair_set_key_file(keypair, &config->error, key_file) != 0)
if (key_file != NULL &&
tls_keypair_set_key_file(keypair, &config->error, key_file) != 0)
goto err;
if (ocsp_file != NULL &&
tls_keypair_set_ocsp_staple_file(keypair, &config->error,
@@ -378,7 +381,8 @@ tls_config_add_keypair_mem_internal(struct tls_config *config, const uint8_t *ce
return (-1);
if (tls_keypair_set_cert_mem(keypair, &config->error, cert, cert_len) != 0)
goto err;
if (tls_keypair_set_key_mem(keypair, &config->error, key, key_len) != 0)
if (key != NULL &&
tls_keypair_set_key_mem(keypair, &config->error, key, key_len) != 0)
goto err;
if (staple != NULL &&
tls_keypair_set_ocsp_staple_mem(keypair, &config->error, staple,
@@ -718,7 +722,7 @@ tls_config_set_session_fd(struct tls_config *config, int session_fd)
if (sb.st_uid != getuid()) {
tls_config_set_errorx(config, "session file has incorrect "
"owner (uid %i != %i)", sb.st_uid, getuid());
"owner (uid %u != %u)", sb.st_uid, getuid());
return (-1);
}
mugo = sb.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO);
@@ -733,6 +737,17 @@ tls_config_set_session_fd(struct tls_config *config, int session_fd)
return (0);
}
int
tls_config_set_sign_cb(struct tls_config *config, tls_sign_cb cb, void *cb_arg)
{
config->use_fake_private_key = 1;
config->skip_private_key_check = 1;
config->sign_cb = cb;
config->sign_cb_arg = cb_arg;
return (0);
}
int
tls_config_set_verify_depth(struct tls_config *config, int verify_depth)
{
@@ -803,6 +818,13 @@ tls_config_skip_private_key_check(struct tls_config *config)
config->skip_private_key_check = 1;
}
void
tls_config_use_fake_private_key(struct tls_config *config)
{
config->use_fake_private_key = 1;
config->skip_private_key_check = 1;
}
int
tls_config_set_ocsp_staple_file(struct tls_config *config, const char *staple_file)
{

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tls_conninfo.c,v 1.21 2019/11/02 13:37:59 jsing Exp $ */
/* $OpenBSD: tls_conninfo.c,v 1.22 2021/01/05 15:57:38 tb Exp $ */
/*
* Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2015 Bob Beck <beck@openbsd.org>
@@ -112,9 +112,6 @@ tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore,
if (ctx->ssl_peer_cert == NULL)
return (-1);
memset(&before_tm, 0, sizeof(before_tm));
memset(&after_tm, 0, sizeof(after_tm));
if ((before = X509_get_notBefore(ctx->ssl_peer_cert)) == NULL)
goto err;
if ((after = X509_get_notAfter(ctx->ssl_peer_cert)) == NULL)

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tls_internal.h,v 1.77 2019/11/16 21:39:52 beck Exp $ */
/* $OpenBSD: tls_internal.h,v 1.80 2022/03/24 15:56:34 tb Exp $ */
/*
* Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org>
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
@@ -78,6 +78,10 @@ struct tls_ticket_key {
time_t time;
};
typedef int (*tls_sign_cb)(void *_cb_arg, const char *_pubkey_hash,
const uint8_t *_input, size_t _input_len, int _padding_type,
uint8_t **_out_signature, size_t *_out_signature_len);
struct tls_config {
struct tls_error error;
@@ -111,6 +115,9 @@ struct tls_config {
int verify_name;
int verify_time;
int skip_private_key_check;
int use_fake_private_key;
tls_sign_cb sign_cb;
void *sign_cb_arg;
};
struct tls_conninfo {
@@ -290,9 +297,31 @@ int tls_cert_pubkey_hash(X509 *_cert, char **_hash);
int tls_password_cb(char *_buf, int _size, int _rwflag, void *_u);
RSA_METHOD *tls_signer_rsa_method(void);
ECDSA_METHOD *tls_signer_ecdsa_method(void);
#define TLS_PADDING_NONE 0
#define TLS_PADDING_RSA_PKCS1 1
#define TLS_PADDING_RSA_X9_31 2
int tls_config_set_sign_cb(struct tls_config *_config, tls_sign_cb _cb,
void *_cb_arg);
struct tls_signer* tls_signer_new(void);
void tls_signer_free(struct tls_signer * _signer);
const char *tls_signer_error(struct tls_signer * _signer);
int tls_signer_add_keypair_file(struct tls_signer *_signer,
const char *_cert_file, const char *_key_file);
int tls_signer_add_keypair_mem(struct tls_signer *_signer, const uint8_t *_cert,
size_t _cert_len, const uint8_t *_key, size_t _key_len);
int tls_signer_sign(struct tls_signer *_signer, const char *_pubkey_hash,
const uint8_t *_input, size_t _input_len, int _padding_type,
uint8_t **_out_signature, size_t *_out_signature_len);
__END_HIDDEN_DECLS
/* XXX this function is not fully hidden so relayd can use it */
void tls_config_skip_private_key_check(struct tls_config *config);
void tls_config_use_fake_private_key(struct tls_config *config);
#endif /* HEADER_TLS_INTERNAL_H */

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tls_keypair.c,v 1.6 2018/04/07 16:35:34 jsing Exp $ */
/* $OpenBSD: tls_keypair.c,v 1.8 2021/01/05 17:37:12 jsing Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
@@ -137,7 +137,7 @@ tls_keypair_load_cert(struct tls_keypair *keypair, struct tls_error *error,
{
char *errstr = "unknown";
BIO *cert_bio = NULL;
int ssl_err;
unsigned long ssl_err;
int rv = -1;
X509_free(*cert);
@@ -155,7 +155,7 @@ tls_keypair_load_cert(struct tls_keypair *keypair, struct tls_error *error,
if ((*cert = PEM_read_bio_X509(cert_bio, NULL, tls_password_cb,
NULL)) == NULL) {
if ((ssl_err = ERR_peek_error()) != 0)
errstr = ERR_error_string(ssl_err, NULL);
errstr = ERR_error_string(ssl_err, NULL);
tls_error_set(error, "failed to load certificate: %s", errstr);
goto err;
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tls_ocsp.c,v 1.19 2019/12/03 14:56:42 tb Exp $ */
/* $OpenBSD: tls_ocsp.c,v 1.22 2021/10/31 16:39:32 tb Exp $ */
/*
* Copyright (c) 2015 Marko Kreen <markokr@gmail.com>
* Copyright (c) 2016 Bob Beck <beck@openbsd.org>
@@ -128,30 +128,38 @@ tls_ocsp_get_certid(X509 *main_cert, STACK_OF(X509) *extra_certs,
{
X509_NAME *issuer_name;
X509 *issuer;
X509_STORE_CTX storectx;
X509_OBJECT tmpobj;
X509_STORE_CTX *storectx = NULL;
X509_OBJECT *obj = NULL;
OCSP_CERTID *cid = NULL;
X509_STORE *store;
if ((issuer_name = X509_get_issuer_name(main_cert)) == NULL)
return NULL;
goto out;
if (extra_certs != NULL) {
issuer = X509_find_by_subject(extra_certs, issuer_name);
if (issuer != NULL)
return OCSP_cert_to_id(NULL, main_cert, issuer);
if (issuer != NULL) {
cid = OCSP_cert_to_id(NULL, main_cert, issuer);
goto out;
}
}
if ((store = SSL_CTX_get_cert_store(ssl_ctx)) == NULL)
return NULL;
if (X509_STORE_CTX_init(&storectx, store, main_cert, extra_certs) != 1)
return NULL;
if (X509_STORE_get_by_subject(&storectx, X509_LU_X509, issuer_name,
&tmpobj) == 1) {
cid = OCSP_cert_to_id(NULL, main_cert, tmpobj.data.x509);
X509_OBJECT_free_contents(&tmpobj);
}
X509_STORE_CTX_cleanup(&storectx);
goto out;
if ((storectx = X509_STORE_CTX_new()) == NULL)
goto out;
if (X509_STORE_CTX_init(storectx, store, main_cert, extra_certs) != 1)
goto out;
if ((obj = X509_STORE_CTX_get_obj_by_subject(storectx, X509_LU_X509,
issuer_name)) == NULL)
goto out;
cid = OCSP_cert_to_id(NULL, main_cert, X509_OBJECT_get0_X509(obj));
out:
X509_STORE_CTX_free(storectx);
X509_OBJECT_free(obj);
return cid;
}
@@ -218,7 +226,7 @@ tls_ocsp_verify_response(struct tls *ctx, OCSP_RESPONSE *resp)
/* now verify */
if (OCSP_basic_verify(br, ctx->ocsp->extra_certs,
SSL_CTX_get_cert_store(ctx->ssl_ctx), flags) != 1) {
tls_set_error(ctx, "ocsp verify failed");
tls_set_errorx(ctx, "ocsp verify failed");
goto err;
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tls_server.c,v 1.45 2019/05/13 22:36:01 bcook Exp $ */
/* $OpenBSD: tls_server.c,v 1.48 2022/01/19 11:10:55 inoguchi Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
@@ -109,7 +109,7 @@ tls_servername_cb(SSL *ssl, int *al, void *arg)
inet_pton(AF_INET6, name, &addrbuf) == 1)
return (SSL_TLSEXT_ERR_NOACK);
free((char *)conn_ctx->servername);
free(conn_ctx->servername);
if ((conn_ctx->servername = strdup(name)) == NULL)
goto err;
@@ -133,7 +133,7 @@ tls_servername_cb(SSL *ssl, int *al, void *arg)
* There is no way to tell libssl that an internal failure occurred.
* The only option we have is to return a fatal alert.
*/
*al = TLS1_AD_INTERNAL_ERROR;
*al = SSL_AD_INTERNAL_ERROR;
return (SSL_TLSEXT_ERR_ALERT_FATAL);
}
@@ -185,10 +185,16 @@ tls_server_ticket_cb(SSL *ssl, unsigned char *keyname, unsigned char *iv,
memcpy(keyname, key->key_name, sizeof(key->key_name));
arc4random_buf(iv, EVP_MAX_IV_LENGTH);
EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL,
key->aes_key, iv);
HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key),
EVP_sha256(), NULL);
if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL,
key->aes_key, iv)) {
tls_set_errorx(tls_ctx, "failed to init encrypt");
return (-1);
}
if (!HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key),
EVP_sha256(), NULL)) {
tls_set_errorx(tls_ctx, "failed to init hmac");
return (-1);
}
return (0);
} else {
/* get key by name */
@@ -196,10 +202,16 @@ tls_server_ticket_cb(SSL *ssl, unsigned char *keyname, unsigned char *iv,
if (key == NULL)
return (0);
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL,
key->aes_key, iv);
HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key),
EVP_sha256(), NULL);
if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL,
key->aes_key, iv)) {
tls_set_errorx(tls_ctx, "failed to init decrypt");
return (-1);
}
if (!HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key),
EVP_sha256(), NULL)) {
tls_set_errorx(tls_ctx, "failed to init hmac");
return (-1);
}
/* time to renew the ticket? is it the primary key? */
if (key != &tls_ctx->config->ticket_keys[0])

451
externals/libressl/tls/tls_signer.c vendored Executable file
View File

@@ -0,0 +1,451 @@
/* $OpenBSD: tls_signer.c,v 1.4 2022/02/01 17:18:38 jsing Exp $ */
/*
* Copyright (c) 2021 Eric Faurot <eric@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <limits.h>
#include <openssl/ecdsa.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include "tls.h"
#include "tls_internal.h"
struct tls_signer_key {
char *hash;
RSA *rsa;
EC_KEY *ecdsa;
struct tls_signer_key *next;
};
struct tls_signer {
struct tls_error error;
struct tls_signer_key *keys;
};
static pthread_mutex_t signer_method_lock = PTHREAD_MUTEX_INITIALIZER;
struct tls_signer *
tls_signer_new(void)
{
struct tls_signer *signer;
if ((signer = calloc(1, sizeof(*signer))) == NULL)
return (NULL);
return (signer);
}
void
tls_signer_free(struct tls_signer *signer)
{
struct tls_signer_key *skey;
if (signer == NULL)
return;
tls_error_clear(&signer->error);
while (signer->keys) {
skey = signer->keys;
signer->keys = skey->next;
RSA_free(skey->rsa);
EC_KEY_free(skey->ecdsa);
free(skey->hash);
free(skey);
}
free(signer);
}
const char *
tls_signer_error(struct tls_signer *signer)
{
return (signer->error.msg);
}
int
tls_signer_add_keypair_mem(struct tls_signer *signer, const uint8_t *cert,
size_t cert_len, const uint8_t *key, size_t key_len)
{
struct tls_signer_key *skey = NULL;
char *errstr = "unknown";
int ssl_err;
EVP_PKEY *pkey = NULL;
X509 *x509 = NULL;
BIO *bio = NULL;
char *hash = NULL;
/* Compute certificate hash */
if ((bio = BIO_new_mem_buf(cert, cert_len)) == NULL) {
tls_error_setx(&signer->error,
"failed to create certificate bio");
goto err;
}
if ((x509 = PEM_read_bio_X509(bio, NULL, tls_password_cb,
NULL)) == NULL) {
if ((ssl_err = ERR_peek_error()) != 0)
errstr = ERR_error_string(ssl_err, NULL);
tls_error_setx(&signer->error, "failed to load certificate: %s",
errstr);
goto err;
}
if (tls_cert_pubkey_hash(x509, &hash) == -1) {
tls_error_setx(&signer->error,
"failed to get certificate hash");
goto err;
}
X509_free(x509);
x509 = NULL;
BIO_free(bio);
bio = NULL;
/* Read private key */
if ((bio = BIO_new_mem_buf(key, key_len)) == NULL) {
tls_error_setx(&signer->error, "failed to create key bio");
goto err;
}
if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb,
NULL)) == NULL) {
tls_error_setx(&signer->error, "failed to read private key");
goto err;
}
if ((skey = calloc(1, sizeof(*skey))) == NULL) {
tls_error_set(&signer->error, "failed to create key entry");
goto err;
}
skey->hash = hash;
if ((skey->rsa = EVP_PKEY_get1_RSA(pkey)) == NULL &&
(skey->ecdsa = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) {
tls_error_setx(&signer->error, "unknown key type");
goto err;
}
skey->next = signer->keys;
signer->keys = skey;
EVP_PKEY_free(pkey);
BIO_free(bio);
return (0);
err:
EVP_PKEY_free(pkey);
X509_free(x509);
BIO_free(bio);
free(hash);
free(skey);
return (-1);
}
int
tls_signer_add_keypair_file(struct tls_signer *signer, const char *cert_file,
const char *key_file)
{
char *cert = NULL, *key = NULL;
size_t cert_len, key_len;
int rv = -1;
if (tls_config_load_file(&signer->error, "certificate", cert_file,
&cert, &cert_len) == -1)
goto err;
if (tls_config_load_file(&signer->error, "key", key_file, &key,
&key_len) == -1)
goto err;
rv = tls_signer_add_keypair_mem(signer, cert, cert_len, key, key_len);
err:
free(cert);
free(key);
return (rv);
}
static int
tls_sign_rsa(struct tls_signer *signer, struct tls_signer_key *skey,
const uint8_t *input, size_t input_len, int padding_type,
uint8_t **out_signature, size_t *out_signature_len)
{
int rsa_padding, rsa_size, signature_len;
char *signature = NULL;
*out_signature = NULL;
*out_signature_len = 0;
if (padding_type == TLS_PADDING_NONE) {
rsa_padding = RSA_NO_PADDING;
} else if (padding_type == TLS_PADDING_RSA_PKCS1) {
rsa_padding = RSA_PKCS1_PADDING;
} else if (padding_type == TLS_PADDING_RSA_X9_31) {
rsa_padding = RSA_X931_PADDING;
} else {
tls_error_setx(&signer->error, "invalid RSA padding type (%d)",
padding_type);
return (-1);
}
if (input_len > INT_MAX) {
tls_error_setx(&signer->error, "input too large");
return (-1);
}
if ((rsa_size = RSA_size(skey->rsa)) <= 0) {
tls_error_setx(&signer->error, "invalid RSA size: %d",
rsa_size);
return (-1);
}
if ((signature = calloc(1, rsa_size)) == NULL) {
tls_error_set(&signer->error, "RSA signature");
return (-1);
}
if ((signature_len = RSA_private_encrypt((int)input_len, input,
signature, skey->rsa, rsa_padding)) <= 0) {
/* XXX - include further details from libcrypto. */
tls_error_setx(&signer->error, "RSA signing failed");
free(signature);
return (-1);
}
*out_signature = signature;
*out_signature_len = (size_t)signature_len;
return (0);
}
static int
tls_sign_ecdsa(struct tls_signer *signer, struct tls_signer_key *skey,
const uint8_t *input, size_t input_len, int padding_type,
uint8_t **out_signature, size_t *out_signature_len)
{
unsigned char *signature;
int signature_len;
*out_signature = NULL;
*out_signature_len = 0;
if (padding_type != TLS_PADDING_NONE) {
tls_error_setx(&signer->error, "invalid ECDSA padding");
return (-1);
}
if (input_len > INT_MAX) {
tls_error_setx(&signer->error, "digest too large");
return (-1);
}
if ((signature_len = ECDSA_size(skey->ecdsa)) <= 0) {
tls_error_setx(&signer->error, "invalid ECDSA size: %d",
signature_len);
return (-1);
}
if ((signature = calloc(1, signature_len)) == NULL) {
tls_error_set(&signer->error, "ECDSA signature");
return (-1);
}
if (!ECDSA_sign(0, input, input_len, signature, &signature_len,
skey->ecdsa)) {
/* XXX - include further details from libcrypto. */
tls_error_setx(&signer->error, "ECDSA signing failed");
free(signature);
return (-1);
}
*out_signature = signature;
*out_signature_len = signature_len;
return (0);
}
int
tls_signer_sign(struct tls_signer *signer, const char *pubkey_hash,
const uint8_t *input, size_t input_len, int padding_type,
uint8_t **out_signature, size_t *out_signature_len)
{
struct tls_signer_key *skey;
*out_signature = NULL;
*out_signature_len = 0;
for (skey = signer->keys; skey; skey = skey->next)
if (!strcmp(pubkey_hash, skey->hash))
break;
if (skey == NULL) {
tls_error_setx(&signer->error, "key not found");
return (-1);
}
if (skey->rsa != NULL)
return tls_sign_rsa(signer, skey, input, input_len,
padding_type, out_signature, out_signature_len);
if (skey->ecdsa != NULL)
return tls_sign_ecdsa(signer, skey, input, input_len,
padding_type, out_signature, out_signature_len);
tls_error_setx(&signer->error, "unknown key type");
return (-1);
}
static int
tls_rsa_priv_enc(int from_len, const unsigned char *from, unsigned char *to,
RSA *rsa, int rsa_padding)
{
struct tls_config *config;
uint8_t *signature = NULL;
size_t signature_len = 0;
const char *pubkey_hash;
int padding_type;
/*
* This function is called via RSA_private_encrypt() and has to conform
* to its calling convention/signature. The caller is required to
* provide a 'to' buffer of at least RSA_size() bytes.
*/
pubkey_hash = RSA_get_ex_data(rsa, 0);
config = RSA_get_ex_data(rsa, 1);
if (pubkey_hash == NULL || config == NULL)
goto err;
if (rsa_padding == RSA_NO_PADDING) {
padding_type = TLS_PADDING_NONE;
} else if (rsa_padding == RSA_PKCS1_PADDING) {
padding_type = TLS_PADDING_RSA_PKCS1;
} else if (rsa_padding == RSA_X931_PADDING) {
padding_type = TLS_PADDING_RSA_X9_31;
} else {
goto err;
}
if (from_len < 0)
goto err;
if (config->sign_cb(config->sign_cb_arg, pubkey_hash, from, from_len,
padding_type, &signature, &signature_len) == -1)
goto err;
if (signature_len > INT_MAX || (int)signature_len > RSA_size(rsa))
goto err;
memcpy(to, signature, signature_len);
free(signature);
return ((int)signature_len);
err:
free(signature);
return (-1);
}
RSA_METHOD *
tls_signer_rsa_method(void)
{
static RSA_METHOD *rsa_method = NULL;
pthread_mutex_lock(&signer_method_lock);
if (rsa_method != NULL)
goto out;
rsa_method = RSA_meth_new("libtls RSA method", 0);
if (rsa_method == NULL)
goto out;
RSA_meth_set_priv_enc(rsa_method, tls_rsa_priv_enc);
out:
pthread_mutex_unlock(&signer_method_lock);
return (rsa_method);
}
static ECDSA_SIG *
tls_ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
const BIGNUM *rp, EC_KEY *eckey)
{
struct tls_config *config;
ECDSA_SIG *ecdsa_sig = NULL;
uint8_t *signature = NULL;
size_t signature_len = 0;
const unsigned char *p;
const char *pubkey_hash;
/*
* This function is called via ECDSA_do_sign_ex() and has to conform
* to its calling convention/signature.
*/
pubkey_hash = ECDSA_get_ex_data(eckey, 0);
config = ECDSA_get_ex_data(eckey, 1);
if (pubkey_hash == NULL || config == NULL)
goto err;
if (dgst_len < 0)
goto err;
if (config->sign_cb(config->sign_cb_arg, pubkey_hash, dgst, dgst_len,
TLS_PADDING_NONE, &signature, &signature_len) == -1)
goto err;
p = signature;
if ((ecdsa_sig = d2i_ECDSA_SIG(NULL, &p, signature_len)) == NULL)
goto err;
free(signature);
return (ecdsa_sig);
err:
free(signature);
return (NULL);
}
ECDSA_METHOD *
tls_signer_ecdsa_method(void)
{
static ECDSA_METHOD *ecdsa_method = NULL;
pthread_mutex_lock(&signer_method_lock);
if (ecdsa_method != NULL)
goto out;
ecdsa_method = calloc(1, sizeof(*ecdsa_method));
if (ecdsa_method == NULL)
goto out;
ecdsa_method->ecdsa_do_sign = tls_ecdsa_do_sign;
ecdsa_method->name = strdup("libtls ECDSA method");
if (ecdsa_method->name == NULL) {
free(ecdsa_method);
ecdsa_method = NULL;
}
out:
pthread_mutex_unlock(&signer_method_lock);
return (ecdsa_method);
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tls_util.c,v 1.14 2019/04/13 18:47:58 tb Exp $ */
/* $OpenBSD: tls_util.c,v 1.15 2021/08/16 13:54:38 tb Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2014 Ted Unangst <tedu@openbsd.org>
@@ -92,7 +92,7 @@ tls_host_port(const char *hostport, char **host, char **port)
*p++ = '\0';
}
/* Find the port seperator. */
/* Find the port separator. */
if ((p = strchr(p, ':')) == NULL)
goto done;