xref: /netbsd-src/external/bsd/pam-u2f/dist/b64.c (revision 510cde34809348e11d0aca2401c67de0cceee33b)
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 
b64_encode(const void * ptr,size_t len,char ** out)13 int 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 
55 fail:
56   BIO_free(bio_b64);
57   BIO_free(bio_mem);
58 
59   return (ok);
60 }
61 
b64_decode(const char * in,void ** ptr,size_t * len)62 int 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 
98 fail:
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