1 /* $OpenBSD: encoding.c,v 1.2 2021/04/19 17:04:35 deraadt Exp $ */ 2 /* 3 * Copyright (c) 2020 Claudio Jeker <claudio@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 #include <err.h> 18 #include <limits.h> 19 #include <stdlib.h> 20 #include <string.h> 21 22 #include <openssl/evp.h> 23 24 #include "extern.h" 25 26 /* 27 * Decode base64 encoded string into binary buffer returned in out. 28 * The out buffer size is stored in outlen. 29 * Returns 0 on success or -1 for any errors. 30 */ 31 int 32 base64_decode(const unsigned char *in, unsigned char **out, size_t *outlen) 33 { 34 static EVP_ENCODE_CTX *ctx; 35 unsigned char *to; 36 size_t inlen; 37 int tolen; 38 39 if (ctx == NULL && (ctx = EVP_ENCODE_CTX_new()) == NULL) 40 err(1, "EVP_ENCODE_CTX_new"); 41 42 *out = NULL; 43 *outlen = 0; 44 45 inlen = strlen(in); 46 if (inlen >= INT_MAX - 3) 47 return -1; 48 tolen = ((inlen + 3) / 4) * 3 + 1; 49 if ((to = malloc(tolen)) == NULL) 50 return -1; 51 52 EVP_DecodeInit(ctx); 53 if (EVP_DecodeUpdate(ctx, to, &tolen, in, inlen) == -1) 54 goto fail; 55 *outlen = tolen; 56 if (EVP_DecodeFinal(ctx, to + tolen, &tolen) == -1) 57 goto fail; 58 *outlen += tolen; 59 *out = to; 60 return 0; 61 62 fail: 63 free(to); 64 return -1; 65 } 66 67 /* 68 * Convert binary buffer of size dsz into an upper-case hex-string. 69 * Returns pointer to the newly allocated string. Function can't fail. 70 */ 71 char * 72 hex_encode(const unsigned char *in, size_t insz) 73 { 74 const char hex[] = "0123456789ABCDEF"; 75 size_t i; 76 char *out; 77 78 if ((out = calloc(2, insz + 1)) == NULL) 79 err(1, NULL); 80 81 for (i = 0; i < insz; i++) { 82 out[i * 2] = hex[in[i] >> 4]; 83 out[i * 2 + 1] = hex[in[i] & 0xf]; 84 } 85 out[i * 2] = '\0'; 86 87 return out; 88 } 89