xref: /openbsd/usr.sbin/rpki-client/encoding.c (revision 771fbea0)
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