1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- // SPDX-License-Identifier: GPL-3.0-or-later
- // Copyright © 2019 Ariadne Devos
- // sHT -- compare byte arrays
- #ifndef _sHT_STRING_H
- #define _sHT_STRING_H
- #include <sHT/test.h>
- #include <limits.h>
- #include <stddef.h>
- #include <stdint.h>
- #include <sys/types.h>
- #include <sHT/minmax-arch.h>
- /** String comparison
- In short: <string.h>, but with Spectre precautions.
- -- and non-optimised, but profile first before fixing that.
- These functions interpret memory areas as a sequence of readable
- bytes, test them and perhaps calculate something. */
- /** Compute the minimum of two integers, typically some kind of length. */
- __attribute__((const))
- static inline size_t
- sHT_min_size(size_t x, size_t y)
- {
- _sHT_min(&x, y);
- return x;
- }
- /** Compare two buffers of know, equal lengths for equality.
- The semantics are the same as @var{sHT_streq}. @var{length0} and
- @var{length1} have been unified into @var{length}. */
- __attribute__((pure))
- size_t
- sHT_memeq(const char *buffer0, const char *buffer1, size_t correct, size_t otherwise, size_t length);
- /** Compare two buffers of known length for equality
- @var{buffer0}: the first string, not modified concurrently and readable
- @var{buffer1}: the second string, not modified concurrently and readable
- @var{correct}: return if the strings are equal
- @var{otherwise}: return if the strings are unequal
- @var{length0}: the number of bytes in @var{buffer0}
- @var{length1}: the number of bytes in @var{buffer1}
- A little Spectre bug: even if the length is zero, the first element might be
- read. A timing side-channel: the execution time does not only depend on the
- lengths, but also the characters of the strings -- therefore, unsuitable for
- passphrases and their hashes.
- The test may speculatively be incorrect, but the return value is always one
- of @var{correct} or @var{otherwise}. */
- __attribute__((pure))
- static inline size_t
- sHT_streq(const char *buffer0, const char *buffer1, size_t correct, size_t otherwise, size_t length0, size_t length1)
- {
- if (sHT_neq(length0, length1))
- return otherwise;
- return sHT_memeq(buffer0, buffer1, correct, otherwise, sHT_min_size(length0, length1));
- }
- /** Move bytes from @var{from} to the end of @var{to}
- @var{to}: a writable buffer that is not accessed concurrently
- @var{from}: a readable buffer that is not modified concurrently
- `length0`:
- the capacity, size of `to` (positive)
- `length1`:
- the capacity, size of `from` (positive)
- @var{i0}: the index in @var{to} to start writing to
- (not greater than length0)
- @var{i1}: the index in @var{from} to start reading from
- (not greater than length1)
- @var{to} and @var{from} are disjoint.
- All bytes of @var{to} may be written and
- all bytes of @var{from} may be read.
- Non-speculatively, copy as many bytes as the capacities allow,
- in order, contiguously, from @var{from + i1} to @var{to + i0},
- and return the number of moved bytes.
- Speculatively, less bytes could be copied, but the number of
- moved bytes is still correct. */
- size_t
- sHT_append(char *to, const char *from, size_t length0, size_t length1, size_t i0, size_t i1);
- #endif
|