string.h 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  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. __attribute__((const))
  19. static inline size_t
  20. sHT_min_size(size_t x, size_t y)
  21. {
  22. _sHT_min(&x, y);
  23. return x;
  24. }
  25. /** Compare two buffers of know, equal lengths for equality.
  26. The semantics are the same as @var{sHT_streq}. @var{length0} and
  27. @var{length1} have been unified into @var{length}. */
  28. __attribute__((pure))
  29. size_t
  30. sHT_memeq(const char *buffer0, const char *buffer1, size_t correct, size_t otherwise, size_t length);
  31. /** Compare two buffers of known length for equality
  32. @var{buffer0}: the first string, not modified concurrently and readable
  33. @var{buffer1}: the second string, not modified concurrently and readable
  34. @var{correct}: return if the strings are equal
  35. @var{otherwise}: return if the strings are unequal
  36. @var{length0}: the number of bytes in @var{buffer0}
  37. @var{length1}: the number of bytes in @var{buffer1}
  38. A little Spectre bug: even if the length is zero, the first element might be
  39. read. A timing side-channel: the execution time does not only depend on the
  40. lengths, but also the characters of the strings -- therefore, unsuitable for
  41. passphrases and their hashes.
  42. The test may speculatively be incorrect, but the return value is always one
  43. of @var{correct} or @var{otherwise}. */
  44. __attribute__((pure))
  45. static inline size_t
  46. sHT_streq(const char *buffer0, const char *buffer1, size_t correct, size_t otherwise, size_t length0, size_t length1)
  47. {
  48. if (sHT_neq(length0, length1))
  49. return otherwise;
  50. return sHT_memeq(buffer0, buffer1, correct, otherwise, sHT_min_size(length0, length1));
  51. }
  52. /** Move bytes from @var{from} to the end of @var{to}
  53. @var{to}: a writable buffer that is not accessed concurrently
  54. @var{from}: a readable buffer that is not modified concurrently
  55. `length0`:
  56. the capacity, size of `to` (positive)
  57. `length1`:
  58. the capacity, size of `from` (positive)
  59. @var{i0}: the index in @var{to} to start writing to
  60. (not greater than length0)
  61. @var{i1}: the index in @var{from} to start reading from
  62. (not greater than length1)
  63. @var{to} and @var{from} are disjoint.
  64. All bytes of @var{to} may be written and
  65. all bytes of @var{from} may be read.
  66. Non-speculatively, copy as many bytes as the capacities allow,
  67. in order, contiguously, from @var{from + i1} to @var{to + i0},
  68. and return the number of moved bytes.
  69. Speculatively, less bytes could be copied, but the number of
  70. moved bytes is still correct. */
  71. size_t
  72. sHT_append(char *to, const char *from, size_t length0, size_t length1, size_t i0, size_t i1);
  73. #endif