From: joshua Date: Tue, 26 Mar 2024 06:24:52 +0000 (+0000) Subject: Add error code support to libtls X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=7a756d3745d54f76014cbb694af2a7a421409519;p=openbsd Add error code support to libtls This adds tls_config_error_code() and tls_error_code(), which will become public API at a later date. Additional error codes will be added in follow-up commits. ok jsing@ beck@ --- diff --git a/lib/libtls/tls.c b/lib/libtls/tls.c index 58245009d74..8433f556bf0 100644 --- a/lib/libtls/tls.c +++ b/lib/libtls/tls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls.c,v 1.100 2024/03/26 01:15:57 joshua Exp $ */ +/* $OpenBSD: tls.c,v 1.101 2024/03/26 06:24:52 joshua Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -72,23 +72,32 @@ tls_error(struct tls *ctx) return ctx->error.msg; } +int +tls_error_code(struct tls *ctx) +{ + return ctx->error.code; +} + void tls_error_clear(struct tls_error *error) { free(error->msg); error->msg = NULL; + error->code = TLS_ERROR_UNKNOWN; error->errno_value = 0; error->tls = 0; } static int -tls_error_vset(struct tls_error *error, int errno_value, const char *fmt, va_list ap) +tls_error_vset(struct tls_error *error, int code, int errno_value, + const char *fmt, va_list ap) { char *errmsg = NULL; int rv = -1; tls_error_clear(error); + error->code = code; error->errno_value = errno_value; error->tls = 1; @@ -115,7 +124,7 @@ tls_error_vset(struct tls_error *error, int errno_value, const char *fmt, va_lis } int -tls_error_set(struct tls_error *error, const char *fmt, ...) +tls_error_set(struct tls_error *error, int code, const char *fmt, ...) { va_list ap; int errno_value, rv; @@ -123,27 +132,27 @@ tls_error_set(struct tls_error *error, const char *fmt, ...) errno_value = errno; va_start(ap, fmt); - rv = tls_error_vset(error, errno_value, fmt, ap); + rv = tls_error_vset(error, code, errno_value, fmt, ap); va_end(ap); return (rv); } int -tls_error_setx(struct tls_error *error, const char *fmt, ...) +tls_error_setx(struct tls_error *error, int code, const char *fmt, ...) { va_list ap; int rv; va_start(ap, fmt); - rv = tls_error_vset(error, -1, fmt, ap); + rv = tls_error_vset(error, code, -1, fmt, ap); va_end(ap); return (rv); } int -tls_config_set_error(struct tls_config *config, const char *fmt, ...) +tls_config_set_error(struct tls_config *config, int code, const char *fmt, ...) { va_list ap; int errno_value, rv; @@ -151,27 +160,27 @@ tls_config_set_error(struct tls_config *config, const char *fmt, ...) errno_value = errno; va_start(ap, fmt); - rv = tls_error_vset(&config->error, errno_value, fmt, ap); + rv = tls_error_vset(&config->error, code, errno_value, fmt, ap); va_end(ap); return (rv); } int -tls_config_set_errorx(struct tls_config *config, const char *fmt, ...) +tls_config_set_errorx(struct tls_config *config, int code, const char *fmt, ...) { va_list ap; int rv; va_start(ap, fmt); - rv = tls_error_vset(&config->error, -1, fmt, ap); + rv = tls_error_vset(&config->error, code, -1, fmt, ap); va_end(ap); return (rv); } int -tls_set_error(struct tls *ctx, const char *fmt, ...) +tls_set_error(struct tls *ctx, int code, const char *fmt, ...) { va_list ap; int errno_value, rv; @@ -179,27 +188,27 @@ tls_set_error(struct tls *ctx, const char *fmt, ...) errno_value = errno; va_start(ap, fmt); - rv = tls_error_vset(&ctx->error, errno_value, fmt, ap); + rv = tls_error_vset(&ctx->error, code, errno_value, fmt, ap); va_end(ap); return (rv); } int -tls_set_errorx(struct tls *ctx, const char *fmt, ...) +tls_set_errorx(struct tls *ctx, int code, const char *fmt, ...) { va_list ap; int rv; va_start(ap, fmt); - rv = tls_error_vset(&ctx->error, -1, fmt, ap); + rv = tls_error_vset(&ctx->error, code, -1, fmt, ap); va_end(ap); return (rv); } int -tls_set_ssl_errorx(struct tls *ctx, const char *fmt, ...) +tls_set_ssl_errorx(struct tls *ctx, int code, const char *fmt, ...) { va_list ap; int rv; @@ -209,7 +218,7 @@ tls_set_ssl_errorx(struct tls *ctx, const char *fmt, ...) return (0); va_start(ap, fmt); - rv = tls_error_vset(&ctx->error, -1, fmt, ap); + rv = tls_error_vset(&ctx->error, code, -1, fmt, ap); va_end(ap); return (rv); @@ -350,31 +359,35 @@ tls_keypair_to_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY **pke return (0); if (len > INT_MAX) { - tls_set_errorx(ctx, ctx->config->use_fake_private_key ? + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + 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"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "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"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to read X509 certificate"); goto err; } if ((*pkey = X509_get_pubkey(x509)) == NULL) { - tls_set_errorx(ctx, "failed to retrieve pubkey"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "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; + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to read private key"); + goto err; } } @@ -399,7 +412,7 @@ tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *p return (0); if (keypair->pubkey_hash == NULL) { - tls_set_errorx(ctx, "public key hash not set"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "public key hash not set"); goto err; } @@ -407,7 +420,8 @@ tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *p 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"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "RSA key setup failure"); goto err; } if (ctx->config->sign_cb != NULL) { @@ -415,20 +429,23 @@ tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *p 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"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "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"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "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) { - tls_set_errorx(ctx, "EC key setup failure"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "EC key setup failure"); goto err; } if (ctx->config->sign_cb != NULL) { @@ -436,18 +453,20 @@ tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *p 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"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "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"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to set EC key"); goto err; } break; default: - tls_set_errorx(ctx, "incorrect key type"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "incorrect key type"); goto err; } @@ -472,13 +491,15 @@ tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx, if (keypair->cert_mem != NULL) { if (keypair->cert_len > INT_MAX) { - tls_set_errorx(ctx, "certificate too long"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "certificate too long"); goto err; } if (SSL_CTX_use_certificate_chain_mem(ssl_ctx, keypair->cert_mem, keypair->cert_len) != 1) { - tls_set_errorx(ctx, "failed to load certificate"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to load certificate"); goto err; } } @@ -489,7 +510,8 @@ tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx, if (tls_keypair_setup_pkey(ctx, keypair, pkey) == -1) goto err; if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) { - tls_set_errorx(ctx, "failed to load private key"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to load private key"); goto err; } EVP_PKEY_free(pkey); @@ -498,7 +520,8 @@ tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx, if (!ctx->config->skip_private_key_check && SSL_CTX_check_private_key(ssl_ctx) != 1) { - tls_set_errorx(ctx, "private/public key mismatch"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "private/public key mismatch"); goto err; } @@ -534,7 +557,8 @@ tls_configure_ssl(struct tls *ctx, SSL_CTX *ssl_ctx) if (ctx->config->alpn != NULL) { if (SSL_CTX_set_alpn_protos(ssl_ctx, ctx->config->alpn, ctx->config->alpn_len) != 0) { - tls_set_errorx(ctx, "failed to set alpn"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to set alpn"); goto err; } } @@ -542,7 +566,8 @@ tls_configure_ssl(struct tls *ctx, SSL_CTX *ssl_ctx) if (ctx->config->ciphers != NULL) { if (SSL_CTX_set_cipher_list(ssl_ctx, ctx->config->ciphers) != 1) { - tls_set_errorx(ctx, "failed to set ciphers"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to set ciphers"); goto err; } } @@ -572,7 +597,8 @@ tls_ssl_cert_verify_cb(X509_STORE_CTX *x509_ctx, void *arg) return (1); if ((X509_verify_cert(x509_ctx)) < 0) { - tls_set_errorx(ctx, "X509 verify cert failed"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "X509 verify cert failed"); return (0); } @@ -580,7 +606,8 @@ tls_ssl_cert_verify_cb(X509_STORE_CTX *x509_ctx, void *arg) if (x509_err == X509_V_OK) return (1); - tls_set_errorx(ctx, "certificate verification failed: %s", + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "certificate verification failed: %s", X509_verify_cert_error_string(x509_err)); return (0); @@ -620,31 +647,35 @@ tls_configure_ssl_verify(struct tls *ctx, SSL_CTX *ssl_ctx, int verify) if (ca_mem != NULL) { if (ca_len > INT_MAX) { - tls_set_errorx(ctx, "ca too long"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "ca too long"); goto err; } if (SSL_CTX_load_verify_mem(ssl_ctx, ca_mem, ca_len) != 1) { - tls_set_errorx(ctx, "ssl verify memory setup failure"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "ssl verify memory setup failure"); goto err; } } else if (SSL_CTX_load_verify_locations(ssl_ctx, NULL, ctx->config->ca_path) != 1) { - tls_set_errorx(ctx, "ssl verify locations failure"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "ssl verify locations failure"); goto err; } if (crl_mem != NULL) { if (crl_len > INT_MAX) { - tls_set_errorx(ctx, "crl too long"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "crl too long"); goto err; } if ((bio = BIO_new_mem_buf(crl_mem, crl_len)) == NULL) { - tls_set_errorx(ctx, "failed to create buffer"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to create buffer"); goto err; } if ((xis = PEM_X509_INFO_read_bio(bio, NULL, tls_password_cb, NULL)) == NULL) { - tls_set_errorx(ctx, "failed to parse crl"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to parse crl"); goto err; } store = SSL_CTX_get_cert_store(ssl_ctx); @@ -653,7 +684,8 @@ tls_configure_ssl_verify(struct tls *ctx, SSL_CTX *ssl_ctx, int verify) if (xi->crl == NULL) continue; if (!X509_STORE_add_crl(store, xi->crl)) { - tls_set_error(ctx, "failed to add crl"); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, + "failed to add crl"); goto err; } } @@ -759,21 +791,24 @@ tls_ssl_error(struct tls *ctx, SSL *ssl_conn, int ssl_ret, const char *prefix) } else if (ssl_ret == -1) { errstr = strerror(errno); } - tls_set_ssl_errorx(ctx, "%s failed: %s", prefix, errstr); + tls_set_ssl_errorx(ctx, TLS_ERROR_UNKNOWN, + "%s failed: %s", prefix, errstr); return (-1); case SSL_ERROR_SSL: if ((err = ERR_peek_error()) != 0) { errstr = ERR_error_string(err, NULL); } - tls_set_ssl_errorx(ctx, "%s failed: %s", prefix, errstr); + tls_set_ssl_errorx(ctx, TLS_ERROR_UNKNOWN, + "%s failed: %s", prefix, errstr); return (-1); case SSL_ERROR_WANT_CONNECT: case SSL_ERROR_WANT_ACCEPT: case SSL_ERROR_WANT_X509_LOOKUP: default: - tls_set_ssl_errorx(ctx, "%s failed (%d)", prefix, ssl_err); + tls_set_ssl_errorx(ctx, TLS_ERROR_UNKNOWN, + "%s failed (%d)", prefix, ssl_err); return (-1); } } @@ -786,12 +821,14 @@ tls_handshake(struct tls *ctx) tls_error_clear(&ctx->error); if ((ctx->flags & (TLS_CLIENT | TLS_SERVER_CONN)) == 0) { - tls_set_errorx(ctx, "invalid operation for context"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "invalid operation for context"); goto out; } if ((ctx->state & TLS_HANDSHAKE_COMPLETE) != 0) { - tls_set_errorx(ctx, "handshake already completed"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "handshake already completed"); goto out; } @@ -828,7 +865,8 @@ tls_read(struct tls *ctx, void *buf, size_t buflen) } if (buflen > INT_MAX) { - tls_set_errorx(ctx, "buflen too long"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "buflen too long"); goto out; } @@ -859,7 +897,8 @@ tls_write(struct tls *ctx, const void *buf, size_t buflen) } if (buflen > INT_MAX) { - tls_set_errorx(ctx, "buflen too long"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "buflen too long"); goto out; } @@ -885,7 +924,8 @@ tls_close(struct tls *ctx) tls_error_clear(&ctx->error); if ((ctx->flags & (TLS_CLIENT | TLS_SERVER_CONN)) == 0) { - tls_set_errorx(ctx, "invalid operation for context"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "invalid operation for context"); rv = -1; goto out; } @@ -906,13 +946,13 @@ tls_close(struct tls *ctx) if (shutdown(ctx->socket, SHUT_RDWR) != 0) { if (rv == 0 && errno != ENOTCONN && errno != ECONNRESET) { - tls_set_error(ctx, "shutdown"); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, "shutdown"); rv = -1; } } if (close(ctx->socket) != 0) { if (rv == 0) { - tls_set_error(ctx, "close"); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, "close"); rv = -1; } } @@ -920,7 +960,7 @@ tls_close(struct tls *ctx) } if ((ctx->state & TLS_EOF_NO_CLOSE_NOTIFY) != 0) { - tls_set_errorx(ctx, "EOF without close notify"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "EOF without close notify"); rv = -1; } diff --git a/lib/libtls/tls.h b/lib/libtls/tls.h index 34183745e5e..0113c1c67f0 100644 --- a/lib/libtls/tls.h +++ b/lib/libtls/tls.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls.h,v 1.63 2023/07/02 06:37:27 beck Exp $ */ +/* $OpenBSD: tls.h,v 1.64 2024/03/26 06:24:52 joshua Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -76,6 +76,12 @@ extern "C" { #define TLS_MAX_SESSION_ID_LENGTH 32 #define TLS_TICKET_KEY_SIZE 48 +/* Error codes */ +#if defined(LIBRESSL_NEXT_API) || defined(LIBRESSL_INTERNAL) +#define TLS_ERROR_UNKNOWN 0x0000 +#define TLS_ERROR_OUT_OF_MEMORY 0x1000 +#endif + struct tls; struct tls_config; @@ -88,6 +94,10 @@ int tls_init(void); const char *tls_config_error(struct tls_config *_config); const char *tls_error(struct tls *_ctx); +#if defined(LIBRESSL_NEXT_API) || defined(LIBRESSL_INTERNAL) +int tls_config_error_code(struct tls_config *_config); +int tls_error_code(struct tls *_ctx); +#endif struct tls_config *tls_config_new(void); void tls_config_free(struct tls_config *_config); diff --git a/lib/libtls/tls_bio_cb.c b/lib/libtls/tls_bio_cb.c index 8a1edfd5e4c..56b9e12a715 100644 --- a/lib/libtls/tls_bio_cb.c +++ b/lib/libtls/tls_bio_cb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_bio_cb.c,v 1.21 2023/05/14 07:26:25 op Exp $ */ +/* $OpenBSD: tls_bio_cb.c,v 1.22 2024/03/26 06:24:52 joshua Exp $ */ /* * Copyright (c) 2016 Tobias Pape * @@ -143,7 +143,7 @@ tls_set_cbs(struct tls *ctx, tls_read_cb read_cb, tls_write_cb write_cb, int rv = -1; if (read_cb == NULL || write_cb == NULL) { - tls_set_errorx(ctx, "no callbacks provided"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "no callbacks provided"); goto err; } @@ -152,11 +152,13 @@ tls_set_cbs(struct tls *ctx, tls_read_cb read_cb, tls_write_cb write_cb, ctx->cb_arg = cb_arg; if ((bio_cb = bio_s_cb()) == NULL) { - tls_set_errorx(ctx, "failed to create callback method"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to create callback method"); goto err; } if ((bio = BIO_new(bio_cb)) == NULL) { - tls_set_errorx(ctx, "failed to create callback i/o"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to create callback i/o"); goto err; } BIO_set_data(bio, ctx); diff --git a/lib/libtls/tls_client.c b/lib/libtls/tls_client.c index deb24ebc23e..40ef9a02e21 100644 --- a/lib/libtls/tls_client.c +++ b/lib/libtls/tls_client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_client.c,v 1.49 2023/05/14 07:26:25 op Exp $ */ +/* $OpenBSD: tls_client.c,v 1.50 2024/03/26 06:24:52 joshua Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -66,12 +66,12 @@ tls_connect_servername(struct tls *ctx, const char *host, const char *port, int rv = -1, s = -1, ret; if ((ctx->flags & TLS_CLIENT) == 0) { - tls_set_errorx(ctx, "not a client context"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "not a client context"); goto err; } if (host == NULL) { - tls_set_errorx(ctx, "host not specified"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "host not specified"); goto err; } @@ -79,11 +79,11 @@ tls_connect_servername(struct tls *ctx, const char *host, const char *port, if (port == NULL) { ret = tls_host_port(host, &hs, &ps); if (ret == -1) { - tls_set_errorx(ctx, "memory allocation failure"); + tls_set_errorx(ctx, TLS_ERROR_OUT_OF_MEMORY, "out of memory"); goto err; } if (ret != 0) { - tls_set_errorx(ctx, "no port provided"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "no port provided"); goto err; } } @@ -114,7 +114,8 @@ tls_connect_servername(struct tls *ctx, const char *host, const char *port, hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_ADDRCONFIG; if ((s = getaddrinfo(h, p, &hints, &res0)) != 0) { - tls_set_error(ctx, "%s", gai_strerror(s)); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, + "%s", gai_strerror(s)); goto err; } } @@ -125,11 +126,13 @@ tls_connect_servername(struct tls *ctx, const char *host, const char *port, for (res = res0; res; res = res->ai_next) { s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s == -1) { - tls_set_error(ctx, "socket"); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, + "socket"); continue; } if (connect(s, res->ai_addr, res->ai_addrlen) == -1) { - tls_set_error(ctx, "connect"); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, + "connect"); close(s); s = -1; continue; @@ -174,11 +177,13 @@ tls_client_read_session(struct tls *ctx) int rv = -1; if (fstat(sfd, &sb) == -1) { - tls_set_error(ctx, "failed to stat session file"); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, + "failed to stat session file"); goto err; } if (sb.st_size < 0 || sb.st_size > INT_MAX) { - tls_set_errorx(ctx, "invalid session file size"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "invalid session file size"); goto err; } session_len = (size_t)sb.st_size; @@ -192,19 +197,22 @@ tls_client_read_session(struct tls *ctx) n = pread(sfd, session, session_len, 0); if (n < 0 || (size_t)n != session_len) { - tls_set_error(ctx, "failed to read session file"); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, + "failed to read session file"); goto err; } if ((bio = BIO_new_mem_buf(session, session_len)) == NULL) goto err; if ((ss = PEM_read_bio_SSL_SESSION(bio, NULL, tls_password_cb, NULL)) == NULL) { - tls_set_errorx(ctx, "failed to parse session"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to parse session"); goto err; } if (SSL_set_session(ctx->ssl_conn, ss) != 1) { - tls_set_errorx(ctx, "failed to set session"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to set session"); goto err; } @@ -234,7 +242,8 @@ tls_client_write_session(struct tls *ctx) if ((ss = SSL_get1_session(ctx->ssl_conn)) == NULL) { if (ftruncate(sfd, 0) == -1) { - tls_set_error(ctx, "failed to truncate session file"); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, + "failed to truncate session file"); goto err; } goto done; @@ -251,12 +260,14 @@ tls_client_write_session(struct tls *ctx) offset = 0; if (ftruncate(sfd, len) == -1) { - tls_set_error(ctx, "failed to truncate session file"); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, + "failed to truncate session file"); goto err; } while (len > 0) { if ((n = pwrite(sfd, data + offset, len, offset)) == -1) { - tls_set_error(ctx, "failed to write session file"); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, + "failed to write session file"); goto err; } offset += n; @@ -281,13 +292,14 @@ tls_connect_common(struct tls *ctx, const char *servername) int rv = -1; if ((ctx->flags & TLS_CLIENT) == 0) { - tls_set_errorx(ctx, "not a client context"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "not a client context"); goto err; } if (servername != NULL) { if ((ctx->servername = strdup(servername)) == NULL) { - tls_set_errorx(ctx, "out of memory"); + tls_set_errorx(ctx, TLS_ERROR_OUT_OF_MEMORY, + "out of memory"); goto err; } @@ -304,7 +316,7 @@ tls_connect_common(struct tls *ctx, const char *servername) } if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { - tls_set_errorx(ctx, "ssl context failure"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "ssl context failure"); goto err; } @@ -317,7 +329,8 @@ tls_connect_common(struct tls *ctx, const char *servername) if (ctx->config->verify_name) { if (ctx->servername == NULL) { - tls_set_errorx(ctx, "server name not specified"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "server name not specified"); goto err; } } @@ -328,23 +341,26 @@ tls_connect_common(struct tls *ctx, const char *servername) if (ctx->config->ecdhecurves != NULL) { if (SSL_CTX_set1_groups(ctx->ssl_ctx, ctx->config->ecdhecurves, ctx->config->ecdhecurves_len) != 1) { - tls_set_errorx(ctx, "failed to set ecdhe curves"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to set ecdhe curves"); goto err; } } if (SSL_CTX_set_tlsext_status_cb(ctx->ssl_ctx, tls_ocsp_verify_cb) != 1) { - tls_set_errorx(ctx, "ssl OCSP verification setup failure"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "ssl OCSP verification setup failure"); goto err; } if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { - tls_set_errorx(ctx, "ssl connection failure"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "ssl connection failure"); goto err; } if (SSL_set_app_data(ctx->ssl_conn, ctx) != 1) { - tls_set_errorx(ctx, "ssl application data failure"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "ssl application data failure"); goto err; } @@ -355,7 +371,8 @@ tls_connect_common(struct tls *ctx, const char *servername) } if (SSL_set_tlsext_status_type(ctx->ssl_conn, TLSEXT_STATUSTYPE_ocsp) != 1) { - tls_set_errorx(ctx, "ssl OCSP extension setup failure"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "ssl OCSP extension setup failure"); goto err; } @@ -368,7 +385,8 @@ tls_connect_common(struct tls *ctx, const char *servername) 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"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "server name indication failure"); goto err; } } @@ -393,7 +411,7 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write, int rv = -1; if (fd_read < 0 || fd_write < 0) { - tls_set_errorx(ctx, "invalid file descriptors"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "invalid file descriptors"); goto err; } @@ -402,7 +420,8 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write, if (SSL_set_rfd(ctx->ssl_conn, fd_read) != 1 || SSL_set_wfd(ctx->ssl_conn, fd_write) != 1) { - tls_set_errorx(ctx, "ssl file descriptor failure"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "ssl file descriptor failure"); goto err; } @@ -437,12 +456,12 @@ tls_handshake_client(struct tls *ctx) int rv = -1; if ((ctx->flags & TLS_CLIENT) == 0) { - tls_set_errorx(ctx, "not a client context"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "not a client context"); goto err; } if ((ctx->state & TLS_CONNECTED) == 0) { - tls_set_errorx(ctx, "context not connected"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "context not connected"); goto err; } @@ -457,14 +476,16 @@ tls_handshake_client(struct tls *ctx) if (ctx->config->verify_name) { cert = SSL_get_peer_certificate(ctx->ssl_conn); if (cert == NULL) { - tls_set_errorx(ctx, "no server certificate"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "no server certificate"); goto err; } if (tls_check_name(ctx, cert, ctx->servername, &match) == -1) goto err; if (!match) { - tls_set_errorx(ctx, "name `%s' not present in" - " server certificate", ctx->servername); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "name `%s' not present in server certificate", + ctx->servername); goto err; } } diff --git a/lib/libtls/tls_config.c b/lib/libtls/tls_config.c index 5eb5b69ac6e..449071641bc 100644 --- a/lib/libtls/tls_config.c +++ b/lib/libtls/tls_config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_config.c,v 1.67 2023/07/02 06:37:27 beck Exp $ */ +/* $OpenBSD: tls_config.c,v 1.68 2024/03/26 06:24:52 joshua Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -50,12 +50,14 @@ tls_config_load_file(struct tls_error *error, const char *filetype, *len = 0; if ((fd = open(filename, O_RDONLY)) == -1) { - tls_error_set(error, "failed to open %s file '%s'", + tls_error_set(error, TLS_ERROR_UNKNOWN, + "failed to open %s file '%s'", filetype, filename); goto err; } if (fstat(fd, &st) != 0) { - tls_error_set(error, "failed to stat %s file '%s'", + tls_error_set(error, TLS_ERROR_UNKNOWN, + "failed to stat %s file '%s'", filetype, filename); goto err; } @@ -63,13 +65,15 @@ tls_config_load_file(struct tls_error *error, const char *filetype, goto err; *len = (size_t)st.st_size; if ((*buf = malloc(*len)) == NULL) { - tls_error_set(error, "failed to allocate buffer for " - "%s file", filetype); + tls_error_set(error, TLS_ERROR_UNKNOWN, + "failed to allocate buffer for %s file", + filetype); goto err; } n = read(fd, *buf, *len); if (n < 0 || (size_t)n != *len) { - tls_error_set(error, "failed to read %s file '%s'", + tls_error_set(error, TLS_ERROR_UNKNOWN, + "failed to read %s file '%s'", filetype, filename); goto err; } @@ -203,6 +207,12 @@ tls_config_error(struct tls_config *config) return config->error.msg; } +int +tls_config_error_code(struct tls_config *config) +{ + return config->error.code; +} + void tls_config_clear_keys(struct tls_config *config) { @@ -291,17 +301,19 @@ tls_config_parse_alpn(struct tls_config *config, const char *alpn, *alpn_len = 0; if ((buf_len = strlen(alpn) + 1) > 65535) { - tls_config_set_errorx(config, "alpn too large"); + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, "alpn too large"); goto err; } if ((buf = malloc(buf_len)) == NULL) { - tls_config_set_errorx(config, "out of memory"); + tls_config_set_errorx(config, TLS_ERROR_OUT_OF_MEMORY, + "out of memory"); goto err; } if ((s = strdup(alpn)) == NULL) { - tls_config_set_errorx(config, "out of memory"); + tls_config_set_errorx(config, TLS_ERROR_OUT_OF_MEMORY, + "out of memory"); goto err; } @@ -309,12 +321,12 @@ tls_config_parse_alpn(struct tls_config *config, const char *alpn, q = s; while ((p = strsep(&q, ",")) != NULL) { if ((len = strlen(p)) == 0) { - tls_config_set_errorx(config, + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, "alpn protocol with zero length"); goto err; } if (len > 255) { - tls_config_set_errorx(config, + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, "alpn protocol too long"); goto err; } @@ -484,11 +496,13 @@ tls_config_set_ciphers(struct tls_config *config, const char *ciphers) ciphers = TLS_CIPHERS_ALL; if ((ssl_ctx = SSL_CTX_new(SSLv23_method())) == NULL) { - tls_config_set_errorx(config, "out of memory"); + tls_config_set_errorx(config, TLS_ERROR_OUT_OF_MEMORY, + "out of memory"); goto err; } if (SSL_CTX_set_cipher_list(ssl_ctx, ciphers) != 1) { - tls_config_set_errorx(config, "no ciphers for '%s'", ciphers); + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, + "no ciphers for '%s'", ciphers); goto err; } @@ -526,7 +540,8 @@ tls_config_set_dheparams(struct tls_config *config, const char *params) else if (strcasecmp(params, "legacy") == 0) keylen = 1024; else { - tls_config_set_errorx(config, "invalid dhe param '%s'", params); + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, + "invalid dhe param '%s'", params); return (-1); } @@ -543,8 +558,8 @@ tls_config_set_ecdhecurve(struct tls_config *config, const char *curve) strcasecmp(curve, "auto") == 0) { curve = TLS_ECDHE_CURVES; } else if (strchr(curve, ',') != NULL || strchr(curve, ':') != NULL) { - tls_config_set_errorx(config, "invalid ecdhe curve '%s'", - curve); + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, + "invalid ecdhe curve '%s'", curve); return (-1); } @@ -569,7 +584,8 @@ tls_config_set_ecdhecurves(struct tls_config *config, const char *curves) curves = TLS_ECDHE_CURVES; if ((cs = strdup(curves)) == NULL) { - tls_config_set_errorx(config, "out of memory"); + tls_config_set_errorx(config, TLS_ERROR_OUT_OF_MEMORY, + "out of memory"); goto err; } @@ -584,14 +600,15 @@ tls_config_set_ecdhecurves(struct tls_config *config, const char *curves) if (nid == NID_undef) nid = EC_curve_nist2nid(p); if (nid == NID_undef) { - tls_config_set_errorx(config, + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, "invalid ecdhe curve '%s'", p); goto err; } if ((curves_new = reallocarray(curves_list, curves_num + 1, sizeof(int))) == NULL) { - tls_config_set_errorx(config, "out of memory"); + tls_config_set_errorx(config, TLS_ERROR_OUT_OF_MEMORY, + "out of memory"); goto err; } curves_list = curves_new; @@ -712,24 +729,26 @@ tls_config_set_session_fd(struct tls_config *config, int session_fd) } if (fstat(session_fd, &sb) == -1) { - tls_config_set_error(config, "failed to stat session file"); + tls_config_set_error(config, TLS_ERROR_UNKNOWN, + "failed to stat session file"); return (-1); } if (!S_ISREG(sb.st_mode)) { - tls_config_set_errorx(config, + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, "session file is not a regular file"); return (-1); } if (sb.st_uid != getuid()) { - tls_config_set_errorx(config, "session file has incorrect " - "owner (uid %u != %u)", sb.st_uid, getuid()); + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, + "session file has incorrect owner (uid %u != %u)", + sb.st_uid, getuid()); return (-1); } mugo = sb.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO); if (mugo != (S_IRUSR|S_IWUSR)) { - tls_config_set_errorx(config, "session file has incorrect " - "permissions (%o != 600)", mugo); + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, + "session file has incorrect permissions (%o != 600)", mugo); return (-1); } @@ -846,7 +865,8 @@ tls_config_set_session_id(struct tls_config *config, const unsigned char *session_id, size_t len) { if (len > TLS_MAX_SESSION_ID_LENGTH) { - tls_config_set_errorx(config, "session ID too large"); + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, + "session ID too large"); return (-1); } memset(config->session_id, 0, sizeof(config->session_id)); @@ -858,11 +878,13 @@ int tls_config_set_session_lifetime(struct tls_config *config, int lifetime) { if (lifetime > TLS_MAX_SESSION_TIMEOUT) { - tls_config_set_errorx(config, "session lifetime too large"); + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, + "session lifetime too large"); return (-1); } if (lifetime != 0 && lifetime < TLS_MIN_SESSION_TIMEOUT) { - tls_config_set_errorx(config, "session lifetime too small"); + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, + "session lifetime too small"); return (-1); } @@ -879,7 +901,7 @@ tls_config_add_ticket_key(struct tls_config *config, uint32_t keyrev, if (TLS_TICKET_KEY_SIZE != keylen || sizeof(newkey.aes_key) + sizeof(newkey.hmac_key) > keylen) { - tls_config_set_errorx(config, + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, "wrong amount of ticket key data"); return (-1); } @@ -903,7 +925,8 @@ tls_config_add_ticket_key(struct tls_config *config, uint32_t keyrev, sizeof(tk->aes_key)) == 0 && memcmp(newkey.hmac_key, tk->hmac_key, sizeof(tk->hmac_key)) == 0) return (0); - tls_config_set_errorx(config, "ticket key already present"); + tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, + "ticket key already present"); return (-1); } diff --git a/lib/libtls/tls_conninfo.c b/lib/libtls/tls_conninfo.c index 08f8714ecd7..bc15b85eaf0 100644 --- a/lib/libtls/tls_conninfo.c +++ b/lib/libtls/tls_conninfo.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_conninfo.c,v 1.25 2024/03/24 11:30:12 beck Exp $ */ +/* $OpenBSD: tls_conninfo.c,v 1.26 2024/03/26 06:24:52 joshua Exp $ */ /* * Copyright (c) 2015 Joel Sing * Copyright (c) 2015 Bob Beck @@ -79,7 +79,7 @@ tls_get_peer_cert_hash(struct tls *ctx, char **hash) return (0); if (tls_cert_hash(ctx->ssl_peer_cert, hash) == -1) { - tls_set_errorx(ctx, "unable to compute peer certificate hash - out of memory"); + tls_set_errorx(ctx, TLS_ERROR_OUT_OF_MEMORY, "out of memory")y *hash = NULL; return -1; } @@ -245,7 +245,7 @@ tls_conninfo_populate(struct tls *ctx) tls_conninfo_free(ctx->conninfo); if ((ctx->conninfo = calloc(1, sizeof(struct tls_conninfo))) == NULL) { - tls_set_errorx(ctx, "out of memory"); + tls_set_errorx(ctx, TLS_ERROR_OUT_OF_MEMORY, "out of memory"); goto err; } diff --git a/lib/libtls/tls_internal.h b/lib/libtls/tls_internal.h index c06e8218f69..5ff48ed7c97 100644 --- a/lib/libtls/tls_internal.h +++ b/lib/libtls/tls_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_internal.h,v 1.84 2024/03/26 00:50:22 joshua Exp $ */ +/* $OpenBSD: tls_internal.h,v 1.85 2024/03/26 06:24:52 joshua Exp $ */ /* * Copyright (c) 2014 Jeremie Courreges-Anglas * Copyright (c) 2014 Joel Sing @@ -46,6 +46,7 @@ union tls_addr { struct tls_error { char *msg; + int code; int errno_value; int tls; }; @@ -258,27 +259,27 @@ int tls_set_cbs(struct tls *ctx, tls_read_cb read_cb, tls_write_cb write_cb, void *cb_arg); void tls_error_clear(struct tls_error *error); -int tls_error_set(struct tls_error *error, const char *fmt, ...) - __attribute__((__format__ (printf, 2, 3))) - __attribute__((__nonnull__ (2))); -int tls_error_setx(struct tls_error *error, const char *fmt, ...) - __attribute__((__format__ (printf, 2, 3))) - __attribute__((__nonnull__ (2))); -int tls_config_set_error(struct tls_config *cfg, const char *fmt, ...) - __attribute__((__format__ (printf, 2, 3))) - __attribute__((__nonnull__ (2))); -int tls_config_set_errorx(struct tls_config *cfg, const char *fmt, ...) - __attribute__((__format__ (printf, 2, 3))) - __attribute__((__nonnull__ (2))); -int tls_set_error(struct tls *ctx, const char *fmt, ...) - __attribute__((__format__ (printf, 2, 3))) - __attribute__((__nonnull__ (2))); -int tls_set_errorx(struct tls *ctx, const char *fmt, ...) - __attribute__((__format__ (printf, 2, 3))) - __attribute__((__nonnull__ (2))); -int tls_set_ssl_errorx(struct tls *ctx, const char *fmt, ...) - __attribute__((__format__ (printf, 2, 3))) - __attribute__((__nonnull__ (2))); +int tls_error_set(struct tls_error *error, int code, const char *fmt, ...) + __attribute__((__format__ (printf, 3, 4))) + __attribute__((__nonnull__ (3))); +int tls_error_setx(struct tls_error *error, int code, const char *fmt, ...) + __attribute__((__format__ (printf, 3, 4))) + __attribute__((__nonnull__ (3))); +int tls_config_set_error(struct tls_config *cfg, int code, const char *fmt, ...) + __attribute__((__format__ (printf, 3, 4))) + __attribute__((__nonnull__ (3))); +int tls_config_set_errorx(struct tls_config *cfg, int code, const char *fmt, ...) + __attribute__((__format__ (printf, 3, 4))) + __attribute__((__nonnull__ (3))); +int tls_set_error(struct tls *ctx, int code, const char *fmt, ...) + __attribute__((__format__ (printf, 3, 4))) + __attribute__((__nonnull__ (3))); +int tls_set_errorx(struct tls *ctx, int code, const char *fmt, ...) + __attribute__((__format__ (printf, 3, 4))) + __attribute__((__nonnull__ (3))); +int tls_set_ssl_errorx(struct tls *ctx, int code, const char *fmt, ...) + __attribute__((__format__ (printf, 3, 4))) + __attribute__((__nonnull__ (3))); int tls_ssl_error(struct tls *ctx, SSL *ssl_conn, int ssl_ret, const char *prefix); diff --git a/lib/libtls/tls_keypair.c b/lib/libtls/tls_keypair.c index a12d21d0da3..ffda91df8e7 100644 --- a/lib/libtls/tls_keypair.c +++ b/lib/libtls/tls_keypair.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_keypair.c,v 1.8 2021/01/05 17:37:12 jsing Exp $ */ +/* $OpenBSD: tls_keypair.c,v 1.9 2024/03/26 06:24:52 joshua Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -144,19 +144,22 @@ tls_keypair_load_cert(struct tls_keypair *keypair, struct tls_error *error, *cert = NULL; if (keypair->cert_mem == NULL) { - tls_error_set(error, "keypair has no certificate"); + tls_error_set(error, TLS_ERROR_UNKNOWN, + "keypair has no certificate"); goto err; } if ((cert_bio = BIO_new_mem_buf(keypair->cert_mem, keypair->cert_len)) == NULL) { - tls_error_set(error, "failed to create certificate bio"); + tls_error_set(error, TLS_ERROR_UNKNOWN, + "failed to create certificate bio"); goto err; } 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); - tls_error_set(error, "failed to load certificate: %s", errstr); + tls_error_set(error, TLS_ERROR_UNKNOWN, + "failed to load certificate: %s", errstr); goto err; } diff --git a/lib/libtls/tls_ocsp.c b/lib/libtls/tls_ocsp.c index f7d7ba91997..bfd06e3c6aa 100644 --- a/lib/libtls/tls_ocsp.c +++ b/lib/libtls/tls_ocsp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_ocsp.c,v 1.25 2024/03/24 11:30:12 beck Exp $ */ +/* $OpenBSD: tls_ocsp.c,v 1.26 2024/03/26 06:24:52 joshua Exp $ */ /* * Copyright (c) 2015 Marko Kreen * Copyright (c) 2016 Bob Beck @@ -85,7 +85,7 @@ tls_ocsp_fill_info(struct tls *ctx, int response_status, int cert_status, ctx->ocsp->ocsp_result = NULL; if ((info = calloc(1, sizeof (struct tls_ocsp_result))) == NULL) { - tls_set_error(ctx, "calloc"); + tls_set_error(ctx, TLS_ERROR_OUT_OF_MEMORY, "out of memory"); return -1; } info->response_status = response_status; @@ -102,19 +102,19 @@ tls_ocsp_fill_info(struct tls *ctx, int response_status, int cert_status, info->revocation_time = info->this_update = info->next_update = -1; if (revtime != NULL && tls_ocsp_asn1_parse_time(ctx, revtime, &info->revocation_time) != 0) { - tls_set_error(ctx, + tls_set_error(ctx, TLS_ERROR_UNKNOWN, "unable to parse revocation time in OCSP reply"); goto err; } if (thisupd != NULL && tls_ocsp_asn1_parse_time(ctx, thisupd, &info->this_update) != 0) { - tls_set_error(ctx, + tls_set_error(ctx, TLS_ERROR_UNKNOWN, "unable to parse this update time in OCSP reply"); goto err; } if (nextupd != NULL && tls_ocsp_asn1_parse_time(ctx, nextupd, &info->next_update) != 0) { - tls_set_error(ctx, + tls_set_error(ctx, TLS_ERROR_UNKNOWN, "unable to parse next update time in OCSP reply"); goto err; } @@ -180,19 +180,21 @@ tls_ocsp_setup_from_peer(struct tls *ctx) ocsp->main_cert = SSL_get_peer_certificate(ctx->ssl_conn); ocsp->extra_certs = SSL_get_peer_cert_chain(ctx->ssl_conn); if (ocsp->main_cert == NULL) { - tls_set_errorx(ctx, "no peer certificate for OCSP"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "no peer certificate for OCSP"); goto err; } ocsp_urls = X509_get1_ocsp(ocsp->main_cert); if (ocsp_urls == NULL) { - tls_set_errorx(ctx, "no OCSP URLs in peer certificate"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "no OCSP URLs in peer certificate"); goto err; } ocsp->ocsp_url = strdup(sk_OPENSSL_STRING_value(ocsp_urls, 0)); if (ocsp->ocsp_url == NULL) { - tls_set_errorx(ctx, "out of memory"); + tls_set_errorx(ctx, TLS_ERROR_OUT_OF_MEMORY, "out of memory"); goto err; } @@ -217,7 +219,7 @@ tls_ocsp_verify_response(struct tls *ctx, OCSP_RESPONSE *resp) unsigned long flags; if ((br = OCSP_response_get1_basic(resp)) == NULL) { - tls_set_errorx(ctx, "cannot load ocsp reply"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "cannot load ocsp reply"); goto err; } @@ -230,14 +232,15 @@ 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_errorx(ctx, "ocsp verify failed"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "ocsp verify failed"); goto err; } /* signature OK, look inside */ response_status = OCSP_response_status(resp); if (response_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { - tls_set_errorx(ctx, "ocsp verify failed: response - %s", + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "ocsp verify failed: response - %s", OCSP_response_status_str(response_status)); goto err; } @@ -245,19 +248,21 @@ tls_ocsp_verify_response(struct tls *ctx, OCSP_RESPONSE *resp) cid = tls_ocsp_get_certid(ctx->ocsp->main_cert, ctx->ocsp->extra_certs, ctx->ssl_ctx); if (cid == NULL) { - tls_set_errorx(ctx, "ocsp verify failed: no issuer cert"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "ocsp verify failed: no issuer cert"); goto err; } if (OCSP_resp_find_status(br, cid, &cert_status, &crl_reason, &revtime, &thisupd, &nextupd) != 1) { - tls_set_errorx(ctx, "ocsp verify failed: no result for cert"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "ocsp verify failed: no result for cert"); goto err; } if (OCSP_check_validity(thisupd, nextupd, JITTER_SEC, MAXAGE_SEC) != 1) { - tls_set_errorx(ctx, + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "ocsp verify failed: ocsp response not current"); goto err; } @@ -269,8 +274,9 @@ tls_ocsp_verify_response(struct tls *ctx, OCSP_RESPONSE *resp) /* finally can look at status */ if (cert_status != V_OCSP_CERTSTATUS_GOOD && cert_status != V_OCSP_CERTSTATUS_UNKNOWN) { - tls_set_errorx(ctx, "ocsp verify failed: revoked cert - %s", - OCSP_crl_reason_str(crl_reason)); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "ocsp verify failed: revoked cert - %s", + OCSP_crl_reason_str(crl_reason)); goto err; } ret = 0; @@ -298,7 +304,8 @@ tls_ocsp_process_response_internal(struct tls *ctx, const unsigned char *respons if (resp == NULL) { tls_ocsp_free(ctx->ocsp); ctx->ocsp = NULL; - tls_set_error(ctx, "unable to parse OCSP response"); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, + "unable to parse OCSP response"); return -1; } ret = tls_ocsp_verify_response(ctx, resp); @@ -320,7 +327,8 @@ tls_ocsp_verify_cb(SSL *ssl, void *arg) size = SSL_get_tlsext_status_ocsp_resp(ssl, &raw); if (size <= 0) { if (ctx->config->ocsp_require_stapling) { - tls_set_errorx(ctx, "no stapled OCSP response provided"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "no stapled OCSP response provided"); return 0; } return 1; diff --git a/lib/libtls/tls_server.c b/lib/libtls/tls_server.c index 5f93c7a0356..a42985744b7 100644 --- a/lib/libtls/tls_server.c +++ b/lib/libtls/tls_server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_server.c,v 1.49 2023/05/14 07:26:25 op Exp $ */ +/* $OpenBSD: tls_server.c,v 1.50 2024/03/26 06:24:52 joshua Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -181,7 +181,8 @@ tls_server_ticket_cb(SSL *ssl, unsigned char *keyname, unsigned char *iv, /* create new session */ key = tls_server_ticket_key(tls_ctx->config, NULL); if (key == NULL) { - tls_set_errorx(tls_ctx, "no valid ticket key found"); + tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN, + "no valid ticket key found"); return (-1); } @@ -189,12 +190,14 @@ tls_server_ticket_cb(SSL *ssl, unsigned char *keyname, unsigned char *iv, arc4random_buf(iv, EVP_MAX_IV_LENGTH); if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key->aes_key, iv)) { - tls_set_errorx(tls_ctx, "failed to init encrypt"); + tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN, + "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"); + tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN, + "failed to init hmac"); return (-1); } return (0); @@ -206,12 +209,14 @@ tls_server_ticket_cb(SSL *ssl, unsigned char *keyname, unsigned char *iv, if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key->aes_key, iv)) { - tls_set_errorx(tls_ctx, "failed to init decrypt"); + tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN, + "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"); + tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN, + "failed to init hmac"); return (-1); } @@ -229,7 +234,7 @@ tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, SSL_CTX_free(*ssl_ctx); if ((*ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) { - tls_set_errorx(ctx, "ssl context failure"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "ssl context failure"); goto err; } @@ -237,11 +242,13 @@ tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, if (SSL_CTX_set_tlsext_servername_callback(*ssl_ctx, tls_servername_cb) != 1) { - tls_set_error(ctx, "failed to set servername callback"); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, + "failed to set servername callback"); goto err; } if (SSL_CTX_set_tlsext_servername_arg(*ssl_ctx, ctx) != 1) { - tls_set_error(ctx, "failed to set servername callback arg"); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, + "failed to set servername callback arg"); goto err; } @@ -270,7 +277,8 @@ tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, SSL_CTX_set_ecdh_auto(*ssl_ctx, 1); if (SSL_CTX_set1_groups(*ssl_ctx, ctx->config->ecdhecurves, ctx->config->ecdhecurves_len) != 1) { - tls_set_errorx(ctx, "failed to set ecdhe curves"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to set ecdhe curves"); goto err; } } @@ -279,7 +287,8 @@ tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, SSL_CTX_set_options(*ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); if (SSL_CTX_set_tlsext_status_cb(*ssl_ctx, tls_ocsp_stapling_cb) != 1) { - tls_set_errorx(ctx, "failed to add OCSP stapling callback"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "failed to add OCSP stapling callback"); goto err; } @@ -289,7 +298,7 @@ tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, SSL_CTX_clear_options(*ssl_ctx, SSL_OP_NO_TICKET); if (!SSL_CTX_set_tlsext_ticket_key_cb(*ssl_ctx, tls_server_ticket_cb)) { - tls_set_error(ctx, + tls_set_error(ctx, TLS_ERROR_UNKNOWN, "failed to set the TLS ticket callback"); goto err; } @@ -297,7 +306,8 @@ tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, if (SSL_CTX_set_session_id_context(*ssl_ctx, ctx->config->session_id, sizeof(ctx->config->session_id)) != 1) { - tls_set_error(ctx, "failed to set session id context"); + tls_set_error(ctx, TLS_ERROR_UNKNOWN, + "failed to set session id context"); goto err; } @@ -323,7 +333,7 @@ tls_configure_server_sni(struct tls *ctx) sni_ctx = &ctx->sni_ctx; for (kp = ctx->config->keypair->next; kp != NULL; kp = kp->next) { if ((*sni_ctx = tls_sni_ctx_new()) == NULL) { - tls_set_errorx(ctx, "out of memory"); + tls_set_errorx(ctx, TLS_ERROR_OUT_OF_MEMORY, "out of memory"); goto err; } (*sni_ctx)->keypair = kp; @@ -362,22 +372,24 @@ tls_accept_common(struct tls *ctx) struct tls *conn_ctx = NULL; if ((ctx->flags & TLS_SERVER) == 0) { - tls_set_errorx(ctx, "not a server context"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "not a server context"); goto err; } if ((conn_ctx = tls_server_conn(ctx)) == NULL) { - tls_set_errorx(ctx, "connection context failure"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "connection context failure"); goto err; } if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { - tls_set_errorx(ctx, "ssl failure"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "ssl failure"); goto err; } if (SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx) != 1) { - tls_set_errorx(ctx, "ssl application data failure"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "ssl application data failure"); goto err; } @@ -405,7 +417,8 @@ tls_accept_fds(struct tls *ctx, struct tls **cctx, int fd_read, int fd_write) if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 || SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) { - tls_set_errorx(ctx, "ssl file descriptor failure"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "ssl file descriptor failure"); goto err; } @@ -448,7 +461,8 @@ tls_handshake_server(struct tls *ctx) int rv = -1; if ((ctx->flags & TLS_SERVER_CONN) == 0) { - tls_set_errorx(ctx, "not a server connection context"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "not a server connection context"); goto err; } diff --git a/lib/libtls/tls_signer.c b/lib/libtls/tls_signer.c index 177c9d07a4e..5eb37074544 100644 --- a/lib/libtls/tls_signer.c +++ b/lib/libtls/tls_signer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_signer.c,v 1.9 2023/06/18 19:12:58 tb Exp $ */ +/* $OpenBSD: tls_signer.c,v 1.10 2024/03/26 06:24:52 joshua Exp $ */ /* * Copyright (c) 2021 Eric Faurot * @@ -91,7 +91,7 @@ tls_signer_add_keypair_mem(struct tls_signer *signer, const uint8_t *cert, /* Compute certificate hash */ if ((bio = BIO_new_mem_buf(cert, cert_len)) == NULL) { - tls_error_setx(&signer->error, + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, "failed to create certificate bio"); goto err; } @@ -99,12 +99,12 @@ tls_signer_add_keypair_mem(struct tls_signer *signer, const uint8_t *cert, 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); + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, + "failed to load certificate: %s", errstr); goto err; } if (tls_cert_pubkey_hash(x509, &hash) == -1) { - tls_error_setx(&signer->error, + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, "failed to get certificate hash"); goto err; } @@ -116,23 +116,27 @@ tls_signer_add_keypair_mem(struct tls_signer *signer, const uint8_t *cert, /* Read private key */ if ((bio = BIO_new_mem_buf(key, key_len)) == NULL) { - tls_error_setx(&signer->error, "failed to create key bio"); + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, + "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"); + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, + "failed to read private key"); goto err; } if ((skey = calloc(1, sizeof(*skey))) == NULL) { - tls_error_set(&signer->error, "failed to create key entry"); + tls_error_set(&signer->error, TLS_ERROR_UNKNOWN, + "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"); + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, + "unknown key type"); goto err; } @@ -194,29 +198,31 @@ tls_sign_rsa(struct tls_signer *signer, struct tls_signer_key *skey, } 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); + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, + "invalid RSA padding type (%d)", padding_type); return (-1); } if (input_len > INT_MAX) { - tls_error_setx(&signer->error, "input too large"); + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, + "input too large"); return (-1); } if ((rsa_size = RSA_size(skey->rsa)) <= 0) { - tls_error_setx(&signer->error, "invalid RSA size: %d", - rsa_size); + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, + "invalid RSA size: %d", rsa_size); return (-1); } if ((signature = calloc(1, rsa_size)) == NULL) { - tls_error_set(&signer->error, "RSA signature"); + tls_error_set(&signer->error, TLS_ERROR_UNKNOWN, "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"); + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, + "RSA signing failed"); free(signature); return (-1); } @@ -239,28 +245,32 @@ tls_sign_ecdsa(struct tls_signer *signer, struct tls_signer_key *skey, *out_signature_len = 0; if (padding_type != TLS_PADDING_NONE) { - tls_error_setx(&signer->error, "invalid ECDSA padding"); + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, + "invalid ECDSA padding"); return (-1); } if (input_len > INT_MAX) { - tls_error_setx(&signer->error, "digest too large"); + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, + "digest too large"); return (-1); } if ((signature_len = ECDSA_size(skey->ecdsa)) <= 0) { - tls_error_setx(&signer->error, "invalid ECDSA size: %d", - signature_len); + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, + "invalid ECDSA size: %d", signature_len); return (-1); } if ((signature = calloc(1, signature_len)) == NULL) { - tls_error_set(&signer->error, "ECDSA signature"); + tls_error_set(&signer->error, TLS_ERROR_UNKNOWN, + "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"); + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, + "ECDSA signing failed"); free(signature); return (-1); } @@ -286,7 +296,7 @@ tls_signer_sign(struct tls_signer *signer, const char *pubkey_hash, break; if (skey == NULL) { - tls_error_setx(&signer->error, "key not found"); + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, "key not found"); return (-1); } @@ -298,7 +308,7 @@ tls_signer_sign(struct tls_signer *signer, const char *pubkey_hash, return tls_sign_ecdsa(signer, skey, input, input_len, padding_type, out_signature, out_signature_len); - tls_error_setx(&signer->error, "unknown key type"); + tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, "unknown key type"); return (-1); } diff --git a/lib/libtls/tls_verify.c b/lib/libtls/tls_verify.c index a35ebe02526..78f6c249cc0 100644 --- a/lib/libtls/tls_verify.c +++ b/lib/libtls/tls_verify.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_verify.c,v 1.29 2023/11/22 18:23:09 op Exp $ */ +/* $OpenBSD: tls_verify.c,v 1.30 2024/03/26 06:24:52 joshua Exp $ */ /* * Copyright (c) 2014 Jeremie Courreges-Anglas * @@ -102,7 +102,8 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, NULL); if (altname_stack == NULL) { if (critical != -1) { - tls_set_errorx(ctx, "error decoding subjectAltName"); + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "error decoding subjectAltName"); goto err; } goto done; @@ -141,7 +142,7 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, len = ASN1_STRING_length(altname->d.dNSName); if (len < 0 || (size_t)len != strlen(data)) { - tls_set_errorx(ctx, + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "error verifying name '%s': " "NUL byte in subjectAltName, " "probably a malicious certificate", @@ -155,7 +156,7 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, * dNSName must be rejected. */ if (strcmp(data, " ") == 0) { - tls_set_errorx(ctx, + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "error verifying name '%s': " "a dNSName of \" \" must not be " "used", name); @@ -182,7 +183,7 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, data = ASN1_STRING_get0_data(altname->d.iPAddress); if (datalen < 0) { - tls_set_errorx(ctx, + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "Unexpected negative length for an " "IP address: %d", datalen); goto err; @@ -243,7 +244,8 @@ tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, * more than one CN fed to us in the subject, treating the * certificate as hostile. */ - tls_set_errorx(ctx, "error verifying name '%s': " + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "error verifying name '%s': " "Certificate subject contains multiple Common Name fields, " "probably a malicious or malformed certificate", name); goto err; @@ -255,7 +257,8 @@ tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, * 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': " + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "error verifying name '%s': " "Common Name field cannot be encoded as a UTF-8 string, " "probably a malicious certificate", name); goto err; @@ -265,7 +268,8 @@ tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, * 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': " + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "error verifying name '%s': " "Common Name field has invalid length, " "probably a malicious certificate", name); goto err; @@ -274,7 +278,8 @@ tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, * 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': " + tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, + "error verifying name '%s': " "NUL byte in Common Name field, " "probably a malicious certificate", name); goto err; @@ -282,7 +287,8 @@ tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, common_name = strndup(utf8_bytes, common_name_len); if (common_name == NULL) { - tls_set_error(ctx, "out of memory"); + tls_set_error(ctx, TLS_ERROR_OUT_OF_MEMORY, + "out of memory"); goto err; }