/*
- * Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2012-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
#ifndef OPENSSL_NO_SSL_TRACE
/* Packet trace support for OpenSSL */
+#include "internal/nelem.h"
typedef struct {
int num;
{TLSEXT_TYPE_application_layer_protocol_negotiation,
"application_layer_protocol_negotiation"},
{TLSEXT_TYPE_signed_certificate_timestamp, "signed_certificate_timestamps"},
+ {TLSEXT_TYPE_client_cert_type, "client_cert_type"},
+ {TLSEXT_TYPE_server_cert_type, "server_cert_type"},
{TLSEXT_TYPE_padding, "padding"},
{TLSEXT_TYPE_encrypt_then_mac, "encrypt_then_mac"},
{TLSEXT_TYPE_extended_master_secret, "extended_master_secret"},
{258, "ffdhe4096"},
{259, "ffdhe6144"},
{260, "ffdhe8192"},
+ {25497, "X25519Kyber768Draft00"},
+ {25498, "SecP256r1Kyber768Draft00"},
{0xFF01, "arbitrary_explicit_prime_curves"},
{0xFF02, "arbitrary_explicit_char2_curves"}
};
{TLSEXT_comp_cert_zstd, "zstd"}
};
+/*
+ * "pgp" and "1609dot2" are defined in RFC7250,
+ * although OpenSSL doesn't support them, it can
+ * at least report them in traces
+ */
+static const ssl_trace_tbl ssl_cert_type_tbl[] = {
+ {TLSEXT_cert_type_x509, "x509"},
+ {TLSEXT_cert_type_pgp, "pgp"},
+ {TLSEXT_cert_type_rpk, "rpk"},
+ {TLSEXT_cert_type_1609dot2, "1609dot2"}
+};
+
static void ssl_print_hex(BIO *bio, int indent, const char *name,
const unsigned char *msg, size_t msglen)
{
| ((unsigned int)ext[2] << 8)
| (unsigned int)ext[3];
BIO_indent(bio, indent + 2, 80);
- BIO_printf(bio, "max_early_data=%u\n", max_early_data);
+ BIO_printf(bio, "max_early_data=%u\n", (unsigned int)max_early_data);
break;
+ case TLSEXT_TYPE_server_cert_type:
+ case TLSEXT_TYPE_client_cert_type:
+ if (server) {
+ if (extlen != 1)
+ return 0;
+ return ssl_trace_list(bio, indent + 2, ext, 1, 1, ssl_cert_type_tbl);
+ }
+ if (extlen < 1)
+ return 0;
+ xlen = ext[0];
+ if (extlen != xlen + 1)
+ return 0;
+ return ssl_trace_list(bio, indent + 2, ext + 1, xlen, 1, ssl_cert_type_tbl);
+
default:
BIO_dump_indent(bio, (const char *)ext, extlen, indent + 2);
}
return !msglen;
}
-static int ssl_print_certificate(BIO *bio, int indent,
+static int ssl_print_certificate(BIO *bio, const SSL_CONNECTION *sc, int indent,
const unsigned char **pmsg, size_t *pmsglen)
{
size_t msglen = *pmsglen;
size_t clen;
X509 *x;
const unsigned char *p = *pmsg, *q;
+ SSL_CTX *ctx = SSL_CONNECTION_GET_CTX(sc);
if (msglen < 3)
return 0;
q = p + 3;
BIO_indent(bio, indent, 80);
BIO_printf(bio, "ASN.1Cert, length=%d", (int)clen);
- x = d2i_X509(NULL, &q, clen);
- if (!x)
+ x = X509_new_ex(ctx->libctx, ctx->propq);
+ if (x != NULL && d2i_X509(&x, &q, clen) == NULL) {
+ X509_free(x);
+ x = NULL;
+ }
+ if (x == NULL)
BIO_puts(bio, "<UNPARSEABLE CERTIFICATE>\n");
else {
BIO_puts(bio, "\n------details-----\n");
return 1;
}
+static int ssl_print_raw_public_key(BIO *bio, const SSL *ssl, int server,
+ int indent, const unsigned char **pmsg,
+ size_t *pmsglen)
+{
+ EVP_PKEY *pkey;
+ size_t clen;
+ const unsigned char *msg = *pmsg;
+ size_t msglen = *pmsglen;
+
+ if (msglen < 3)
+ return 0;
+ clen = (msg[0] << 16) | (msg[1] << 8) | msg[2];
+ if (msglen < clen + 3)
+ return 0;
+
+ msg += 3;
+
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "raw_public_key, length=%d\n", (int)clen);
+
+ pkey = d2i_PUBKEY_ex(NULL, &msg, clen, ssl->ctx->libctx, ssl->ctx->propq);
+ if (pkey == NULL)
+ return 0;
+ EVP_PKEY_print_public(bio, pkey, indent + 2, NULL);
+ EVP_PKEY_free(pkey);
+ *pmsg += clen + 3;
+ *pmsglen -= clen + 3;
+ return 1;
+}
+
static int ssl_print_certificates(BIO *bio, const SSL_CONNECTION *sc, int server,
int indent, const unsigned char *msg,
size_t msglen)
if (msglen != clen + 3)
return 0;
msg += 3;
+ if ((server && sc->ext.server_cert_type == TLSEXT_cert_type_rpk)
+ || (!server && sc->ext.client_cert_type == TLSEXT_cert_type_rpk)) {
+ if (!ssl_print_raw_public_key(bio, &sc->ssl, server, indent, &msg, &clen))
+ return 0;
+ if (SSL_CONNECTION_IS_TLS13(sc)
+ && !ssl_print_extensions(bio, indent + 2, server,
+ SSL3_MT_CERTIFICATE, &msg, &clen))
+ return 0;
+ return 1;
+ }
BIO_indent(bio, indent, 80);
BIO_printf(bio, "certificate_list, length=%d\n", (int)clen);
while (clen > 0) {
- if (!ssl_print_certificate(bio, indent + 2, &msg, &clen))
+ if (!ssl_print_certificate(bio, sc, indent + 2, &msg, &clen))
return 0;
if (SSL_CONNECTION_IS_TLS13(sc)
&& !ssl_print_extensions(bio, indent + 2, server,
BIO_indent(bio, indent, 80);
BIO_printf(bio, "Uncompressed length=%d\n", (int)uclen);
BIO_indent(bio, indent, 80);
- BIO_printf(bio, "Compressed length=%d, Ratio=%f:1\n", (int)clen, (float)uclen / (float)clen);
+ if (clen > 0)
+ BIO_printf(bio, "Compressed length=%d, Ratio=%f:1\n", (int)clen, (float)uclen / (float)clen);
+ else
+ BIO_printf(bio, "Compressed length=%d, Ratio=unknown\n", (int)clen);
BIO_dump_indent(bio, (const char *)msg, clen, indent);
if (!ossl_comp_has_alg(alg))
return 0;
- if ((ucdata = OPENSSL_malloc(uclen)) == NULL)
+ /* Check against certificate maximum size (coverity) */
+ if (uclen == 0 || uclen > 0xFFFFFF || (ucdata = OPENSSL_malloc(uclen)) == NULL)
return 0;
switch (alg) {
const unsigned char *msg = buf;
BIO *bio = arg;
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
+#ifndef OPENSSL_NO_QUIC
+ QUIC_CONNECTION *qc = QUIC_CONNECTION_FROM_SSL(ssl);
+
+ if (qc != NULL) {
+ if (ossl_quic_trace(write_p, version, content_type, buf, msglen, ssl,
+ arg))
+ return;
+ /*
+ * Otherwise ossl_quic_trace didn't handle this content_type so we
+ * fallback to standard TLS handling
+ */
+ }
+#endif
if (sc == NULL)
return;
}
hvers = msg[1] << 8 | msg[2];
BIO_puts(bio, write_p ? "Sent" : "Received");
- BIO_printf(bio, " Record\nHeader:\n Version = %s (0x%x)\n",
+ BIO_printf(bio, " TLS Record\nHeader:\n Version = %s (0x%x)\n",
ssl_trace_str(hvers, ssl_version_tbl), hvers);
if (SSL_CONNECTION_IS_DTLS(sc)) {
BIO_printf(bio,