xref: /DragonStub/apps/lib/hexdump.c (revision f412fd2a1a248b546b7085648dece8d908077fab)
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 }