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