string.h 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // SPDX-License-Identifier: GPL-2.0 or GPL-3.0
  2. // Copyright © 2019 Ariadne Devos
  3. // sHT -- compare byte arrays
  4. #ifndef _sHT_STRING_H
  5. #define _sHT_STRING_H
  6. #include <sHT/test.h>
  7. #include <limits.h>
  8. #include <stddef.h>
  9. #include <stdint.h>
  10. #include <sys/types.h>
  11. #include <sHT/minmax-arch.h>
  12. /** String comparison
  13. In short: <string.h>, but with Spectre precautions.
  14. -- and non-optimised, but profile first before fixing that.
  15. These functions interpret memory areas as a sequence of readable
  16. bytes, test them and perhaps calculate something. */
  17. /** Compute the minimum of two integers, typically some kind of length.
  18. Ensures:
  19. (x) ret = x ∨ ret = y
  20. (y) ret ≤ x
  21. (z) ret ≤ y */
  22. __attribute__((const))
  23. static inline size_t
  24. sHT_min_size(size_t x, size_t y)
  25. {
  26. _sHT_min(&x, y);
  27. return x;
  28. }
  29. /** Compare two buffers of know, equal lengths for equality.
  30. The semantics are the same as @var{sHT_streq}. @var{length0} and
  31. @var{length1} have been unified into @var{length}. */
  32. __attribute__((pure))
  33. size_t
  34. sHT_memeq(const char *buffer0, const char *buffer1, size_t correct, size_t otherwise, size_t length);
  35. /** Compare two buffers of known length for equality
  36. @var{buffer0}: the first string, not modified concurrently and readable
  37. @var{buffer1}: the second string, not modified concurrently and readable
  38. @var{correct}: return if the strings are equal
  39. @var{otherwise}: return if the strings are unequal
  40. @var{length0}: the number of bytes in @var{buffer0}
  41. @var{length1}: the number of bytes in @var{buffer1}
  42. A little Spectre bug: even if the length is zero, the first element might be
  43. read. A timing side-channel: the execution time does not only depend on the
  44. lengths, but also the characters of the strings -- therefore, unsuitable for
  45. passphrases and their hashes.
  46. The test may speculatively be incorrect, but the return value is always one
  47. of @var{correct} or @var{otherwise}. */
  48. __attribute__((pure))
  49. static inline size_t
  50. sHT_streq(const char *buffer0, const char *buffer1, size_t correct, size_t otherwise, size_t length0, size_t length1)
  51. {
  52. if (sHT_neq(length0, length1))
  53. return otherwise;
  54. return sHT_memeq(buffer0, buffer1, correct, otherwise, sHT_min_size(length0, length1));
  55. }
  56. /** Move bytes from @var{from} to the end of @var{to}
  57. @var{to}: a writable buffer that is not accessed concurrently
  58. @var{from}: a readable buffer that is not modified concurrently
  59. `length0`:
  60. the capacity, size of `to` (positive)
  61. `length1`:
  62. the capacity, size of `from` (positive)
  63. @var{i0}: the index in @var{to} to start writing to
  64. (not greater than length0)
  65. @var{i1}: the index in @var{from} to start reading from
  66. (not greater than length1)
  67. @var{to} and @var{from} are disjoint.
  68. All bytes of @var{to} may be written and
  69. all bytes of @var{from} may be read.
  70. Non-speculatively, copy as many bytes as the capacities allow,
  71. in order, contiguously, from @var{from + i1} to @var{to + i0},
  72. and return the number of moved bytes.
  73. Speculatively, less bytes could be copied, but the number of
  74. moved bytes is still correct. */
  75. size_t
  76. sHT_append(char *to, const char *from, size_t length0, size_t length1, size_t i0, size_t i1);
  77. #endif