1 /* $OpenBSD: tls_conninfo.c,v 1.23 2023/05/14 07:26:25 op Exp $ */ 2 /* 3 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> 4 * Copyright (c) 2015 Bob Beck <beck@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <stdio.h> 20 #include <string.h> 21 22 #include <openssl/x509.h> 23 24 #include <tls.h> 25 #include "tls_internal.h" 26 27 int ASN1_time_tm_clamp_notafter(struct tm *tm); 28 29 int 30 tls_hex_string(const unsigned char *in, size_t inlen, char **out, 31 size_t *outlen) 32 { 33 static const char hex[] = "0123456789abcdef"; 34 size_t i, len; 35 char *p; 36 37 if (outlen != NULL) 38 *outlen = 0; 39 40 if (inlen >= SIZE_MAX) 41 return (-1); 42 if ((*out = reallocarray(NULL, inlen + 1, 2)) == NULL) 43 return (-1); 44 45 p = *out; 46 len = 0; 47 for (i = 0; i < inlen; i++) { 48 p[len++] = hex[(in[i] >> 4) & 0x0f]; 49 p[len++] = hex[in[i] & 0x0f]; 50 } 51 p[len++] = 0; 52 53 if (outlen != NULL) 54 *outlen = len; 55 56 return (0); 57 } 58 59 static int 60 tls_get_peer_cert_hash(struct tls *ctx, char **hash) 61 { 62 *hash = NULL; 63 if (ctx->ssl_peer_cert == NULL) 64 return (0); 65 66 if (tls_cert_hash(ctx->ssl_peer_cert, hash) == -1) { 67 tls_set_errorx(ctx, "unable to compute peer certificate hash - out of memory"); 68 *hash = NULL; 69 return -1; 70 } 71 return 0; 72 } 73 74 static int 75 tls_get_peer_cert_issuer(struct tls *ctx, char **issuer) 76 { 77 X509_NAME *name = NULL; 78 79 *issuer = NULL; 80 if (ctx->ssl_peer_cert == NULL) 81 return (-1); 82 if ((name = X509_get_issuer_name(ctx->ssl_peer_cert)) == NULL) 83 return (-1); 84 *issuer = X509_NAME_oneline(name, 0, 0); 85 if (*issuer == NULL) 86 return (-1); 87 return (0); 88 } 89 90 static int 91 tls_get_peer_cert_subject(struct tls *ctx, char **subject) 92 { 93 X509_NAME *name = NULL; 94 95 *subject = NULL; 96 if (ctx->ssl_peer_cert == NULL) 97 return (-1); 98 if ((name = X509_get_subject_name(ctx->ssl_peer_cert)) == NULL) 99 return (-1); 100 *subject = X509_NAME_oneline(name, 0, 0); 101 if (*subject == NULL) 102 return (-1); 103 return (0); 104 } 105 106 static int 107 tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore, 108 time_t *notafter) 109 { 110 struct tm before_tm, after_tm; 111 ASN1_TIME *before, *after; 112 113 if (ctx->ssl_peer_cert == NULL) 114 return (-1); 115 116 if ((before = X509_get_notBefore(ctx->ssl_peer_cert)) == NULL) 117 goto err; 118 if ((after = X509_get_notAfter(ctx->ssl_peer_cert)) == NULL) 119 goto err; 120 if (ASN1_time_parse(before->data, before->length, &before_tm, 0) == -1) 121 goto err; 122 if (ASN1_time_parse(after->data, after->length, &after_tm, 0) == -1) 123 goto err; 124 if (!ASN1_time_tm_clamp_notafter(&after_tm)) 125 goto err; 126 if ((*notbefore = timegm(&before_tm)) == -1) 127 goto err; 128 if ((*notafter = timegm(&after_tm)) == -1) 129 goto err; 130 131 return (0); 132 133 err: 134 return (-1); 135 } 136 137 static int 138 tls_get_peer_cert_info(struct tls *ctx) 139 { 140 if (ctx->ssl_peer_cert == NULL) 141 return (0); 142 143 if (tls_get_peer_cert_hash(ctx, &ctx->conninfo->hash) == -1) 144 goto err; 145 if (tls_get_peer_cert_subject(ctx, &ctx->conninfo->subject) == -1) 146 goto err; 147 if (tls_get_peer_cert_issuer(ctx, &ctx->conninfo->issuer) == -1) 148 goto err; 149 if (tls_get_peer_cert_times(ctx, &ctx->conninfo->notbefore, 150 &ctx->conninfo->notafter) == -1) 151 goto err; 152 153 return (0); 154 155 err: 156 return (-1); 157 } 158 159 static int 160 tls_conninfo_alpn_proto(struct tls *ctx) 161 { 162 const unsigned char *p; 163 unsigned int len; 164 165 free(ctx->conninfo->alpn); 166 ctx->conninfo->alpn = NULL; 167 168 SSL_get0_alpn_selected(ctx->ssl_conn, &p, &len); 169 if (len > 0) { 170 if ((ctx->conninfo->alpn = malloc(len + 1)) == NULL) 171 return (-1); 172 memcpy(ctx->conninfo->alpn, p, len); 173 ctx->conninfo->alpn[len] = '\0'; 174 } 175 176 return (0); 177 } 178 179 static int 180 tls_conninfo_cert_pem(struct tls *ctx) 181 { 182 int i, rv = -1; 183 BIO *membio = NULL; 184 BUF_MEM *bptr = NULL; 185 186 if (ctx->ssl_peer_cert == NULL) 187 return 0; 188 if ((membio = BIO_new(BIO_s_mem()))== NULL) 189 goto err; 190 191 /* 192 * We have to write the peer cert out separately, because 193 * the certificate chain may or may not contain it. 194 */ 195 if (!PEM_write_bio_X509(membio, ctx->ssl_peer_cert)) 196 goto err; 197 for (i = 0; i < sk_X509_num(ctx->ssl_peer_chain); i++) { 198 X509 *chaincert = sk_X509_value(ctx->ssl_peer_chain, i); 199 if (chaincert != ctx->ssl_peer_cert && 200 !PEM_write_bio_X509(membio, chaincert)) 201 goto err; 202 } 203 204 BIO_get_mem_ptr(membio, &bptr); 205 free(ctx->conninfo->peer_cert); 206 ctx->conninfo->peer_cert_len = 0; 207 if ((ctx->conninfo->peer_cert = malloc(bptr->length)) == NULL) 208 goto err; 209 ctx->conninfo->peer_cert_len = bptr->length; 210 memcpy(ctx->conninfo->peer_cert, bptr->data, 211 ctx->conninfo->peer_cert_len); 212 213 /* BIO_free() will kill BUF_MEM - because we have not set BIO_NOCLOSE */ 214 rv = 0; 215 err: 216 BIO_free(membio); 217 return rv; 218 } 219 220 static int 221 tls_conninfo_session(struct tls *ctx) 222 { 223 ctx->conninfo->session_resumed = SSL_session_reused(ctx->ssl_conn); 224 225 return 0; 226 } 227 228 int 229 tls_conninfo_populate(struct tls *ctx) 230 { 231 const char *tmp; 232 233 tls_conninfo_free(ctx->conninfo); 234 235 if ((ctx->conninfo = calloc(1, sizeof(struct tls_conninfo))) == NULL) { 236 tls_set_errorx(ctx, "out of memory"); 237 goto err; 238 } 239 240 if (tls_conninfo_alpn_proto(ctx) == -1) 241 goto err; 242 243 if ((tmp = SSL_get_cipher(ctx->ssl_conn)) == NULL) 244 goto err; 245 if ((ctx->conninfo->cipher = strdup(tmp)) == NULL) 246 goto err; 247 ctx->conninfo->cipher_strength = SSL_get_cipher_bits(ctx->ssl_conn, NULL); 248 249 if (ctx->servername != NULL) { 250 if ((ctx->conninfo->servername = 251 strdup(ctx->servername)) == NULL) 252 goto err; 253 } 254 255 if ((tmp = SSL_get_version(ctx->ssl_conn)) == NULL) 256 goto err; 257 if ((ctx->conninfo->version = strdup(tmp)) == NULL) 258 goto err; 259 260 if (tls_get_peer_cert_info(ctx) == -1) 261 goto err; 262 263 if (tls_conninfo_cert_pem(ctx) == -1) 264 goto err; 265 266 if (tls_conninfo_session(ctx) == -1) 267 goto err; 268 269 return (0); 270 271 err: 272 tls_conninfo_free(ctx->conninfo); 273 ctx->conninfo = NULL; 274 275 return (-1); 276 } 277 278 void 279 tls_conninfo_free(struct tls_conninfo *conninfo) 280 { 281 if (conninfo == NULL) 282 return; 283 284 free(conninfo->alpn); 285 free(conninfo->cipher); 286 free(conninfo->servername); 287 free(conninfo->version); 288 289 free(conninfo->hash); 290 free(conninfo->issuer); 291 free(conninfo->subject); 292 293 free(conninfo->peer_cert); 294 295 free(conninfo); 296 } 297 298 const char * 299 tls_conn_alpn_selected(struct tls *ctx) 300 { 301 if (ctx->conninfo == NULL) 302 return (NULL); 303 return (ctx->conninfo->alpn); 304 } 305 306 const char * 307 tls_conn_cipher(struct tls *ctx) 308 { 309 if (ctx->conninfo == NULL) 310 return (NULL); 311 return (ctx->conninfo->cipher); 312 } 313 314 int 315 tls_conn_cipher_strength(struct tls *ctx) 316 { 317 if (ctx->conninfo == NULL) 318 return (0); 319 return (ctx->conninfo->cipher_strength); 320 } 321 322 const char * 323 tls_conn_servername(struct tls *ctx) 324 { 325 if (ctx->conninfo == NULL) 326 return (NULL); 327 return (ctx->conninfo->servername); 328 } 329 330 int 331 tls_conn_session_resumed(struct tls *ctx) 332 { 333 if (ctx->conninfo == NULL) 334 return (0); 335 return (ctx->conninfo->session_resumed); 336 } 337 338 const char * 339 tls_conn_version(struct tls *ctx) 340 { 341 if (ctx->conninfo == NULL) 342 return (NULL); 343 return (ctx->conninfo->version); 344 } 345