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