hexdump.c 1.5 KB

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