diff options
Diffstat (limited to 'tools/base64.c')
-rw-r--r-- | tools/base64.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/tools/base64.c b/tools/base64.c new file mode 100644 index 0000000..9f31def --- /dev/null +++ b/tools/base64.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018 Yubico AB. All rights reserved. | ||
3 | * Use of this source code is governed by a BSD-style | ||
4 | * license that can be found in the LICENSE file. | ||
5 | */ | ||
6 | |||
7 | #include <openssl/bio.h> | ||
8 | #include <openssl/evp.h> | ||
9 | |||
10 | #include <fido.h> | ||
11 | #include <limits.h> | ||
12 | #include <stdint.h> | ||
13 | #include <string.h> | ||
14 | |||
15 | #include "../openbsd-compat/openbsd-compat.h" | ||
16 | #include "extern.h" | ||
17 | |||
18 | int | ||
19 | base64_encode(const void *ptr, size_t len, char **out) | ||
20 | { | ||
21 | BIO *bio_b64 = NULL; | ||
22 | BIO *bio_mem = NULL; | ||
23 | char *b64_ptr = NULL; | ||
24 | long b64_len; | ||
25 | int n; | ||
26 | int ok = -1; | ||
27 | |||
28 | if (ptr == NULL || out == NULL || len > INT_MAX) | ||
29 | return (-1); | ||
30 | |||
31 | *out = NULL; | ||
32 | |||
33 | if ((bio_b64 = BIO_new(BIO_f_base64())) == NULL) | ||
34 | goto fail; | ||
35 | if ((bio_mem = BIO_new(BIO_s_mem())) == NULL) | ||
36 | goto fail; | ||
37 | |||
38 | BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL); | ||
39 | BIO_push(bio_b64, bio_mem); | ||
40 | |||
41 | n = BIO_write(bio_b64, ptr, (int)len); | ||
42 | if (n < 0 || (size_t)n != len) | ||
43 | goto fail; | ||
44 | |||
45 | if (BIO_flush(bio_b64) < 0) | ||
46 | goto fail; | ||
47 | |||
48 | b64_len = BIO_get_mem_data(bio_b64, &b64_ptr); | ||
49 | if (b64_len < 0 || (size_t)b64_len == SIZE_MAX || b64_ptr == NULL) | ||
50 | goto fail; | ||
51 | if ((*out = calloc(1, (size_t)b64_len + 1)) == NULL) | ||
52 | goto fail; | ||
53 | |||
54 | memcpy(*out, b64_ptr, (size_t)b64_len); | ||
55 | ok = 0; | ||
56 | |||
57 | fail: | ||
58 | BIO_free(bio_b64); | ||
59 | BIO_free(bio_mem); | ||
60 | |||
61 | return (ok); | ||
62 | } | ||
63 | |||
64 | int | ||
65 | base64_decode(char *in, void **ptr, size_t *len) | ||
66 | { | ||
67 | BIO *bio_mem = NULL; | ||
68 | BIO *bio_b64 = NULL; | ||
69 | size_t alloc_len; | ||
70 | int n; | ||
71 | int ok = -1; | ||
72 | |||
73 | if (in == NULL || ptr == NULL || len == NULL || strlen(in) > INT_MAX) | ||
74 | return (-1); | ||
75 | |||
76 | *ptr = NULL; | ||
77 | *len = 0; | ||
78 | |||
79 | if ((bio_b64 = BIO_new(BIO_f_base64())) == NULL) | ||
80 | goto fail; | ||
81 | if ((bio_mem = BIO_new_mem_buf((void *)in, -1)) == NULL) | ||
82 | goto fail; | ||
83 | |||
84 | BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL); | ||
85 | BIO_push(bio_b64, bio_mem); | ||
86 | |||
87 | alloc_len = strlen(in); | ||
88 | if ((*ptr = calloc(1, alloc_len)) == NULL) | ||
89 | goto fail; | ||
90 | |||
91 | n = BIO_read(bio_b64, *ptr, (int)alloc_len); | ||
92 | if (n <= 0 || BIO_eof(bio_b64) == 0) | ||
93 | goto fail; | ||
94 | |||
95 | *len = (size_t)n; | ||
96 | ok = 0; | ||
97 | |||
98 | fail: | ||
99 | BIO_free(bio_b64); | ||
100 | BIO_free(bio_mem); | ||
101 | |||
102 | if (ok < 0) { | ||
103 | free(*ptr); | ||
104 | *ptr = NULL; | ||
105 | *len = 0; | ||
106 | } | ||
107 | |||
108 | return (ok); | ||
109 | } | ||
110 | |||
111 | int | ||
112 | base64_read(FILE *f, struct blob *out) | ||
113 | { | ||
114 | char *line = NULL; | ||
115 | size_t linesize = 0; | ||
116 | ssize_t n; | ||
117 | |||
118 | out->ptr = NULL; | ||
119 | out->len = 0; | ||
120 | |||
121 | if ((n = getline(&line, &linesize, f)) <= 0 || | ||
122 | (size_t)n != strlen(line)) { | ||
123 | free(line); /* XXX should be free'd _even_ if getline() fails */ | ||
124 | return (-1); | ||
125 | } | ||
126 | |||
127 | if (base64_decode(line, (void **)&out->ptr, &out->len) < 0) { | ||
128 | free(line); | ||
129 | return (-1); | ||
130 | } | ||
131 | |||
132 | free(line); | ||
133 | |||
134 | return (0); | ||
135 | } | ||