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