1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3
4 #include "tomcrypt_private.h"
5
6 /**
7 @file base16_decode.c
8 Base16/Hex decode a string.
9 Based on https://stackoverflow.com/a/23898449
10 Adapted for libtomcrypt by Steffen Jaeckel
11 */
12
13 #ifdef LTC_BASE16
14
15 /**
16 Base16 decode a string
17 @param in The Base16 string to decode
18 @param inlen The length of the Base16 data
19 @param out [out] The destination of the binary decoded data
20 @param outlen [in/out] The max size and resulting size of the decoded data
21 @return CRYPT_OK if successful
22 */
base16_decode(const char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen)23 int base16_decode(const char *in, unsigned long inlen,
24 unsigned char *out, unsigned long *outlen)
25 {
26 unsigned long pos, out_len;
27 unsigned char idx0, idx1;
28 char in0, in1;
29
30 const unsigned char hashmap[] = {
31 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */
32 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 89:;<=>? */
33 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* @ABCDEFG */
34 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* HIJKLMNO */
35 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* PQRSTUVW */
36 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ[\]^_ */
37 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* `abcdefg */
38 };
39
40 LTC_ARGCHK(in != NULL);
41 LTC_ARGCHK(out != NULL);
42 LTC_ARGCHK(outlen != NULL);
43
44 if ((inlen % 2) == 1) return CRYPT_INVALID_PACKET;
45 out_len = *outlen * 2;
46 for (pos = 0; ((pos + 1 < out_len) && (pos + 1 < inlen)); pos += 2) {
47 in0 = in[pos + 0];
48 in1 = in[pos + 1];
49
50 if ((in0 < '0') || (in0 > 'g')) return CRYPT_INVALID_PACKET;
51 if ((in1 < '0') || (in1 > 'g')) return CRYPT_INVALID_PACKET;
52
53 idx0 = (unsigned char) (in0 & 0x1F) ^ 0x10;
54 idx1 = (unsigned char) (in1 & 0x1F) ^ 0x10;
55
56 if (hashmap[idx0] == 0xff) return CRYPT_INVALID_PACKET;
57 if (hashmap[idx1] == 0xff) return CRYPT_INVALID_PACKET;
58
59 out[pos / 2] = (unsigned char) (hashmap[idx0] << 4) | hashmap[idx1];
60 }
61 *outlen = pos / 2;
62 return CRYPT_OK;
63 }
64
65 #endif
66