diff options
| author | June McEnroe <june@causal.agency> | 2026-06-01 14:42:49 -0400 |
|---|---|---|
| committer | June McEnroe <june@causal.agency> | 2026-06-01 14:42:49 -0400 |
| commit | d08958f5d2c4d71d8132ea5c6cb45e48b5c4d83d (patch) | |
| tree | 01f7eb5bc8d9d0e708ec077364a6b3fda7f1bdde /tls.c | |
| parent | Import LibreSSL 3.9.2 (diff) | |
| download | libretls-d08958f5d2c4d71d8132ea5c6cb45e48b5c4d83d.tar.gz libretls-d08958f5d2c4d71d8132ea5c6cb45e48b5c4d83d.zip | |
Import LibreSSL 4.0.0
Diffstat (limited to 'tls.c')
| -rw-r--r-- | tls.c | 176 |
1 files changed, 109 insertions, 67 deletions
diff --git a/tls.c b/tls.c index fdb994d..41bb06d 100644 --- a/tls.c +++ b/tls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls.c,v 1.98 2023/07/02 06:37:27 beck Exp $ */ +/* $OpenBSD: tls.c,v 1.104 2024/04/08 20:47:32 tb Exp $ */ /* * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> * @@ -72,24 +72,33 @@ 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->num = 0; + error->code = TLS_ERROR_UNKNOWN; + error->errno_value = 0; error->tls = 0; } static int -tls_error_vset(struct tls_error *error, int errnum, 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->num = errnum; + error->code = code; + error->errno_value = errno_value; error->tls = 1; if (vasprintf(&errmsg, fmt, ap) == -1) { @@ -97,12 +106,12 @@ tls_error_vset(struct tls_error *error, int errnum, const char *fmt, va_list ap) goto err; } - if (errnum == -1) { + if (errno_value == -1) { error->msg = errmsg; return (0); } - if (asprintf(&error->msg, "%s: %s", errmsg, strerror(errnum)) == -1) { + if (asprintf(&error->msg, "%s: %s", errmsg, strerror(errno_value)) == -1) { error->msg = NULL; goto err; } @@ -115,91 +124,91 @@ tls_error_vset(struct tls_error *error, int errnum, const char *fmt, va_list ap) } 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 errnum, rv; + int errno_value, rv; - errnum = errno; + errno_value = errno; va_start(ap, fmt); - rv = tls_error_vset(error, errnum, 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 errnum, rv; + int errno_value, rv; - errnum = errno; + errno_value = errno; va_start(ap, fmt); - rv = tls_error_vset(&config->error, errnum, 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 errnum, rv; + int errno_value, rv; - errnum = errno; + errno_value = errno; va_start(ap, fmt); - rv = tls_error_vset(&ctx->error, errnum, 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,30 +359,34 @@ 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 ? - "cert too long" : "key too long"); + tls_set_errorx(ctx, TLS_ERROR_INVALID_ARGUMENT, + ctx->config->use_fake_private_key ? + "certificate 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"); + 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_INVALID_ARGUMENT, + "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,37 @@ 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_INVALID_ARGUMENT, + "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_INVALID_ARGUMENT, + "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 +686,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; } } @@ -709,7 +743,7 @@ tls_reset(struct tls *ctx) free(ctx->error.msg); ctx->error.msg = NULL; - ctx->error.num = -1; + ctx->error.errno_value = -1; tls_conninfo_free(ctx->conninfo); ctx->conninfo = NULL; @@ -759,21 +793,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 +823,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_INVALID_CONTEXT, + "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 +867,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_INVALID_ARGUMENT, + "buflen too long"); goto out; } @@ -859,7 +899,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_INVALID_ARGUMENT, + "buflen too long"); goto out; } @@ -885,7 +926,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_INVALID_CONTEXT, + "invalid operation for context"); rv = -1; goto out; } @@ -906,13 +948,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 +962,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; } |