1 const char hex_asc[] = "0123456789abcdef";
2 const char hex_asc_upper[] = "0123456789ABCDEF";
3
4 /**
5 * hex_to_bin - convert a hex digit to its real value
6 * @ch: ascii character represents hex digit
7 *
8 * hex_to_bin() converts one hex digit to its actual value or -1 in case of bad
9 * input.
10 *
11 * This function is used to load cryptographic keys, so it is coded in such a
12 * way that there are no conditions or memory accesses that depend on data.
13 *
14 * Explanation of the logic:
15 * (ch - '9' - 1) is negative if ch <= '9'
16 * ('0' - 1 - ch) is negative if ch >= '0'
17 * we "and" these two values, so the result is negative if ch is in the range
18 * '0' ... '9'
19 * we are only interested in the sign, so we do a shift ">> 8"; note that right
20 * shift of a negative value is implementation-defined, so we cast the
21 * value to (unsigned) before the shift --- we have 0xffffff if ch is in
22 * the range '0' ... '9', 0 otherwise
23 * we "and" this value with (ch - '0' + 1) --- we have a value 1 ... 10 if ch is
24 * in the range '0' ... '9', 0 otherwise
25 * we add this value to -1 --- we have a value 0 ... 9 if ch is in the range '0'
26 * ... '9', -1 otherwise
27 * the next line is similar to the previous one, but we need to decode both
28 * uppercase and lowercase letters, so we use (ch & 0xdf), which converts
29 * lowercase to uppercase
30 */
hex_to_bin(unsigned char ch)31 int hex_to_bin(unsigned char ch)
32 {
33 unsigned char cu = ch & 0xdf;
34 return -1 +
35 ((ch - '0' + 1) &
36 (unsigned)((ch - '9' - 1) & ('0' - 1 - ch)) >> 8) +
37 ((cu - 'A' + 11) &
38 (unsigned)((cu - 'F' - 1) & ('A' - 1 - cu)) >> 8);
39 }