From 3d99d9b4431c00fe86a6f451e37fce72b0a12909 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 22 Mar 2018 15:44:01 +0100 Subject: [PATCH] add base16_{de,en}code() --- src/headers/tomcrypt_custom.h | 2 + src/headers/tomcrypt_misc.h | 9 +++++ src/misc/base16/base16_decode.c | 65 ++++++++++++++++++++++++++++++ src/misc/base16/base16_encode.c | 71 +++++++++++++++++++++++++++++++++ src/misc/crypt/crypt.c | 3 ++ tests/base16_test.c | 53 ++++++++++++++++++++++++ tests/misc_test.c | 3 ++ tests/tomcrypt_test.h | 1 + 8 files changed, 207 insertions(+) create mode 100644 src/misc/base16/base16_decode.c create mode 100644 src/misc/base16/base16_encode.c create mode 100644 tests/base16_test.c diff --git a/src/headers/tomcrypt_custom.h b/src/headers/tomcrypt_custom.h index dc051ac6..4353536a 100644 --- a/src/headers/tomcrypt_custom.h +++ b/src/headers/tomcrypt_custom.h @@ -450,6 +450,8 @@ #define LTC_BASE64_URL /* Base32 encoding/decoding */ #define LTC_BASE32 +/* Base16/hex encoding/decoding */ +#define LTC_BASE16 /* Keep LTC_NO_HKDF for compatibility reasons * superseeded by LTC_NO_MISC*/ diff --git a/src/headers/tomcrypt_misc.h b/src/headers/tomcrypt_misc.h index 63fc3a89..67573dba 100644 --- a/src/headers/tomcrypt_misc.h +++ b/src/headers/tomcrypt_misc.h @@ -46,6 +46,15 @@ int base32_decode(const unsigned char *in, unsigned long inlen, base32_alphabet id); #endif +/* ---- BASE16 Routines ---- */ +#ifdef LTC_BASE16 +int base16_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + int caps); +int base16_decode(const char *in, + unsigned char *out, unsigned long *outlen); +#endif + /* ===> LTC_HKDF -- RFC5869 HMAC-based Key Derivation Function <=== */ #ifdef LTC_HKDF diff --git a/src/misc/base16/base16_decode.c b/src/misc/base16/base16_decode.c new file mode 100644 index 00000000..5743be9e --- /dev/null +++ b/src/misc/base16/base16_decode.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt.h" + +/** + @file base16_decode.c + Base16/Hex decode a string. + Based on https://stackoverflow.com/a/23898449 + Adapted for libtomcrypt by Steffen Jaeckel +*/ + +#ifdef LTC_BASE16 + +/** + Base16 decode a string + @param in The Base16 string to decode + @param out [out] The destination of the binary decoded data + @param outlen [in/out] The max size and resulting size of the decoded data + @return CRYPT_OK if successful +*/ +int base16_decode(const char *in, + unsigned char *out, unsigned long *outlen) +{ + unsigned long pos, in_len, out_len; + unsigned char idx0; + unsigned char idx1; + + const unsigned char hashmap[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */ + 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 89:;<=>? */ + 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, /* @ABCDEFG */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* HIJKLMNO */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* PQRSTUVW */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* XYZ[\]^_ */ + 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, /* `abcdefg */ + }; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + in_len = strlen(in); + if ((in_len % 2) == 1) return CRYPT_INVALID_PACKET; + out_len = *outlen * 2; + for (pos = 0; ((pos + 1 < out_len) && (pos + 1 < in_len)); pos += 2) { + idx0 = (unsigned char) (in[pos + 0] & 0x1F) ^ 0x10; + idx1 = (unsigned char) (in[pos + 1] & 0x1F) ^ 0x10; + out[pos / 2] = (unsigned char) (hashmap[idx0] << 4) | hashmap[idx1]; + } + *outlen = pos / 2; + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/misc/base16/base16_encode.c b/src/misc/base16/base16_encode.c new file mode 100644 index 00000000..d400d76b --- /dev/null +++ b/src/misc/base16/base16_encode.c @@ -0,0 +1,71 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt.h" + +/** + @file base16_encode.c + Base16/Hex encode a string, Steffen Jaeckel +*/ + +#ifdef LTC_BASE16 + +/** + Base16 encode a buffer + @param in The input buffer to encode + @param inlen The length of the input buffer + @param out [out] The destination of the Base16 encoded data + @param outlen [in/out] The max size and resulting size of the encoded data + @param caps Output 'a-f' on 0 and 'A-F' otherwise. + @return CRYPT_OK if successful +*/ +int base16_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + int caps) +{ + unsigned long i, x; + const char *alphabet; + const char *alphabets[2] = { + "0123456789abcdef", + "0123456789ABCDEF", + }; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* check the sizes */ + x = inlen * 2 + 1; + + if (x < inlen) return CRYPT_OVERFLOW; + + if (*outlen < x) { + *outlen = x; + return CRYPT_BUFFER_OVERFLOW; + } + *outlen = x; + + if (caps == 0) alphabet = alphabets[0]; + else alphabet = alphabets[1]; + + x -= 1; + for (i = 0; i < x; i += 2) { + out[i] = alphabet[(in[i/2] >> 4) & 0x0f]; + out[i+1] = alphabet[in[i/2] & 0x0f]; + } + out[x] = '\0'; + + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/misc/crypt/crypt.c b/src/misc/crypt/crypt.c index bd57a0aa..2345d7d9 100644 --- a/src/misc/crypt/crypt.c +++ b/src/misc/crypt/crypt.c @@ -414,6 +414,9 @@ const char *crypt_build_settings = #if defined(LTC_BASE32) " BASE32 " #endif +#if defined(LTC_BASE16) + " BASE16 " +#endif #if defined(LTC_CRC32) " CRC32 " #endif diff --git a/tests/base16_test.c b/tests/base16_test.c new file mode 100644 index 00000000..e025e5b0 --- /dev/null +++ b/tests/base16_test.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include + +#ifdef LTC_BASE16 + +int base16_test(void) +{ + unsigned char in[100], tmp[100]; + char out[201]; + unsigned char testin[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; + const char *testout[2] = { + "0123456789abcdef", + "0123456789ABCDEF", + }; + unsigned long x, l1, l2; + int idx; + + for (idx = 0; idx < 2; idx++) { + for (x = 0; x < 100; x++) { + yarrow_read(in, x, &yarrow_prng); + l1 = sizeof(out); + DO(base16_encode(in, x, out, &l1, idx)); + l2 = sizeof(tmp); + DO(base16_decode(out, tmp, &l2)); + DO(do_compare_testvector(tmp, l2, in, x, "random base16", idx * 100 + x)); + } + } + + for (idx = 0; idx < 2; idx++) { + l1 = sizeof(out); + DO(base16_encode(testin, sizeof(testin), out, &l1, idx)); + DO(do_compare_testvector(out, strlen(out), testout[idx], strlen(testout[idx]), "testout base16", idx)); + l2 = sizeof(tmp); + DO(base16_decode(out, tmp, &l2)); + DO(do_compare_testvector(tmp, l2, testin, sizeof(testin), "testin base16", idx)); + } + + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/tests/misc_test.c b/tests/misc_test.c index c2dcdf73..0bb4707f 100644 --- a/tests/misc_test.c +++ b/tests/misc_test.c @@ -22,6 +22,9 @@ int misc_test(void) #ifdef LTC_BASE32 DO(base32_test()); #endif +#ifdef LTC_BASE16 + DO(base16_test()); +#endif #ifdef LTC_ADLER32 DO(adler32_test()); #endif diff --git a/tests/tomcrypt_test.h b/tests/tomcrypt_test.h index b51b8810..bb5f5f74 100644 --- a/tests/tomcrypt_test.h +++ b/tests/tomcrypt_test.h @@ -39,6 +39,7 @@ int der_test(void); int misc_test(void); int base64_test(void); int base32_test(void); +int base16_test(void); int file_test(void); int multi_test(void); int prng_test(void);