Merge branch 'vendor/BINUTILS225'
[dragonfly.git] / crypto / libressl / tls / tls_util.c
1 /* $OpenBSD: tls_util.c,v 1.2 2015/02/07 23:25:37 reyk Exp $ */
2 /*
3  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4  * Copyright (c) 2015 Reyk Floeter <reyk@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 <sys/stat.h>
20
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24
25 #include "tls.h"
26 #include "tls_internal.h"
27
28 /*
29  * Extract the host and port from a colon separated value. For a literal IPv6
30  * address the address must be contained with square braces. If a host and
31  * port are successfully extracted, the function will return 0 and the
32  * caller is responsible for freeing the host and port. If no port is found
33  * then the function will return 1, with both host and port being NULL.
34  * On memory allocation failure -1 will be returned.
35  */
36 int
37 tls_host_port(const char *hostport, char **host, char **port)
38 {
39         char *h, *p, *s;
40         int rv = 1;
41
42         *host = NULL;
43         *port = NULL;
44
45         if ((s = strdup(hostport)) == NULL)
46                 goto fail;
47
48         h = p = s;
49
50         /* See if this is an IPv6 literal with square braces. */
51         if (p[0] == '[') {
52                 h++;
53                 if ((p = strchr(s, ']')) == NULL)
54                         goto done;
55                 *p++ = '\0';
56         }
57
58         /* Find the port seperator. */
59         if ((p = strchr(p, ':')) == NULL)
60                 goto done;
61
62         /* If there is another separator then we have issues. */
63         if (strchr(p + 1, ':') != NULL)
64                 goto done;
65
66         *p++ = '\0';
67
68         if (asprintf(host, "%s", h) == -1)
69                 goto fail;
70         if (asprintf(port, "%s", p) == -1)
71                 goto fail;
72
73         rv = 0;
74         goto done;
75
76  fail:
77         free(*host);
78         *host = NULL;
79         free(*port);
80         *port = NULL;
81         rv = -1;
82
83  done:
84         free(s);
85
86         return (rv);
87 }
88
89 static int
90 tls_password_cb(char *buf, int size, int rwflag, void *u)
91 {
92         size_t  len;
93         if (u == NULL) {
94                 memset(buf, 0, size);
95                 return (0);
96         }
97         if ((len = strlcpy(buf, u, size)) >= (size_t)size)
98                 return (0);
99         return (len);
100 }
101
102 uint8_t *
103 tls_load_file(const char *name, size_t *len, char *password)
104 {
105         FILE *fp;
106         EVP_PKEY *key = NULL;
107         BIO *bio = NULL;
108         char *data, *buf = NULL;
109         struct stat st;
110         size_t size;
111         int fd = -1;
112
113         *len = 0;
114
115         if ((fd = open(name, O_RDONLY)) == -1)
116                 return (NULL);
117
118         /* Just load the file into memory without decryption */
119         if (password == NULL) {
120                 if (fstat(fd, &st) != 0)
121                         goto fail;
122                 size = (size_t)st.st_size;
123                 if ((buf = calloc(1, size + 1)) == NULL)
124                         goto fail;
125                 if (read(fd, buf, size) != size)
126                         goto fail;
127                 close(fd);
128                 goto done;
129         }
130
131         /* Or read the (possibly) encrypted key from file */
132         if ((fp = fdopen(fd, "r")) == NULL)
133                 goto fail;
134         fd = -1;
135
136         key = PEM_read_PrivateKey(fp, NULL, tls_password_cb, password);
137         fclose(fp);
138         if (key == NULL)
139                 goto fail;
140
141         /* Write unencrypted key to memory buffer */
142         if ((bio = BIO_new(BIO_s_mem())) == NULL)
143                 goto fail;
144         if (!PEM_write_bio_PrivateKey(bio, key, NULL, NULL, 0, NULL, NULL))
145                 goto fail;
146         if ((size = BIO_get_mem_data(bio, &data)) <= 0)
147                 goto fail;
148         if ((buf = calloc(1, size)) == NULL)
149                 goto fail;
150         memcpy(buf, data, size);
151
152         BIO_free_all(bio);
153         EVP_PKEY_free(key);
154
155  done:
156         *len = size;
157         return (buf);
158
159  fail:
160         free(buf);
161         if (fd != -1)
162                 close(fd);
163         if (bio != NULL)
164                 BIO_free_all(bio);
165         if (key != NULL)
166                 EVP_PKEY_free(key);
167
168         return (NULL);
169 }