Browse Source

add byte_start, byte_starts

add a man page for byte_equal_notimingattack
master
Felix von Leitner 1 month ago
parent
commit
966c3f4d2f
8 changed files with 125 additions and 2 deletions
  1. +2
    -0
      CHANGES
  2. +16
    -0
      byte.h
  3. +6
    -2
      byte/byte_equal.3
  4. +17
    -0
      byte/byte_equal_notimingattack.3
  5. +20
    -0
      byte/byte_start.3
  6. +16
    -0
      byte/byte_start.c
  7. +24
    -0
      byte/byte_starts.3
  8. +24
    -0
      byte/byte_starts.c

+ 2
- 0
CHANGES View File

@ -1,4 +1,6 @@
0.33:
add byte_start, byte_starts
add a man page for byte_equal_notimingattack
0.32:
remove OpenBSD #warning (obsd maintainer says no longer needed)

+ 16
- 0
byte.h View File

@ -56,6 +56,22 @@ void byte_zero(void* out, size_t len);
#define byte_equal(s,n,t) (!byte_diff((s),(n),(t)))
/* Return 1 iff (b,blen) is a prefix of (a,alen), 0 otherwise.
* Will abort early on mismatch */
__readmemsz__(1,2)
__readmemsz__(3,4)
int byte_start(const void* a,size_t alen,const void* b,size_t blen) __pure__;
/* equivalent to byte_start(a,alen,str,strlen(str)) */
__readmemsz__(1,2)
__readmem__(3)
int byte_starts(const void* a,size_t alen,const char* str) __pure__;
#if defined(__GNUC__) && !defined(__LIBOWFAT_INTERNAL)
/* If str is a string constant, strlen will be done at compile time */
#define byte_starts(a,alen,str) (__builtin_constant_p(str) ? byte_start(a,alen,str,strlen(str)) : byte_starts(a,alen,str))
#endif
__readmemsz__(1,2)
__readmemsz__(3,2)
int byte_equal_notimingattack(const void* a, size_t len,const void* b) __pure__;

+ 6
- 2
byte/byte_equal.3 View File

@ -9,7 +9,11 @@ int \fBbyte_equal\fP(const char *\fIone\fR,size_t \fIlen\fR,const char *\fItwo\f
\fIbyte_equal\fR returns 1 if the strings are equal, 0 otherwise.
When the strings are different, byte_equal does not read bytes past the
first difference.
first difference. An attacker observing the execution timing can thus
learn where the first mismatch happened.
Use byte_equal_notimingattack to compare keys, passphrases, cookies or
hashes instead.
.SH "SEE ALSO"
byte_diff(3)
byte_diff(3), byte_equal_notimingattack(3)

+ 17
- 0
byte/byte_equal_notimingattack.3 View File

@ -0,0 +1,17 @@
.TH byte_equal_notimingattack 3
.SH NAME
byte_equal_notimingattack \- compare two strings
.SH SYNTAX
.B #include <libowfat/byte.h>
int \fBbyte_equal_notimingattack\fP(const char *\fIone\fR,size_t \fIlen\fR,const char *\fItwo\fR);
.SH DESCRIPTION
\fIbyte_equal_notimingattack\fR returns 1 if the strings are equal, 0 otherwise.
When the strings are different, byte_equal_notimingattack will still
read and compare all the other bytes. That way, an attacker observing
the timing of the execution can not learn where the first mismatch
occurred.
.SH "SEE ALSO"
byte_diff(3), byte_equal(3)

+ 20
- 0
byte/byte_start.3 View File

@ -0,0 +1,20 @@
.TH byte_start 3
.SH NAME
byte_start \- find out if string b is prefix of string a
.SH SYNTAX
.B #include <libowfat/byte.h>
int \fBbyte_start\fP(const char *\fIa\fR,size_t \fIalen\fR,const char *\fIb\fR,size_t blen);
.SH DESCRIPTION
\fIbyte_start\fR returns 1 if \fIalen\fR >= \fIblen\fR and the first \fIblen\fR bytes from
\fIa\fR and \fIb\fR are equal.
When \fIblen\fR is too large or the strings are different, \fIbyte_start\fR does not
read bytes past the first difference. An attacker observing the
execution timing can thus learn where the first mismatch happened.
Use \fIbyte_equal_notimingattack\fR to compare keys, passphrases, cookies or
hashes instead.
.SH "SEE ALSO"
byte_equal(3), byte_equal_notimingattack(3), byte_starts(3)

+ 16
- 0
byte/byte_start.c View File

@ -0,0 +1,16 @@
#include <byte.h>
#include <string.h>
int byte_start(const void* a,size_t alen,const void* b,size_t blen) {
return blen<=alen && !memcmp(a,b,blen);
}
#ifdef UNITTEST
#include <assert.h>
int main() {
static char buf[]="The quick brown fox jumps over the lazy dog";
assert(byte_start(buf,sizeof(buf)-1,"The ",4));
assert(!byte_start(buf,sizeof(buf)-1,"the ",4));
assert(!byte_start(buf,3,buf,9));
}
#endif

+ 24
- 0
byte/byte_starts.3 View File

@ -0,0 +1,24 @@
.TH byte_starts 3
.SH NAME
byte_starts \- find out if a buffer starts with a string
.SH SYNTAX
.B #include <libowfat/byte.h>
int \fBbyte_starts\fP(const char *\fIbuf\fR,size_t \fIbuflen\fR,const char *\fIstr\fR);
.SH DESCRIPTION
\fIbyte_starts\fR returns 1 if the \fIbuflen\fR>=strlen(\fIstr\fR) and the first
strlen(\fIstr\fR) bytes of \fIbuf\fR match the contents of \fIstr\fR, or
0 otherwise.
This function is meant to be used in protocol parsing and with a string
constant for \fIstr\fR and will use gcc/clang macro trickery to reduce to a call to
\fImemcmp\fR then.
\fIbyte_starts\fR compares as few bytes as possible. An attacker observing
the execution timing can thus learn where the first mismatch happened.
Use \fIbyte_equal_notimingattack\fR to compare keys, passphrases, cookies or
hashes instead.
.SH "SEE ALSO"
byte_equal(3), byte_equal_notimingattack(3), byte_start(3)

+ 24
- 0
byte/byte_starts.c View File

@ -0,0 +1,24 @@
#include <byte.h>
#undef byte_starts
#include <string.h>
int byte_starts(const void* a,size_t alen,const char* s) {
size_t i;
for (i=0; i<alen; ++i) {
if (s[i]==0) return 1;
if (((const char*)a)[i] != s[i]) return 0;
}
return s[i]==0;
}
#ifdef UNITTEST
#include <assert.h>
int main() {
static char buf[]="The quick brown fox jumps over the lazy dog";
assert(byte_starts(buf,sizeof(buf)-1,"The "));
assert(!byte_starts(buf,sizeof(buf)-1,"the "));
assert(!byte_starts(buf,2,"The "));
assert(byte_starts("The ",4,"The "));
}
#endif

Loading…
Cancel
Save