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