Update libressl README.DRAGONFLY for v2.4.4
[dragonfly.git] / crypto / libressl / tls / tls_conninfo.c
1 /* $OpenBSD: tls_conninfo.c,v 1.4 2015/10/07 23:25:45 beck 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
21 #include <openssl/x509.h>
22
23 #include <tls.h>
24 #include "tls_internal.h"
25
26 static int
27 tls_hex_string(const unsigned char *in, size_t inlen, char **out,
28     size_t *outlen)
29 {
30         static const char hex[] = "0123456789abcdef";
31         size_t i, len;
32         char *p;
33
34         if (outlen != NULL)
35                 *outlen = 0;
36
37         if (inlen >= SIZE_MAX)
38                 return (-1);
39         if ((*out = reallocarray(NULL, inlen + 1, 2)) == NULL)
40                 return (-1);
41
42         p = *out;
43         len = 0;
44         for (i = 0; i < inlen; i++) {
45                 p[len++] = hex[(in[i] >> 4) & 0x0f];
46                 p[len++] = hex[in[i] & 0x0f];
47         }
48         p[len++] = 0;
49
50         if (outlen != NULL)
51                 *outlen = len;
52
53         return (0);
54 }
55
56 static int
57 tls_get_peer_cert_hash(struct tls *ctx, char **hash)
58 {
59         char d[EVP_MAX_MD_SIZE], *dhex = NULL;
60         int dlen, rv = -1;
61
62         *hash = NULL;
63         if (ctx->ssl_peer_cert == NULL)
64                 return (0);
65
66         if (X509_digest(ctx->ssl_peer_cert, EVP_sha256(), d, &dlen) != 1) {
67                 tls_set_errorx(ctx, "digest failed");
68                 goto err;
69         }
70
71         if (tls_hex_string(d, dlen, &dhex, NULL) != 0) {
72                 tls_set_errorx(ctx, "digest hex string failed");
73                 goto err;
74         }
75
76         if (asprintf(hash, "SHA256:%s", dhex) == -1) {
77                 tls_set_errorx(ctx, "out of memory");
78                 *hash = NULL;
79                 goto err;
80         }
81
82         rv = 0;
83
84 err:
85         free(dhex);
86
87         return (rv);
88 }
89
90 static int
91 tls_get_peer_cert_issuer(struct tls *ctx,  char **issuer)
92 {
93         X509_NAME *name = NULL;
94
95         *issuer = NULL;
96         if (ctx->ssl_peer_cert == NULL)
97                 return (-1);
98         if ((name = X509_get_issuer_name(ctx->ssl_peer_cert)) == NULL)
99                 return (-1);
100         *issuer = X509_NAME_oneline(name, 0, 0);
101         if (*issuer == NULL)
102                 return (-1);
103         return (0);
104 }
105
106 static int
107 tls_get_peer_cert_subject(struct tls *ctx, char **subject)
108 {
109         X509_NAME *name = NULL;
110
111         *subject = NULL;
112         if (ctx->ssl_peer_cert == NULL)
113                 return (-1);
114         if ((name = X509_get_subject_name(ctx->ssl_peer_cert)) == NULL)
115                 return (-1);
116         *subject = X509_NAME_oneline(name, 0, 0);
117         if (*subject == NULL)
118                 return (-1);
119         return (0);
120 }
121
122 static int
123 tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore, time_t *notafter)
124 {
125         struct tm before_tm, after_tm;
126         ASN1_TIME *before, *after;
127         int rv = -1;
128
129         memset(&before_tm, 0, sizeof(before_tm));
130         memset(&after_tm, 0, sizeof(after_tm));
131
132         if (ctx->ssl_peer_cert != NULL) {
133                 if ((before = X509_get_notBefore(ctx->ssl_peer_cert)) == NULL)
134                         goto err;
135                 if ((after = X509_get_notAfter(ctx->ssl_peer_cert)) == NULL)
136                         goto err;
137                 if (asn1_time_parse(before->data, before->length, &before_tm, 0)
138                     == -1)
139                         goto err;
140                 if (asn1_time_parse(after->data, after->length, &after_tm, 0)
141                     == -1)
142                         goto err;
143                 if ((*notbefore = timegm(&before_tm)) == -1)
144                         goto err;
145                 if ((*notafter = timegm(&after_tm)) == -1)
146                         goto err;
147         }
148         rv = 0;
149  err:
150         return (rv);
151 }
152
153 int
154 tls_get_conninfo(struct tls *ctx) {
155         const char * tmp;
156         if (ctx->ssl_peer_cert != NULL) {
157                 if (tls_get_peer_cert_hash(ctx, &ctx->conninfo->hash) == -1)
158                         goto err;
159                 if (tls_get_peer_cert_subject(ctx, &ctx->conninfo->subject)
160                     == -1)
161                         goto err;
162                 if (tls_get_peer_cert_issuer(ctx, &ctx->conninfo->issuer) == -1)
163                         goto err;
164                 if (tls_get_peer_cert_times(ctx, &ctx->conninfo->notbefore,
165                     &ctx->conninfo->notafter) == -1)
166                         goto err;
167         }
168         if ((tmp = SSL_get_version(ctx->ssl_conn)) == NULL)
169                 goto err;
170         ctx->conninfo->version = strdup(tmp);
171         if (ctx->conninfo->version == NULL)
172                 goto err;
173         if ((tmp = SSL_get_cipher(ctx->ssl_conn)) == NULL)
174                 goto err;
175         ctx->conninfo->cipher = strdup(tmp);
176         if (ctx->conninfo->cipher == NULL)
177                 goto err;
178         return (0);
179 err:
180         tls_free_conninfo(ctx->conninfo);
181         return (-1);
182 }
183
184 void
185 tls_free_conninfo(struct tls_conninfo *conninfo) {
186         if (conninfo != NULL) {
187                 free(conninfo->hash);
188                 conninfo->hash = NULL;
189                 free(conninfo->subject);
190                 conninfo->subject = NULL;
191                 free(conninfo->issuer);
192                 conninfo->issuer = NULL;
193                 free(conninfo->version);
194                 conninfo->version = NULL;
195                 free(conninfo->cipher);
196                 conninfo->cipher = NULL;
197         }
198 }
199
200 const char *
201 tls_conn_cipher(struct tls *ctx)
202 {
203         if (ctx->conninfo == NULL)
204                 return (NULL);
205         return (ctx->conninfo->cipher);
206 }
207
208 const char *
209 tls_conn_version(struct tls *ctx)
210 {
211         if (ctx->conninfo == NULL)
212                 return (NULL);
213         return (ctx->conninfo->version);
214 }