1*26433cb1Stb /* $OpenBSD: tls_conninfo.c,v 1.28 2024/12/10 08:40:30 tb Exp $ */ 2ab8f2ec6Sbeck /* 3ab8f2ec6Sbeck * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> 4ab8f2ec6Sbeck * Copyright (c) 2015 Bob Beck <beck@openbsd.org> 5ab8f2ec6Sbeck * 6ab8f2ec6Sbeck * Permission to use, copy, modify, and distribute this software for any 7ab8f2ec6Sbeck * purpose with or without fee is hereby granted, provided that the above 8ab8f2ec6Sbeck * copyright notice and this permission notice appear in all copies. 9ab8f2ec6Sbeck * 10ab8f2ec6Sbeck * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11ab8f2ec6Sbeck * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12ab8f2ec6Sbeck * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13ab8f2ec6Sbeck * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14ab8f2ec6Sbeck * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15ab8f2ec6Sbeck * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16ab8f2ec6Sbeck * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17ab8f2ec6Sbeck */ 18ab8f2ec6Sbeck 19ab8f2ec6Sbeck #include <stdio.h> 20e6d77be9Sop #include <string.h> 21ab8f2ec6Sbeck 22ac059987Sbeck #include <openssl/posix_time.h> 23ab8f2ec6Sbeck #include <openssl/x509.h> 24ab8f2ec6Sbeck 25ab8f2ec6Sbeck #include <tls.h> 26ab8f2ec6Sbeck #include "tls_internal.h" 27ab8f2ec6Sbeck 28ac059987Sbeck static int 29ac059987Sbeck tls_convert_notafter(struct tm *tm, time_t *out_time) 30ac059987Sbeck { 31ac059987Sbeck int64_t posix_time; 32ac059987Sbeck 33ac059987Sbeck /* OPENSSL_timegm() fails if tm is not representable in a time_t */ 34ac059987Sbeck if (OPENSSL_timegm(tm, out_time)) 35ac059987Sbeck return 1; 36ac059987Sbeck if (!OPENSSL_tm_to_posix(tm, &posix_time)) 37ac059987Sbeck return 0; 38ac059987Sbeck if (posix_time < INT32_MIN) 39ac059987Sbeck return 0; 40ac059987Sbeck *out_time = (posix_time > INT32_MAX) ? INT32_MAX : posix_time; 41ac059987Sbeck return 1; 42ac059987Sbeck } 439fdb873dSbeck 44c793ca29Sbeck int 45ab8f2ec6Sbeck tls_hex_string(const unsigned char *in, size_t inlen, char **out, 46ab8f2ec6Sbeck size_t *outlen) 47ab8f2ec6Sbeck { 48ab8f2ec6Sbeck static const char hex[] = "0123456789abcdef"; 49ab8f2ec6Sbeck size_t i, len; 50ab8f2ec6Sbeck char *p; 51ab8f2ec6Sbeck 52ab8f2ec6Sbeck if (outlen != NULL) 53ab8f2ec6Sbeck *outlen = 0; 54ab8f2ec6Sbeck 55ab8f2ec6Sbeck if (inlen >= SIZE_MAX) 56ab8f2ec6Sbeck return (-1); 57ab8f2ec6Sbeck if ((*out = reallocarray(NULL, inlen + 1, 2)) == NULL) 58ab8f2ec6Sbeck return (-1); 59ab8f2ec6Sbeck 60ab8f2ec6Sbeck p = *out; 61ab8f2ec6Sbeck len = 0; 62ab8f2ec6Sbeck for (i = 0; i < inlen; i++) { 63ab8f2ec6Sbeck p[len++] = hex[(in[i] >> 4) & 0x0f]; 64ab8f2ec6Sbeck p[len++] = hex[in[i] & 0x0f]; 65ab8f2ec6Sbeck } 66ab8f2ec6Sbeck p[len++] = 0; 67ab8f2ec6Sbeck 68ab8f2ec6Sbeck if (outlen != NULL) 69ab8f2ec6Sbeck *outlen = len; 70ab8f2ec6Sbeck 71ab8f2ec6Sbeck return (0); 72ab8f2ec6Sbeck } 73ab8f2ec6Sbeck 74ab8f2ec6Sbeck static int 75ab8f2ec6Sbeck tls_get_peer_cert_hash(struct tls *ctx, char **hash) 76ab8f2ec6Sbeck { 77ab8f2ec6Sbeck *hash = NULL; 78ab8f2ec6Sbeck if (ctx->ssl_peer_cert == NULL) 79ab8f2ec6Sbeck return (0); 80ab8f2ec6Sbeck 81c793ca29Sbeck if (tls_cert_hash(ctx->ssl_peer_cert, hash) == -1) { 821450a961Sjsing tls_set_errorx(ctx, TLS_ERROR_OUT_OF_MEMORY, "out of memory"); 83ab8f2ec6Sbeck *hash = NULL; 84c793ca29Sbeck return -1; 85ab8f2ec6Sbeck } 86c793ca29Sbeck return 0; 87ab8f2ec6Sbeck } 88ab8f2ec6Sbeck 89ab8f2ec6Sbeck static int 90ab8f2ec6Sbeck tls_get_peer_cert_issuer(struct tls *ctx, char **issuer) 91ab8f2ec6Sbeck { 92ab8f2ec6Sbeck X509_NAME *name = NULL; 93ab8f2ec6Sbeck 94ab8f2ec6Sbeck *issuer = NULL; 95ab8f2ec6Sbeck if (ctx->ssl_peer_cert == NULL) 96ab8f2ec6Sbeck return (-1); 97ab8f2ec6Sbeck if ((name = X509_get_issuer_name(ctx->ssl_peer_cert)) == NULL) 98ab8f2ec6Sbeck return (-1); 99ab8f2ec6Sbeck *issuer = X509_NAME_oneline(name, 0, 0); 100ab8f2ec6Sbeck if (*issuer == NULL) 101ab8f2ec6Sbeck return (-1); 102ab8f2ec6Sbeck return (0); 103ab8f2ec6Sbeck } 104ab8f2ec6Sbeck 105ab8f2ec6Sbeck static int 106ab8f2ec6Sbeck tls_get_peer_cert_subject(struct tls *ctx, char **subject) 107ab8f2ec6Sbeck { 108ab8f2ec6Sbeck X509_NAME *name = NULL; 109ab8f2ec6Sbeck 110ab8f2ec6Sbeck *subject = NULL; 111ab8f2ec6Sbeck if (ctx->ssl_peer_cert == NULL) 112ab8f2ec6Sbeck return (-1); 113ab8f2ec6Sbeck if ((name = X509_get_subject_name(ctx->ssl_peer_cert)) == NULL) 114ab8f2ec6Sbeck return (-1); 115ab8f2ec6Sbeck *subject = X509_NAME_oneline(name, 0, 0); 116ab8f2ec6Sbeck if (*subject == NULL) 117ab8f2ec6Sbeck return (-1); 118ab8f2ec6Sbeck return (0); 119ab8f2ec6Sbeck } 120ab8f2ec6Sbeck 121f00a4e85Sbeck static int 122*26433cb1Stb tls_get_peer_cert_common_name(struct tls *ctx, char **common_name) 123*26433cb1Stb { 124*26433cb1Stb if (ctx->ssl_peer_cert == NULL) 125*26433cb1Stb return (-1); 126*26433cb1Stb return tls_get_common_name(ctx, ctx->ssl_peer_cert, NULL, common_name); 127*26433cb1Stb } 128*26433cb1Stb 129*26433cb1Stb static int 130dc559dc0Sjsing tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore, 131dc559dc0Sjsing time_t *notafter) 132f00a4e85Sbeck { 133f00a4e85Sbeck struct tm before_tm, after_tm; 134f00a4e85Sbeck ASN1_TIME *before, *after; 135dc559dc0Sjsing 136dc559dc0Sjsing if (ctx->ssl_peer_cert == NULL) 137dc559dc0Sjsing return (-1); 138f00a4e85Sbeck 139f00a4e85Sbeck if ((before = X509_get_notBefore(ctx->ssl_peer_cert)) == NULL) 140f00a4e85Sbeck goto err; 141f00a4e85Sbeck if ((after = X509_get_notAfter(ctx->ssl_peer_cert)) == NULL) 142f00a4e85Sbeck goto err; 143029ab7abStb if (!ASN1_TIME_to_tm(before, &before_tm)) 144f00a4e85Sbeck goto err; 145029ab7abStb if (!ASN1_TIME_to_tm(after, &after_tm)) 146f00a4e85Sbeck goto err; 147ac059987Sbeck if (!tls_convert_notafter(&after_tm, notafter)) 1489fdb873dSbeck goto err; 149ac059987Sbeck if (!OPENSSL_timegm(&before_tm, notbefore)) 150f00a4e85Sbeck goto err; 151dc559dc0Sjsing return (0); 152dc559dc0Sjsing 153f00a4e85Sbeck err: 154dc559dc0Sjsing return (-1); 155dc559dc0Sjsing } 156dc559dc0Sjsing 157dc559dc0Sjsing static int 158dc559dc0Sjsing tls_get_peer_cert_info(struct tls *ctx) 159dc559dc0Sjsing { 160dc559dc0Sjsing if (ctx->ssl_peer_cert == NULL) 161dc559dc0Sjsing return (0); 162dc559dc0Sjsing 163dc559dc0Sjsing if (tls_get_peer_cert_hash(ctx, &ctx->conninfo->hash) == -1) 164dc559dc0Sjsing goto err; 165dc559dc0Sjsing if (tls_get_peer_cert_subject(ctx, &ctx->conninfo->subject) == -1) 166dc559dc0Sjsing goto err; 167dc559dc0Sjsing if (tls_get_peer_cert_issuer(ctx, &ctx->conninfo->issuer) == -1) 168dc559dc0Sjsing goto err; 169*26433cb1Stb if (tls_get_peer_cert_common_name(ctx, 170*26433cb1Stb &ctx->conninfo->common_name) == -1) 171*26433cb1Stb goto err; 172dc559dc0Sjsing if (tls_get_peer_cert_times(ctx, &ctx->conninfo->notbefore, 173dc559dc0Sjsing &ctx->conninfo->notafter) == -1) 174dc559dc0Sjsing goto err; 175dc559dc0Sjsing 176dc559dc0Sjsing return (0); 177dc559dc0Sjsing 178dc559dc0Sjsing err: 179dc559dc0Sjsing return (-1); 180f00a4e85Sbeck } 181f00a4e85Sbeck 182183da8c6Sjsing static int 183183da8c6Sjsing tls_conninfo_alpn_proto(struct tls *ctx) 184183da8c6Sjsing { 185183da8c6Sjsing const unsigned char *p; 186183da8c6Sjsing unsigned int len; 187183da8c6Sjsing 188183da8c6Sjsing free(ctx->conninfo->alpn); 189183da8c6Sjsing ctx->conninfo->alpn = NULL; 190183da8c6Sjsing 191183da8c6Sjsing SSL_get0_alpn_selected(ctx->ssl_conn, &p, &len); 192183da8c6Sjsing if (len > 0) { 193183da8c6Sjsing if ((ctx->conninfo->alpn = malloc(len + 1)) == NULL) 194183da8c6Sjsing return (-1); 195183da8c6Sjsing memcpy(ctx->conninfo->alpn, p, len); 196183da8c6Sjsing ctx->conninfo->alpn[len] = '\0'; 197183da8c6Sjsing } 198183da8c6Sjsing 199183da8c6Sjsing return (0); 200183da8c6Sjsing } 201183da8c6Sjsing 202c67861f7Sbeck static int 203c67861f7Sbeck tls_conninfo_cert_pem(struct tls *ctx) 204c67861f7Sbeck { 205c67861f7Sbeck int i, rv = -1; 206c67861f7Sbeck BIO *membio = NULL; 207c67861f7Sbeck BUF_MEM *bptr = NULL; 208c67861f7Sbeck 209c67861f7Sbeck if (ctx->ssl_peer_cert == NULL) 210c67861f7Sbeck return 0; 211c67861f7Sbeck if ((membio = BIO_new(BIO_s_mem()))== NULL) 212c67861f7Sbeck goto err; 213c67861f7Sbeck 214c67861f7Sbeck /* 215c67861f7Sbeck * We have to write the peer cert out separately, because 216c67861f7Sbeck * the certificate chain may or may not contain it. 217c67861f7Sbeck */ 218c67861f7Sbeck if (!PEM_write_bio_X509(membio, ctx->ssl_peer_cert)) 219c67861f7Sbeck goto err; 220c67861f7Sbeck for (i = 0; i < sk_X509_num(ctx->ssl_peer_chain); i++) { 221c67861f7Sbeck X509 *chaincert = sk_X509_value(ctx->ssl_peer_chain, i); 222c67861f7Sbeck if (chaincert != ctx->ssl_peer_cert && 223c67861f7Sbeck !PEM_write_bio_X509(membio, chaincert)) 224c67861f7Sbeck goto err; 225c67861f7Sbeck } 226c67861f7Sbeck 227c67861f7Sbeck BIO_get_mem_ptr(membio, &bptr); 228c67861f7Sbeck free(ctx->conninfo->peer_cert); 229c67861f7Sbeck ctx->conninfo->peer_cert_len = 0; 230c67861f7Sbeck if ((ctx->conninfo->peer_cert = malloc(bptr->length)) == NULL) 231c67861f7Sbeck goto err; 232c67861f7Sbeck ctx->conninfo->peer_cert_len = bptr->length; 233c67861f7Sbeck memcpy(ctx->conninfo->peer_cert, bptr->data, 234c67861f7Sbeck ctx->conninfo->peer_cert_len); 235c67861f7Sbeck 236c67861f7Sbeck /* BIO_free() will kill BUF_MEM - because we have not set BIO_NOCLOSE */ 237c67861f7Sbeck rv = 0; 238c67861f7Sbeck err: 239c67861f7Sbeck BIO_free(membio); 240c67861f7Sbeck return rv; 241c67861f7Sbeck } 242c67861f7Sbeck 2430dd084b9Sjsing static int 2440dd084b9Sjsing tls_conninfo_session(struct tls *ctx) 2450dd084b9Sjsing { 2460dd084b9Sjsing ctx->conninfo->session_resumed = SSL_session_reused(ctx->ssl_conn); 2470dd084b9Sjsing 2480dd084b9Sjsing return 0; 2490dd084b9Sjsing } 2500dd084b9Sjsing 251ab8f2ec6Sbeck int 252dc559dc0Sjsing tls_conninfo_populate(struct tls *ctx) 25317727490Sjsing { 254cbeeb52cSbeck const char *tmp; 25517727490Sjsing 256dc559dc0Sjsing tls_conninfo_free(ctx->conninfo); 257dc559dc0Sjsing 258dc559dc0Sjsing if ((ctx->conninfo = calloc(1, sizeof(struct tls_conninfo))) == NULL) { 2597a756d37Sjoshua tls_set_errorx(ctx, TLS_ERROR_OUT_OF_MEMORY, "out of memory"); 260f00a4e85Sbeck goto err; 261cbeeb52cSbeck } 262dc559dc0Sjsing 263dc559dc0Sjsing if (tls_conninfo_alpn_proto(ctx) == -1) 264cbeeb52cSbeck goto err; 265dc559dc0Sjsing 266cbeeb52cSbeck if ((tmp = SSL_get_cipher(ctx->ssl_conn)) == NULL) 267cbeeb52cSbeck goto err; 268f385e3b3Sjsing if ((ctx->conninfo->cipher = strdup(tmp)) == NULL) 2692eb13fbaSbeck goto err; 270bbf181b7Sjsing ctx->conninfo->cipher_strength = SSL_get_cipher_bits(ctx->ssl_conn, NULL); 271dc559dc0Sjsing 27255272e79Sjsing if (ctx->servername != NULL) { 27355272e79Sjsing if ((ctx->conninfo->servername = 27455272e79Sjsing strdup(ctx->servername)) == NULL) 27555272e79Sjsing goto err; 27655272e79Sjsing } 277183da8c6Sjsing 278dc559dc0Sjsing if ((tmp = SSL_get_version(ctx->ssl_conn)) == NULL) 279dc559dc0Sjsing goto err; 280f385e3b3Sjsing if ((ctx->conninfo->version = strdup(tmp)) == NULL) 281dc559dc0Sjsing goto err; 282dc559dc0Sjsing 283dc559dc0Sjsing if (tls_get_peer_cert_info(ctx) == -1) 284dc559dc0Sjsing goto err; 285dc559dc0Sjsing 286c67861f7Sbeck if (tls_conninfo_cert_pem(ctx) == -1) 287c67861f7Sbeck goto err; 288c67861f7Sbeck 2890dd084b9Sjsing if (tls_conninfo_session(ctx) == -1) 2900dd084b9Sjsing goto err; 2910dd084b9Sjsing 292cbeeb52cSbeck return (0); 293dc559dc0Sjsing 294ab8f2ec6Sbeck err: 295dc559dc0Sjsing tls_conninfo_free(ctx->conninfo); 296dc559dc0Sjsing ctx->conninfo = NULL; 297dc559dc0Sjsing 298cbeeb52cSbeck return (-1); 299ab8f2ec6Sbeck } 300ab8f2ec6Sbeck 301ab8f2ec6Sbeck void 302dc559dc0Sjsing tls_conninfo_free(struct tls_conninfo *conninfo) 30317727490Sjsing { 304dc559dc0Sjsing if (conninfo == NULL) 305dc559dc0Sjsing return; 306dc559dc0Sjsing 307183da8c6Sjsing free(conninfo->alpn); 3082eb13fbaSbeck free(conninfo->cipher); 3091c402a93Sjsing free(conninfo->servername); 310dc559dc0Sjsing free(conninfo->version); 311dc559dc0Sjsing 312*26433cb1Stb free(conninfo->common_name); 313dc559dc0Sjsing free(conninfo->hash); 314dc559dc0Sjsing free(conninfo->issuer); 315dc559dc0Sjsing free(conninfo->subject); 316dc559dc0Sjsing 317c67861f7Sbeck free(conninfo->peer_cert); 318c67861f7Sbeck 319dc559dc0Sjsing free(conninfo); 320ab8f2ec6Sbeck } 3212eb13fbaSbeck 3222eb13fbaSbeck const char * 323183da8c6Sjsing tls_conn_alpn_selected(struct tls *ctx) 324183da8c6Sjsing { 325183da8c6Sjsing if (ctx->conninfo == NULL) 326183da8c6Sjsing return (NULL); 327183da8c6Sjsing return (ctx->conninfo->alpn); 328183da8c6Sjsing } 329183da8c6Sjsing 330183da8c6Sjsing const char * 3312eb13fbaSbeck tls_conn_cipher(struct tls *ctx) 3322eb13fbaSbeck { 3330112cb75Sjsing if (ctx->conninfo == NULL) 3340112cb75Sjsing return (NULL); 3352eb13fbaSbeck return (ctx->conninfo->cipher); 3362eb13fbaSbeck } 3372eb13fbaSbeck 338bbf181b7Sjsing int 339bbf181b7Sjsing tls_conn_cipher_strength(struct tls *ctx) 340bbf181b7Sjsing { 341bbf181b7Sjsing if (ctx->conninfo == NULL) 342bbf181b7Sjsing return (0); 343bbf181b7Sjsing return (ctx->conninfo->cipher_strength); 344bbf181b7Sjsing } 345bbf181b7Sjsing 3462eb13fbaSbeck const char * 34755272e79Sjsing tls_conn_servername(struct tls *ctx) 34855272e79Sjsing { 34955272e79Sjsing if (ctx->conninfo == NULL) 35055272e79Sjsing return (NULL); 35155272e79Sjsing return (ctx->conninfo->servername); 35255272e79Sjsing } 35355272e79Sjsing 3540dd084b9Sjsing int 3550dd084b9Sjsing tls_conn_session_resumed(struct tls *ctx) 3560dd084b9Sjsing { 3570dd084b9Sjsing if (ctx->conninfo == NULL) 3580dd084b9Sjsing return (0); 3590dd084b9Sjsing return (ctx->conninfo->session_resumed); 3600dd084b9Sjsing } 3610dd084b9Sjsing 36255272e79Sjsing const char * 3632eb13fbaSbeck tls_conn_version(struct tls *ctx) 3642eb13fbaSbeck { 3650112cb75Sjsing if (ctx->conninfo == NULL) 3660112cb75Sjsing return (NULL); 3672eb13fbaSbeck return (ctx->conninfo->version); 3682eb13fbaSbeck } 369