optimize bin/hex low parsing level functions (#1646)
* optimize sc_hex_to_bin * optimize sc_bin_to_hex * added documentation closes https://github.com/OpenSC/OpenSC/pull/1643 thanks to carblue <ka6613-496@online.de>
This commit is contained in:
parent
0abe9d11c7
commit
fd20ffe608
|
@ -1379,6 +1379,25 @@ const sc_path_t *sc_get_mf_path(void);
|
|||
/********************************************************************/
|
||||
|
||||
int sc_hex_to_bin(const char *in, u8 *out, size_t *outlen);
|
||||
/**
|
||||
* Converts an u8 array to a string representing the input as hexadecimal,
|
||||
* human-readable/printable form. It's the inverse function of sc_hex_to_bin.
|
||||
*
|
||||
* @param in The u8 array input to be interpreted, may be NULL iff in_len==0
|
||||
* @param in_len Less or equal to the amount of bytes available from in
|
||||
* @param out output buffer offered for the string representation, *MUST NOT*
|
||||
* be NULL and *MUST* be sufficiently sized, see out_len
|
||||
* @param out_len *MUST* be at least 1 and state the maximum of bytes available
|
||||
* within out to be written, including the \0 termination byte
|
||||
* that will be written unconditionally
|
||||
* @param separator The character to be used to separate the u8 string
|
||||
* representations. `0` will suppress separation.
|
||||
*
|
||||
* Example: input [0x3f], in_len=1, requiring an out_len>=3, will write to out:
|
||||
* [0x33, 0x66, 0x00] which reads as "3f"
|
||||
* Example: input [0x3f, 0x01], in_len=2, separator=':', req. an out_len>=6,
|
||||
* writes to out: [0x33, 0x66, 0x3A, 0x30, 0x31, 0x00] which reads as "3f:01"
|
||||
*/
|
||||
int sc_bin_to_hex(const u8 *, size_t, char *, size_t, int separator);
|
||||
size_t sc_right_trim(u8 *buf, size_t len);
|
||||
scconf_block *sc_get_conf_block(sc_context_t *ctx, const char *name1, const char *name2, int priority);
|
||||
|
|
|
@ -63,77 +63,90 @@ const char *sc_get_version(void)
|
|||
|
||||
int sc_hex_to_bin(const char *in, u8 *out, size_t *outlen)
|
||||
{
|
||||
int err = SC_SUCCESS;
|
||||
size_t left, count = 0, in_len;
|
||||
|
||||
const char *sc_hex_to_bin_separators = " :";
|
||||
if (in == NULL || out == NULL || outlen == NULL) {
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
left = *outlen;
|
||||
in_len = strlen(in);
|
||||
|
||||
while (*in != '\0') {
|
||||
int byte = 0, nybbles = 2;
|
||||
|
||||
while (nybbles-- && *in && *in != ':' && *in != ' ') {
|
||||
char c;
|
||||
byte <<= 4;
|
||||
c = *in++;
|
||||
if ('0' <= c && c <= '9')
|
||||
c -= '0';
|
||||
else
|
||||
if ('a' <= c && c <= 'f')
|
||||
c = c - 'a' + 10;
|
||||
else
|
||||
if ('A' <= c && c <= 'F')
|
||||
c = c - 'A' + 10;
|
||||
else {
|
||||
err = SC_ERROR_INVALID_ARGUMENTS;
|
||||
goto out;
|
||||
}
|
||||
byte |= c;
|
||||
int byte_needs_nibble = 0;
|
||||
int r = SC_SUCCESS;
|
||||
size_t left = *outlen;
|
||||
u8 byte = 0;
|
||||
while (*in != '\0' && 0 != left) {
|
||||
char c = *in++;
|
||||
u8 nibble;
|
||||
if ('0' <= c && c <= '9')
|
||||
nibble = c - '0';
|
||||
else if ('a' <= c && c <= 'f')
|
||||
nibble = c - 'a' + 10;
|
||||
else if ('A' <= c && c <= 'F')
|
||||
nibble = c - 'A' + 10;
|
||||
else {
|
||||
if (strchr(sc_hex_to_bin_separators, (int) c))
|
||||
continue;
|
||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Detect premature end of string before byte is complete */
|
||||
if (in_len > 1 && *in == '\0' && nybbles >= 0) {
|
||||
err = SC_ERROR_INVALID_ARGUMENTS;
|
||||
break;
|
||||
if (byte_needs_nibble) {
|
||||
byte |= nibble;
|
||||
*out++ = (u8) byte;
|
||||
left--;
|
||||
byte_needs_nibble = 0;
|
||||
} else {
|
||||
byte = nibble << 4;
|
||||
byte_needs_nibble = 1;
|
||||
}
|
||||
|
||||
if (*in == ':' || *in == ' ')
|
||||
in++;
|
||||
if (left <= 0) {
|
||||
err = SC_ERROR_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
out[count++] = (u8) byte;
|
||||
left--;
|
||||
}
|
||||
|
||||
out:
|
||||
*outlen = count;
|
||||
return err;
|
||||
/* for ease of implementation we only accept completely hexed bytes. */
|
||||
if (byte_needs_nibble) {
|
||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* skip all trailing separators to see if we missed something */
|
||||
while (*in != '\0') {
|
||||
if (NULL == strchr(sc_hex_to_bin_separators, (int) *in))
|
||||
break;
|
||||
in++;
|
||||
}
|
||||
if (*in != '\0') {
|
||||
r = SC_ERROR_BUFFER_TOO_SMALL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
err:
|
||||
*outlen -= left;
|
||||
return r;
|
||||
}
|
||||
|
||||
int sc_bin_to_hex(const u8 *in, size_t in_len, char *out, size_t out_len,
|
||||
int in_sep)
|
||||
int in_sep)
|
||||
{
|
||||
unsigned int n, sep_len;
|
||||
char *pos, *end, sep;
|
||||
|
||||
sep = (char)in_sep;
|
||||
sep_len = sep > 0 ? 1 : 0;
|
||||
pos = out;
|
||||
end = out + out_len;
|
||||
for (n = 0; n < in_len; n++) {
|
||||
if (pos + 3 + sep_len >= end)
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
if (n && sep_len)
|
||||
*pos++ = sep;
|
||||
sprintf(pos, "%02x", in[n]);
|
||||
pos += 2;
|
||||
if (in == NULL || out == NULL) {
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
*pos = '\0';
|
||||
|
||||
if (in_sep > 0) {
|
||||
if (out_len < in_len*3 || out_len < 1)
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
} else {
|
||||
if (out_len < in_len*2 + 1)
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
const char hex[] = "0123456789abcdef";
|
||||
while (in_len) {
|
||||
unsigned char value = *in++;
|
||||
*out++ = hex[(value >> 4) & 0xF];
|
||||
*out++ = hex[ value & 0xF];
|
||||
in_len--;
|
||||
if (in_len && in_sep > 0)
|
||||
*out++ = (char)in_sep;
|
||||
}
|
||||
*out = '\0';
|
||||
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue