1/* 2 * Copyright (C) 2018 Yubico AB - See COPYING 3 */ 4 5#include <openssl/bio.h> 6#include <openssl/evp.h> 7#include <limits.h> 8#include <stdint.h> 9#include <string.h> 10 11#include "b64.h" 12 13int b64_encode(const void *ptr, size_t len, char **out) { 14 BIO *bio_b64 = NULL; 15 BIO *bio_mem = NULL; 16 char *b64_ptr = NULL; 17 long b64_len; 18 int n; 19 int ok = 0; 20 21 if (ptr == NULL || out == NULL || len > INT_MAX) 22 return (0); 23 24 *out = NULL; 25 26 bio_b64 = BIO_new(BIO_f_base64()); 27 if (bio_b64 == NULL) 28 goto fail; 29 30 bio_mem = BIO_new(BIO_s_mem()); 31 if (bio_mem == NULL) 32 goto fail; 33 34 BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL); 35 BIO_push(bio_b64, bio_mem); 36 37 n = BIO_write(bio_b64, ptr, (int) len); 38 if (n < 0 || (size_t) n != len) 39 goto fail; 40 41 if (BIO_flush(bio_b64) < 0) 42 goto fail; 43 44 b64_len = BIO_get_mem_data(bio_b64, &b64_ptr); 45 if (b64_len < 0 || (size_t) b64_len == SIZE_MAX || b64_ptr == NULL) 46 goto fail; 47 48 *out = calloc(1, (size_t) b64_len + 1); 49 if (*out == NULL) 50 goto fail; 51 52 memcpy(*out, b64_ptr, (size_t) b64_len); 53 ok = 1; 54 55fail: 56 BIO_free(bio_b64); 57 BIO_free(bio_mem); 58 59 return (ok); 60} 61 62int b64_decode(const char *in, void **ptr, size_t *len) { 63 BIO *bio_mem = NULL; 64 BIO *bio_b64 = NULL; 65 size_t alloc_len; 66 int n; 67 int ok = 0; 68 69 if (in == NULL || ptr == NULL || len == NULL || strlen(in) > INT_MAX) 70 return (0); 71 72 *ptr = NULL; 73 *len = 0; 74 75 bio_b64 = BIO_new(BIO_f_base64()); 76 if (bio_b64 == NULL) 77 goto fail; 78 79 bio_mem = BIO_new_mem_buf((const void *) in, -1); 80 if (bio_mem == NULL) 81 goto fail; 82 83 BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL); 84 BIO_push(bio_b64, bio_mem); 85 86 alloc_len = strlen(in); 87 *ptr = calloc(1, alloc_len); 88 if (*ptr == 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 = 1; 97 98fail: 99 BIO_free(bio_b64); 100 BIO_free(bio_mem); 101 102 if (!ok) { 103 free(*ptr); 104 *ptr = NULL; 105 *len = 0; 106 } 107 108 return (ok); 109} 110