Home | History | Annotate | Line # | Download | only in dist
      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 
     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 
     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