xref: /freebsd/contrib/libfido2/tools/base64.c (revision 2ccfa855b2fc331819953e3de1b1c15ce5b95a7e)
10afa8e06SEd Maste /*
20afa8e06SEd Maste  * Copyright (c) 2018 Yubico AB. All rights reserved.
30afa8e06SEd Maste  * Use of this source code is governed by a BSD-style
40afa8e06SEd Maste  * license that can be found in the LICENSE file.
5*2ccfa855SEd Maste  * SPDX-License-Identifier: BSD-2-Clause
60afa8e06SEd Maste  */
70afa8e06SEd Maste 
80afa8e06SEd Maste #include <openssl/bio.h>
90afa8e06SEd Maste #include <openssl/evp.h>
100afa8e06SEd Maste 
110afa8e06SEd Maste #include <limits.h>
120afa8e06SEd Maste #include <stdint.h>
130afa8e06SEd Maste #include <string.h>
140afa8e06SEd Maste 
150afa8e06SEd Maste #include "../openbsd-compat/openbsd-compat.h"
160afa8e06SEd Maste #include "extern.h"
170afa8e06SEd Maste 
180afa8e06SEd Maste int
base64_encode(const void * ptr,size_t len,char ** out)190afa8e06SEd Maste base64_encode(const void *ptr, size_t len, char **out)
200afa8e06SEd Maste {
210afa8e06SEd Maste 	BIO  *bio_b64 = NULL;
220afa8e06SEd Maste 	BIO  *bio_mem = NULL;
230afa8e06SEd Maste 	char *b64_ptr = NULL;
240afa8e06SEd Maste 	long  b64_len;
250afa8e06SEd Maste 	int   n;
260afa8e06SEd Maste 	int   ok = -1;
270afa8e06SEd Maste 
280afa8e06SEd Maste 	if (ptr == NULL || out == NULL || len > INT_MAX)
290afa8e06SEd Maste 		return (-1);
300afa8e06SEd Maste 
310afa8e06SEd Maste 	*out = NULL;
320afa8e06SEd Maste 
330afa8e06SEd Maste 	if ((bio_b64 = BIO_new(BIO_f_base64())) == NULL)
340afa8e06SEd Maste 		goto fail;
350afa8e06SEd Maste 	if ((bio_mem = BIO_new(BIO_s_mem())) == NULL)
360afa8e06SEd Maste 		goto fail;
370afa8e06SEd Maste 
380afa8e06SEd Maste 	BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL);
390afa8e06SEd Maste 	BIO_push(bio_b64, bio_mem);
400afa8e06SEd Maste 
410afa8e06SEd Maste 	n = BIO_write(bio_b64, ptr, (int)len);
420afa8e06SEd Maste 	if (n < 0 || (size_t)n != len)
430afa8e06SEd Maste 		goto fail;
440afa8e06SEd Maste 
450afa8e06SEd Maste 	if (BIO_flush(bio_b64) < 0)
460afa8e06SEd Maste 		goto fail;
470afa8e06SEd Maste 
480afa8e06SEd Maste 	b64_len = BIO_get_mem_data(bio_b64, &b64_ptr);
490afa8e06SEd Maste 	if (b64_len < 0 || (size_t)b64_len == SIZE_MAX || b64_ptr == NULL)
500afa8e06SEd Maste 		goto fail;
510afa8e06SEd Maste 	if ((*out = calloc(1, (size_t)b64_len + 1)) == NULL)
520afa8e06SEd Maste 		goto fail;
530afa8e06SEd Maste 
540afa8e06SEd Maste 	memcpy(*out, b64_ptr, (size_t)b64_len);
550afa8e06SEd Maste 	ok = 0;
560afa8e06SEd Maste 
570afa8e06SEd Maste fail:
580afa8e06SEd Maste 	BIO_free(bio_b64);
590afa8e06SEd Maste 	BIO_free(bio_mem);
600afa8e06SEd Maste 
610afa8e06SEd Maste 	return (ok);
620afa8e06SEd Maste }
630afa8e06SEd Maste 
640afa8e06SEd Maste int
base64_decode(const char * in,void ** ptr,size_t * len)650afa8e06SEd Maste base64_decode(const char *in, void **ptr, size_t *len)
660afa8e06SEd Maste {
670afa8e06SEd Maste 	BIO    *bio_mem = NULL;
680afa8e06SEd Maste 	BIO    *bio_b64 = NULL;
690afa8e06SEd Maste 	size_t  alloc_len;
700afa8e06SEd Maste 	int     n;
710afa8e06SEd Maste 	int     ok = -1;
720afa8e06SEd Maste 
730afa8e06SEd Maste 	if (in == NULL || ptr == NULL || len == NULL || strlen(in) > INT_MAX)
740afa8e06SEd Maste 		return (-1);
750afa8e06SEd Maste 
760afa8e06SEd Maste 	*ptr = NULL;
770afa8e06SEd Maste 	*len = 0;
780afa8e06SEd Maste 
790afa8e06SEd Maste 	if ((bio_b64 = BIO_new(BIO_f_base64())) == NULL)
800afa8e06SEd Maste 		goto fail;
810afa8e06SEd Maste 	if ((bio_mem = BIO_new_mem_buf((const void *)in, -1)) == NULL)
820afa8e06SEd Maste 		goto fail;
830afa8e06SEd Maste 
840afa8e06SEd Maste 	BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL);
850afa8e06SEd Maste 	BIO_push(bio_b64, bio_mem);
860afa8e06SEd Maste 
870afa8e06SEd Maste 	alloc_len = strlen(in);
880afa8e06SEd Maste 	if ((*ptr = calloc(1, alloc_len)) == NULL)
890afa8e06SEd Maste 		goto fail;
900afa8e06SEd Maste 
910afa8e06SEd Maste 	n = BIO_read(bio_b64, *ptr, (int)alloc_len);
920afa8e06SEd Maste 	if (n <= 0 || BIO_eof(bio_b64) == 0)
930afa8e06SEd Maste 		goto fail;
940afa8e06SEd Maste 
950afa8e06SEd Maste 	*len = (size_t)n;
960afa8e06SEd Maste 	ok = 0;
970afa8e06SEd Maste 
980afa8e06SEd Maste fail:
990afa8e06SEd Maste 	BIO_free(bio_b64);
1000afa8e06SEd Maste 	BIO_free(bio_mem);
1010afa8e06SEd Maste 
1020afa8e06SEd Maste 	if (ok < 0) {
1030afa8e06SEd Maste 		free(*ptr);
1040afa8e06SEd Maste 		*ptr = NULL;
1050afa8e06SEd Maste 		*len = 0;
1060afa8e06SEd Maste 	}
1070afa8e06SEd Maste 
1080afa8e06SEd Maste 	return (ok);
1090afa8e06SEd Maste }
1100afa8e06SEd Maste 
1110afa8e06SEd Maste int
base64_read(FILE * f,struct blob * out)1120afa8e06SEd Maste base64_read(FILE *f, struct blob *out)
1130afa8e06SEd Maste {
1140afa8e06SEd Maste 	char *line = NULL;
1150afa8e06SEd Maste 	size_t linesize = 0;
1160afa8e06SEd Maste 	ssize_t n;
1170afa8e06SEd Maste 
1180afa8e06SEd Maste 	out->ptr = NULL;
1190afa8e06SEd Maste 	out->len = 0;
1200afa8e06SEd Maste 
1210afa8e06SEd Maste 	if ((n = getline(&line, &linesize, f)) <= 0 ||
1220afa8e06SEd Maste 	    (size_t)n != strlen(line)) {
1230afa8e06SEd Maste 		free(line); /* XXX should be free'd _even_ if getline() fails */
1240afa8e06SEd Maste 		return (-1);
1250afa8e06SEd Maste 	}
1260afa8e06SEd Maste 
1270afa8e06SEd Maste 	if (base64_decode(line, (void **)&out->ptr, &out->len) < 0) {
1280afa8e06SEd Maste 		free(line);
1290afa8e06SEd Maste 		return (-1);
1300afa8e06SEd Maste 	}
1310afa8e06SEd Maste 
1320afa8e06SEd Maste 	free(line);
1330afa8e06SEd Maste 
1340afa8e06SEd Maste 	return (0);
1350afa8e06SEd Maste }
136