mirror of https://github.com/omar-polo/gmid.git
sync libtls
This commit is contained in:
parent
12eb29d878
commit
ebfc578491
|
@ -13,6 +13,7 @@ DISTFILES = Makefile \
|
|||
tls_ocsp.c \
|
||||
tls_peer.c \
|
||||
tls_server.c \
|
||||
tls_signer.c \
|
||||
tls_util.c \
|
||||
tls_verify.c
|
||||
|
||||
|
|
|
@ -26,38 +26,38 @@
|
|||
#define GENTIME_LENGTH 15
|
||||
#define UTCTIME_LENGTH 13
|
||||
|
||||
#define V_ASN1_UTCTIME 23
|
||||
#define V_ASN1_GENERALIZEDTIME 24
|
||||
#define V_ASN1_UTCTIME 23
|
||||
#define V_ASN1_GENERALIZEDTIME 24
|
||||
|
||||
#ifndef HAVE_ASN1_TIME_TM_CMP
|
||||
int
|
||||
ASN1_time_tm_cmp(struct tm *tm1, struct tm *tm2)
|
||||
{
|
||||
if (tm1->tm_year < tm2->tm_year)
|
||||
return (-1);
|
||||
if (tm1->tm_year > tm2->tm_year)
|
||||
return (1);
|
||||
if (tm1->tm_mon < tm2->tm_mon)
|
||||
return (-1);
|
||||
if (tm1->tm_mon > tm2->tm_mon)
|
||||
return (1);
|
||||
if (tm1->tm_mday < tm2->tm_mday)
|
||||
return (-1);
|
||||
if (tm1->tm_mday > tm2->tm_mday)
|
||||
return (1);
|
||||
if (tm1->tm_hour < tm2->tm_hour)
|
||||
return (-1);
|
||||
if (tm1->tm_hour > tm2->tm_hour)
|
||||
return (1);
|
||||
if (tm1->tm_min < tm2->tm_min)
|
||||
return (-1);
|
||||
if (tm1->tm_min > tm2->tm_min)
|
||||
return (1);
|
||||
if (tm1->tm_sec < tm2->tm_sec)
|
||||
return (-1);
|
||||
if (tm1->tm_sec > tm2->tm_sec)
|
||||
return (1);
|
||||
return 0;
|
||||
if (tm1->tm_year < tm2->tm_year)
|
||||
return (-1);
|
||||
if (tm1->tm_year > tm2->tm_year)
|
||||
return (1);
|
||||
if (tm1->tm_mon < tm2->tm_mon)
|
||||
return (-1);
|
||||
if (tm1->tm_mon > tm2->tm_mon)
|
||||
return (1);
|
||||
if (tm1->tm_mday < tm2->tm_mday)
|
||||
return (-1);
|
||||
if (tm1->tm_mday > tm2->tm_mday)
|
||||
return (1);
|
||||
if (tm1->tm_hour < tm2->tm_hour)
|
||||
return (-1);
|
||||
if (tm1->tm_hour > tm2->tm_hour)
|
||||
return (1);
|
||||
if (tm1->tm_min < tm2->tm_min)
|
||||
return (-1);
|
||||
if (tm1->tm_min > tm2->tm_min)
|
||||
return (1);
|
||||
if (tm1->tm_sec < tm2->tm_sec)
|
||||
return (-1);
|
||||
if (tm1->tm_sec > tm2->tm_sec)
|
||||
return (1);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -66,112 +66,15 @@ int
|
|||
ASN1_time_tm_clamp_notafter(struct tm *tm)
|
||||
{
|
||||
#ifdef SMALL_TIME_T
|
||||
struct tm broken_os_epoch_tm;
|
||||
time_t broken_os_epoch_time = INT_MAX;
|
||||
struct tm broken_os_epoch_tm;
|
||||
time_t broken_os_epoch_time = INT_MAX;
|
||||
|
||||
if (gmtime_r(&broken_os_epoch_time, &broken_os_epoch_tm) == NULL)
|
||||
return 0;
|
||||
if (gmtime_r(&broken_os_epoch_time, &broken_os_epoch_tm) == NULL)
|
||||
return 0;
|
||||
|
||||
if (ASN1_time_tm_cmp(tm, &broken_os_epoch_tm) == 1)
|
||||
memcpy(tm, &broken_os_epoch_tm, sizeof(*tm));
|
||||
if (ASN1_time_tm_cmp(tm, &broken_os_epoch_tm) == 1)
|
||||
memcpy(tm, &broken_os_epoch_tm, sizeof(*tm));
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Parse an RFC 5280 format ASN.1 time string.
|
||||
*
|
||||
* mode must be:
|
||||
* 0 if we expect to parse a time as specified in RFC 5280 for an X509 object.
|
||||
* V_ASN1_UTCTIME if we wish to parse an RFC5280 format UTC time.
|
||||
* V_ASN1_GENERALIZEDTIME if we wish to parse an RFC5280 format Generalized time.
|
||||
*
|
||||
* Returns:
|
||||
* -1 if the string was invalid.
|
||||
* V_ASN1_UTCTIME if the string validated as a UTC time string.
|
||||
* V_ASN1_GENERALIZEDTIME if the string validated as a Generalized time string.
|
||||
*
|
||||
* Fills in *tm with the corresponding time if tm is non NULL.
|
||||
*/
|
||||
#ifndef HAVE_ASN1_TIME_PARSE
|
||||
#define ATOI2(ar) ((ar) += 2, ((ar)[-2] - '0') * 10 + ((ar)[-1] - '0'))
|
||||
int
|
||||
ASN1_time_parse(const char *bytes, size_t len, struct tm *tm, int mode)
|
||||
{
|
||||
size_t i;
|
||||
int type = 0;
|
||||
struct tm ltm;
|
||||
struct tm *lt;
|
||||
const char *p;
|
||||
|
||||
if (bytes == NULL)
|
||||
return (-1);
|
||||
|
||||
/* Constrain to valid lengths. */
|
||||
if (len != UTCTIME_LENGTH && len != GENTIME_LENGTH)
|
||||
return (-1);
|
||||
|
||||
lt = tm;
|
||||
if (lt == NULL) {
|
||||
memset(<m, 0, sizeof(ltm));
|
||||
lt = <m;
|
||||
}
|
||||
|
||||
/* Timezone is required and must be GMT (Zulu). */
|
||||
if (bytes[len - 1] != 'Z')
|
||||
return (-1);
|
||||
|
||||
/* Make sure everything else is digits. */
|
||||
for (i = 0; i < len - 1; i++) {
|
||||
if (isdigit((unsigned char)bytes[i]))
|
||||
continue;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate and convert the time
|
||||
*/
|
||||
p = bytes;
|
||||
switch (len) {
|
||||
case GENTIME_LENGTH:
|
||||
if (mode == V_ASN1_UTCTIME)
|
||||
return (-1);
|
||||
lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */
|
||||
type = V_ASN1_GENERALIZEDTIME;
|
||||
/* FALLTHROUGH */
|
||||
case UTCTIME_LENGTH:
|
||||
if (type == 0) {
|
||||
if (mode == V_ASN1_GENERALIZEDTIME)
|
||||
return (-1);
|
||||
type = V_ASN1_UTCTIME;
|
||||
}
|
||||
lt->tm_year += ATOI2(p); /* yy */
|
||||
if (type == V_ASN1_UTCTIME) {
|
||||
if (lt->tm_year < 50)
|
||||
lt->tm_year += 100;
|
||||
}
|
||||
lt->tm_mon = ATOI2(p) - 1; /* mm */
|
||||
if (lt->tm_mon < 0 || lt->tm_mon > 11)
|
||||
return (-1);
|
||||
lt->tm_mday = ATOI2(p); /* dd */
|
||||
if (lt->tm_mday < 1 || lt->tm_mday > 31)
|
||||
return (-1);
|
||||
lt->tm_hour = ATOI2(p); /* HH */
|
||||
if (lt->tm_hour < 0 || lt->tm_hour > 23)
|
||||
return (-1);
|
||||
lt->tm_min = ATOI2(p); /* MM */
|
||||
if (lt->tm_min < 0 || lt->tm_min > 59)
|
||||
return (-1);
|
||||
lt->tm_sec = ATOI2(p); /* SS */
|
||||
/* Leap second 60 is not accepted. Reconsider later? */
|
||||
if (lt->tm_sec < 0 || lt->tm_sec > 59)
|
||||
return (-1);
|
||||
break;
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (type);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
X509_LOOKUP_METHOD *
|
||||
X509_LOOKUP_mem(void);
|
||||
|
||||
static int
|
||||
int
|
||||
X509_STORE_load_mem(X509_STORE *ctx, void *buf, int len)
|
||||
{
|
||||
X509_LOOKUP *lookup;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: tls.c,v 1.97 2023/06/18 11:43:03 op Exp $ */
|
||||
/* $OpenBSD: tls.c,v 1.98 2023/07/02 06:37:27 beck Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
|
||||
*
|
||||
|
@ -384,6 +384,8 @@ tls_keypair_to_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY **pke
|
|||
static int
|
||||
tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *pkey)
|
||||
{
|
||||
RSA_METHOD *rsa_method;
|
||||
EC_KEY_METHOD *ecdsa_method;
|
||||
RSA *rsa = NULL;
|
||||
EC_KEY *eckey = NULL;
|
||||
int ret = -1;
|
||||
|
@ -400,19 +402,45 @@ tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *p
|
|||
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 ||
|
||||
EVP_PKEY_set1_RSA(pkey, rsa) == 0) {
|
||||
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) {
|
||||
rsa_method = tls_signer_rsa_method();
|
||||
if (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;
|
||||
}
|
||||
}
|
||||
/* Reset the key to work around caching in OpenSSL 3. */
|
||||
if (EVP_PKEY_set1_RSA(pkey, rsa) == 0) {
|
||||
tls_set_errorx(ctx, "failed to set RSA key");
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case EVP_PKEY_EC:
|
||||
if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) == NULL ||
|
||||
EC_KEY_set_ex_data(eckey, 0, keypair->pubkey_hash) == 0 ||
|
||||
EVP_PKEY_set1_EC_KEY(pkey, eckey) == 0) {
|
||||
EC_KEY_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) {
|
||||
ecdsa_method = tls_signer_ecdsa_method();
|
||||
if (ecdsa_method == NULL ||
|
||||
EC_KEY_set_ex_data(eckey, 1, ctx->config) == 0 ||
|
||||
EC_KEY_set_method(eckey, ecdsa_method) == 0) {
|
||||
tls_set_errorx(ctx, "failed to setup EC key");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/* Reset the key to work around caching in OpenSSL 3. */
|
||||
if (EVP_PKEY_set1_EC_KEY(pkey, eckey) == 0) {
|
||||
tls_set_errorx(ctx, "failed to set EC key");
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
tls_set_errorx(ctx, "incorrect key type");
|
||||
|
@ -488,16 +516,12 @@ tls_configure_ssl(struct tls *ctx, SSL_CTX *ssl_ctx)
|
|||
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2);
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv3);
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1);
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_1);
|
||||
|
||||
SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1);
|
||||
SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1_1);
|
||||
SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1_2);
|
||||
SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1_3);
|
||||
|
||||
if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_0) == 0)
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1);
|
||||
if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_1) == 0)
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_1);
|
||||
if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_2) == 0)
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_2);
|
||||
if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_3) == 0)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: tls.h,v 1.62 2022/03/24 15:56:34 tb Exp $ */
|
||||
/* $OpenBSD: tls.h,v 1.63 2023/07/02 06:37:27 beck Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
|
||||
*
|
||||
|
@ -29,14 +29,18 @@ extern "C" {
|
|||
|
||||
#define TLS_API 20200120
|
||||
|
||||
#define TLS_PROTOCOL_TLSv1_0 (1 << 1)
|
||||
#define TLS_PROTOCOL_TLSv1_1 (1 << 2)
|
||||
/*
|
||||
* Deprecated versions of TLS. Using these effectively selects
|
||||
* the minimum supported version.
|
||||
*/
|
||||
#define TLS_PROTOCOL_TLSv1_0 (1 << 3)
|
||||
#define TLS_PROTOCOL_TLSv1_1 (1 << 3)
|
||||
/* Supported versions of TLS */
|
||||
#define TLS_PROTOCOL_TLSv1_2 (1 << 3)
|
||||
#define TLS_PROTOCOL_TLSv1_3 (1 << 4)
|
||||
|
||||
#define TLS_PROTOCOL_TLSv1 \
|
||||
(TLS_PROTOCOL_TLSv1_0|TLS_PROTOCOL_TLSv1_1|\
|
||||
TLS_PROTOCOL_TLSv1_2|TLS_PROTOCOL_TLSv1_3)
|
||||
(TLS_PROTOCOL_TLSv1_2|TLS_PROTOCOL_TLSv1_3)
|
||||
|
||||
#define TLS_PROTOCOLS_ALL TLS_PROTOCOL_TLSv1
|
||||
#define TLS_PROTOCOLS_DEFAULT (TLS_PROTOCOL_TLSv1_2|TLS_PROTOCOL_TLSv1_3)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: tls_config.c,v 1.66 2023/05/14 07:26:25 op Exp $ */
|
||||
/* $OpenBSD: tls_config.c,v 1.67 2023/07/02 06:37:27 beck Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
|
||||
*
|
||||
|
@ -247,9 +247,9 @@ tls_config_parse_protocols(uint32_t *protocols, const char *protostr)
|
|||
if (strcasecmp(p, "tlsv1") == 0)
|
||||
proto = TLS_PROTOCOL_TLSv1;
|
||||
else if (strcasecmp(p, "tlsv1.0") == 0)
|
||||
proto = TLS_PROTOCOL_TLSv1_0;
|
||||
proto = TLS_PROTOCOL_TLSv1_2;
|
||||
else if (strcasecmp(p, "tlsv1.1") == 0)
|
||||
proto = TLS_PROTOCOL_TLSv1_1;
|
||||
proto = TLS_PROTOCOL_TLSv1_2;
|
||||
else if (strcasecmp(p, "tlsv1.2") == 0)
|
||||
proto = TLS_PROTOCOL_TLSv1_2;
|
||||
else if (strcasecmp(p, "tlsv1.3") == 0)
|
||||
|
@ -734,6 +734,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)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: tls_conninfo.c,v 1.23 2023/05/14 07:26:25 op Exp $ */
|
||||
/* $OpenBSD: tls_conninfo.c,v 1.24 2023/11/13 10:51:49 tb Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
|
||||
* Copyright (c) 2015 Bob Beck <beck@openbsd.org>
|
||||
|
@ -119,9 +119,9 @@ tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore,
|
|||
goto err;
|
||||
if ((after = X509_get_notAfter(ctx->ssl_peer_cert)) == NULL)
|
||||
goto err;
|
||||
if (ASN1_time_parse(before->data, before->length, &before_tm, 0) == -1)
|
||||
if (!ASN1_TIME_to_tm(before, &before_tm))
|
||||
goto err;
|
||||
if (ASN1_time_parse(after->data, after->length, &after_tm, 0) == -1)
|
||||
if (!ASN1_TIME_to_tm(after, &after_tm))
|
||||
goto err;
|
||||
if (!ASN1_time_tm_clamp_notafter(&after_tm))
|
||||
goto err;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: tls_internal.h,v 1.82 2023/06/18 11:43:03 op Exp $ */
|
||||
/* $OpenBSD: tls_internal.h,v 1.83 2023/06/27 18:19:59 tb Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org>
|
||||
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
|
||||
|
@ -70,6 +70,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;
|
||||
|
||||
|
@ -103,6 +107,8 @@ struct tls_config {
|
|||
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 {
|
||||
|
@ -282,13 +288,30 @@ 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);
|
||||
EC_KEY_METHOD *tls_signer_ecdsa_method(void);
|
||||
|
||||
#define TLS_PADDING_NONE 0
|
||||
#define TLS_PADDING_RSA_PKCS1 1
|
||||
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* XXX prototypes brought for OpenSMTPD libtls wrapper to OpenSSL */
|
||||
int ASN1_time_parse(const char *bytes, size_t len, struct tm *tm, int mode);
|
||||
|
||||
#ifndef HAVE_SSL_CTX_USE_CERTIFICATE_CHAIN_MEM
|
||||
int SSL_CTX_use_certificate_chain_mem(SSL_CTX *, void *, int);
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: tls_ocsp.c,v 1.23 2023/05/14 07:26:25 op Exp $ */
|
||||
/* $OpenBSD: tls_ocsp.c,v 1.24 2023/11/13 10:56:19 tb Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2015 Marko Kreen <markokr@gmail.com>
|
||||
* Copyright (c) 2016 Bob Beck <beck@openbsd.org>
|
||||
|
@ -66,8 +66,9 @@ tls_ocsp_asn1_parse_time(struct tls *ctx, ASN1_GENERALIZEDTIME *gt, time_t *gt_t
|
|||
if (gt == NULL)
|
||||
return -1;
|
||||
/* RFC 6960 specifies that all times in OCSP must be GENERALIZEDTIME */
|
||||
if (ASN1_time_parse(gt->data, gt->length, &tm,
|
||||
V_ASN1_GENERALIZEDTIME) == -1)
|
||||
if (!ASN1_GENERALIZEDTIME_check(gt))
|
||||
return -1;
|
||||
if (!ASN1_TIME_to_tm(gt, &tm))
|
||||
return -1;
|
||||
if ((*gt_time = timegm(&tm)) == -1)
|
||||
return -1;
|
||||
|
|
|
@ -0,0 +1,443 @@
|
|||
/* $OpenBSD: tls_signer.c,v 1.9 2023/06/18 19:12:58 tb 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 "config.h"
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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;
|
||||
|
||||
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:
|
||||
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 = EC_KEY_get_ex_data(eckey, 0);
|
||||
config = EC_KEY_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);
|
||||
}
|
||||
|
||||
EC_KEY_METHOD *
|
||||
tls_signer_ecdsa_method(void)
|
||||
{
|
||||
static EC_KEY_METHOD *ecdsa_method = NULL;
|
||||
const EC_KEY_METHOD *default_method;
|
||||
int (*sign)(int type, const unsigned char *dgst, int dlen,
|
||||
unsigned char *sig, unsigned int *siglen,
|
||||
const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey);
|
||||
int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
|
||||
BIGNUM **kinvp, BIGNUM **rp);
|
||||
|
||||
if (ecdsa_method != NULL)
|
||||
goto out;
|
||||
|
||||
default_method = EC_KEY_get_default_method();
|
||||
ecdsa_method = EC_KEY_METHOD_new(default_method);
|
||||
if (ecdsa_method == NULL)
|
||||
goto out;
|
||||
|
||||
EC_KEY_METHOD_get_sign(default_method, &sign, &sign_setup, NULL);
|
||||
EC_KEY_METHOD_set_sign(ecdsa_method, sign, sign_setup,
|
||||
tls_ecdsa_do_sign);
|
||||
|
||||
out:
|
||||
return (ecdsa_method);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: tls_verify.c,v 1.23 2023/05/11 07:35:27 tb Exp $ */
|
||||
/* $OpenBSD: tls_verify.c,v 1.29 2023/11/22 18:23:09 op Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org>
|
||||
*
|
||||
|
@ -94,15 +94,21 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name,
|
|||
union tls_addr addrbuf;
|
||||
int addrlen, type;
|
||||
int count, i;
|
||||
int rv = 0;
|
||||
int critical = 0;
|
||||
int rv = -1;
|
||||
|
||||
*alt_match = 0;
|
||||
*alt_exists = 0;
|
||||
|
||||
altname_stack = X509_get_ext_d2i(cert, NID_subject_alt_name,
|
||||
NULL, NULL);
|
||||
if (altname_stack == NULL)
|
||||
return 0;
|
||||
altname_stack = X509_get_ext_d2i(cert, NID_subject_alt_name, &critical,
|
||||
NULL);
|
||||
if (altname_stack == NULL) {
|
||||
if (critical != -1) {
|
||||
tls_set_errorx(ctx, "error decoding subjectAltName");
|
||||
goto err;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, name, &addrbuf) == 1) {
|
||||
type = GEN_IPADD;
|
||||
|
@ -142,8 +148,7 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name,
|
|||
"NUL byte in subjectAltName, "
|
||||
"probably a malicious certificate",
|
||||
name);
|
||||
rv = -1;
|
||||
break;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -156,13 +161,12 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name,
|
|||
"error verifying name '%s': "
|
||||
"a dNSName of \" \" must not be "
|
||||
"used", name);
|
||||
rv = -1;
|
||||
break;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tls_match_name(data, name) == 0) {
|
||||
*alt_match = 1;
|
||||
break;
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
|
@ -183,8 +187,7 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name,
|
|||
tls_set_errorx(ctx,
|
||||
"Unexpected negative length for an "
|
||||
"IP address: %d", datalen);
|
||||
rv = -1;
|
||||
break;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -194,11 +197,15 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name,
|
|||
if (datalen == addrlen &&
|
||||
memcmp(data, &addrbuf, addrlen) == 0) {
|
||||
*alt_match = 1;
|
||||
break;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
rv = 0;
|
||||
|
||||
err:
|
||||
sk_GENERAL_NAME_pop_free(altname_stack, GENERAL_NAME_free);
|
||||
return rv;
|
||||
}
|
||||
|
@ -207,10 +214,13 @@ static int
|
|||
tls_check_common_name(struct tls *ctx, X509 *cert, const char *name,
|
||||
int *cn_match)
|
||||
{
|
||||
unsigned char *utf8_bytes = NULL;
|
||||
X509_NAME *subject_name;
|
||||
char *common_name = NULL;
|
||||
union tls_addr addrbuf;
|
||||
int common_name_len;
|
||||
ASN1_STRING *data;
|
||||
int lastpos = -1;
|
||||
int rv = -1;
|
||||
|
||||
*cn_match = 0;
|
||||
|
@ -219,29 +229,65 @@ tls_check_common_name(struct tls *ctx, X509 *cert, const char *name,
|
|||
if (subject_name == NULL)
|
||||
goto done;
|
||||
|
||||
common_name_len = X509_NAME_get_text_by_NID(subject_name,
|
||||
NID_commonName, NULL, 0);
|
||||
if (common_name_len < 0)
|
||||
lastpos = X509_NAME_get_index_by_NID(subject_name,
|
||||
NID_commonName, lastpos);
|
||||
if (lastpos == -1)
|
||||
goto done;
|
||||
|
||||
common_name = calloc(common_name_len + 1, 1);
|
||||
if (common_name == NULL) {
|
||||
tls_set_error(ctx, "out of memory");
|
||||
if (lastpos < 0)
|
||||
goto err;
|
||||
if (X509_NAME_get_index_by_NID(subject_name, NID_commonName, lastpos)
|
||||
!= -1) {
|
||||
/*
|
||||
* Having multiple CN's is possible, and even happened back in
|
||||
* the glory days of mullets and Hammer pants. In anything like
|
||||
* a modern TLS cert, CN is as close to deprecated as it gets,
|
||||
* and having more than one is bad. We therefore fail if we have
|
||||
* more than one CN fed to us in the subject, treating the
|
||||
* certificate as hostile.
|
||||
*/
|
||||
tls_set_errorx(ctx, "error verifying name '%s': "
|
||||
"Certificate subject contains multiple Common Name fields, "
|
||||
"probably a malicious or malformed certificate", name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
X509_NAME_get_text_by_NID(subject_name, NID_commonName, common_name,
|
||||
common_name_len + 1);
|
||||
|
||||
/* NUL bytes in CN? */
|
||||
if (common_name_len < 0 ||
|
||||
(size_t)common_name_len != strlen(common_name)) {
|
||||
data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name,
|
||||
lastpos));
|
||||
/*
|
||||
* Fail if we cannot encode the CN bytes as UTF-8.
|
||||
*/
|
||||
if ((common_name_len = ASN1_STRING_to_UTF8(&utf8_bytes, data)) < 0) {
|
||||
tls_set_errorx(ctx, "error verifying name '%s': "
|
||||
"Common Name field cannot be encoded as a UTF-8 string, "
|
||||
"probably a malicious certificate", name);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* Fail if the CN is of invalid length. RFC 5280 specifies that a CN
|
||||
* must be between 1 and 64 bytes long.
|
||||
*/
|
||||
if (common_name_len < 1 || common_name_len > 64) {
|
||||
tls_set_errorx(ctx, "error verifying name '%s': "
|
||||
"Common Name field has invalid length, "
|
||||
"probably a malicious certificate", name);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* Fail if the resulting text contains a NUL byte.
|
||||
*/
|
||||
if (memchr(utf8_bytes, 0, common_name_len) != NULL) {
|
||||
tls_set_errorx(ctx, "error verifying name '%s': "
|
||||
"NUL byte in Common Name field, "
|
||||
"probably a malicious certificate", name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
common_name = strndup(utf8_bytes, common_name_len);
|
||||
if (common_name == NULL) {
|
||||
tls_set_error(ctx, "out of memory");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't want to attempt wildcard matching against IP addresses,
|
||||
* so perform a simple comparison here.
|
||||
|
@ -260,6 +306,7 @@ tls_check_common_name(struct tls *ctx, X509 *cert, const char *name,
|
|||
rv = 0;
|
||||
|
||||
err:
|
||||
free(utf8_bytes);
|
||||
free(common_name);
|
||||
return rv;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue