Merge pull request #368 from libtom/fix/base16-api

Improve base16
This commit is contained in:
Steffen Jaeckel 2018-03-27 12:58:18 +02:00 committed by GitHub
commit f4afa5d5bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 21 deletions

View File

@ -6631,7 +6631,7 @@ The library provides functions to encode and decode a Base16 a.k.a Hex string.
To encode a binary string in base16 call:
\index{base32\_encode()}
\index{base16\_encode()}
\begin{verbatim}
int base16_encode(const unsigned char *in, unsigned long inlen,
char *out, unsigned long *outlen,
@ -6644,9 +6644,9 @@ and \textit{caps} is either $0$ to use lower-letter \textit{a..f} or else to use
To decode a base16 string call:
\index{base32\_decode()}
\index{base16\_decode()}
\begin{verbatim}
int base16_decode(const char *in,
int base16_decode(const char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
\end{verbatim}

View File

@ -51,7 +51,7 @@ int base32_decode(const char *in, unsigned long inlen,
int base16_encode(const unsigned char *in, unsigned long inlen,
char *out, unsigned long *outlen,
int caps);
int base16_decode(const char *in,
int base16_decode(const char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
#endif

View File

@ -25,33 +25,42 @@
@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,
int base16_decode(const char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long pos, in_len, out_len;
unsigned char idx0;
unsigned char idx1;
unsigned long pos, out_len;
unsigned char idx0, idx1;
char in0, in1;
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 */
0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 89:;<=>? */
0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* @ABCDEFG */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* HIJKLMNO */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* PQRSTUVW */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ[\]^_ */
0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* `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;
if ((inlen % 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;
for (pos = 0; ((pos + 1 < out_len) && (pos + 1 < inlen)); pos += 2) {
in0 = in[pos + 0];
in1 = in[pos + 1];
if ((in0 < '0') || (in0 > 'g')) return CRYPT_INVALID_PACKET;
if ((in1 < '0') || (in1 > 'g')) return CRYPT_INVALID_PACKET;
idx0 = (unsigned char) (in0 & 0x1F) ^ 0x10;
idx1 = (unsigned char) (in1 & 0x1F) ^ 0x10;
if (hashmap[idx0] == 0xff) return CRYPT_INVALID_PACKET;
if (hashmap[idx1] == 0xff) return CRYPT_INVALID_PACKET;
out[pos / 2] = (unsigned char) (hashmap[idx0] << 4) | hashmap[idx1];
}
*outlen = pos / 2;

View File

@ -20,6 +20,7 @@ int base16_test(void)
"0123456789abcdef",
"0123456789ABCDEF",
};
const char *failing_decode = "test";
unsigned long x, l1, l2;
int idx;
@ -28,8 +29,9 @@ int base16_test(void)
yarrow_read(in, x, &yarrow_prng);
l1 = sizeof(out);
DO(base16_encode(in, x, out, &l1, idx));
l1--;
l2 = sizeof(tmp);
DO(base16_decode(out, tmp, &l2));
DO(base16_decode(out, l1, tmp, &l2));
DO(do_compare_testvector(tmp, l2, in, x, "random base16", idx * 100 + x));
}
}
@ -38,11 +40,16 @@ int base16_test(void)
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));
l1--;
l2 = sizeof(tmp);
DO(base16_decode(out, tmp, &l2));
DO(base16_decode(out, l1, tmp, &l2));
DO(do_compare_testvector(tmp, l2, testin, sizeof(testin), "testin base16", idx));
}
l1 = 4;
l2 = sizeof(tmp);
DO(base16_decode(failing_decode, l1, tmp, &l2) == CRYPT_OK ? CRYPT_FAIL_TESTVECTOR : CRYPT_OK);
return CRYPT_OK;
}