diff options
author | matthew <> | 2014-06-13 02:12:17 +0000 |
---|---|---|
committer | matthew <> | 2014-06-13 02:12:17 +0000 |
commit | cc594d5ff9b7bb08404d34d62287ee1dfd6b8332 (patch) | |
tree | 228054f338d1a5a8d53b4b58798bd55801ab2ce2 | |
parent | 5a1fd238ffb5612e4dd1965f694b7f04ab0d5ecb (diff) | |
download | openbsd-cc594d5ff9b7bb08404d34d62287ee1dfd6b8332.tar.gz openbsd-cc594d5ff9b7bb08404d34d62287ee1dfd6b8332.tar.bz2 openbsd-cc594d5ff9b7bb08404d34d62287ee1dfd6b8332.zip |
Add timingsafe_memcmp().
ok deraadt, jmc, tedu
-rw-r--r-- | src/lib/libc/string/Makefile.inc | 11 | ||||
-rw-r--r-- | src/lib/libc/string/bcmp.3 | 31 | ||||
-rw-r--r-- | src/lib/libc/string/memcmp.3 | 5 | ||||
-rw-r--r-- | src/lib/libc/string/timingsafe_bcmp.3 | 92 | ||||
-rw-r--r-- | src/lib/libc/string/timingsafe_memcmp.c | 46 | ||||
-rw-r--r-- | src/regress/lib/libc/timingsafe/timingsafe.c | 6 |
6 files changed, 153 insertions, 38 deletions
diff --git a/src/lib/libc/string/Makefile.inc b/src/lib/libc/string/Makefile.inc index 1f6d756182..a293219058 100644 --- a/src/lib/libc/string/Makefile.inc +++ b/src/lib/libc/string/Makefile.inc | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: Makefile.inc,v 1.34 2014/03/23 23:16:48 tedu Exp $ | 1 | # $OpenBSD: Makefile.inc,v 1.35 2014/06/13 02:12:17 matthew Exp $ |
2 | 2 | ||
3 | # string sources | 3 | # string sources |
4 | .PATH: ${LIBCSRCDIR}/arch/${MACHINE_CPU}/string ${LIBCSRCDIR}/string | 4 | .PATH: ${LIBCSRCDIR}/arch/${MACHINE_CPU}/string ${LIBCSRCDIR}/string |
@@ -7,11 +7,11 @@ SRCS+= explicit_bzero.c memccpy.c memmem.c memrchr.c stpcpy.c stpncpy.c \ | |||
7 | strcasecmp.c strcasestr.c strcoll.c strdup.c \ | 7 | strcasecmp.c strcasestr.c strcoll.c strdup.c \ |
8 | strerror.c strerror_r.c strlcat.c strmode.c strndup.c strnlen.c \ | 8 | strerror.c strerror_r.c strlcat.c strmode.c strndup.c strnlen.c \ |
9 | strsignal.c strtok.c strxfrm.c \ | 9 | strsignal.c strtok.c strxfrm.c \ |
10 | timingsafe_bcmp.c timingsafe_memcmp.c \ | ||
10 | wcscat.c wcschr.c wcscmp.c wcscpy.c wcscspn.c wcslcat.c wcslcpy.c \ | 11 | wcscat.c wcschr.c wcscmp.c wcscpy.c wcscspn.c wcslcat.c wcslcpy.c \ |
11 | wcslen.c wcsncat.c wcsncmp.c wcsncpy.c wcspbrk.c wcsrchr.c wcsspn.c \ | 12 | wcslen.c wcsncat.c wcsncmp.c wcsncpy.c wcspbrk.c wcsrchr.c wcsspn.c \ |
12 | wcsstr.c wcstok.c wcswcs.c wcswidth.c wmemchr.c wmemcmp.c wmemcpy.c \ | 13 | wcsstr.c wcstok.c wcswcs.c wcswidth.c wmemchr.c wmemcmp.c wmemcpy.c \ |
13 | wmemmove.c wmemset.c wcsdup.c \ | 14 | wmemmove.c wmemset.c wcsdup.c wcscasecmp.c |
14 | timingsafe_bcmp.c wcscasecmp.c | ||
15 | 15 | ||
16 | # machine-dependent net sources | 16 | # machine-dependent net sources |
17 | # m-d Makefile.inc must include sources for: | 17 | # m-d Makefile.inc must include sources for: |
@@ -149,7 +149,8 @@ MAN+= bcmp.3 bcopy.3 bstring.3 bzero.3 ffs.3 memccpy.3 memchr.3 \ | |||
149 | strcat.3 strchr.3 strcmp.3 strcoll.3 strcpy.3 strcspn.3 strdup.3 \ | 149 | strcat.3 strchr.3 strcmp.3 strcoll.3 strcpy.3 strcspn.3 strdup.3 \ |
150 | strerror.3 string.3 strlen.3 strmode.3 strncat.3 strncpy.3 strpbrk.3 \ | 150 | strerror.3 string.3 strlen.3 strmode.3 strncat.3 strncpy.3 strpbrk.3 \ |
151 | strrchr.3 strsep.3 strsignal.3 strspn.3 strstr.3 strtok.3 strxfrm.3 \ | 151 | strrchr.3 strsep.3 strsignal.3 strspn.3 strstr.3 strtok.3 strxfrm.3 \ |
152 | swab.3 strlcpy.3 wcscasecmp.3 wcscat.3 wcschr.3 wcscmp.3 wcscpy.3 \ | 152 | swab.3 strlcpy.3 timingsafe_bcmp.3 \ |
153 | wcscasecmp.3 wcscat.3 wcschr.3 wcscmp.3 wcscpy.3 \ | ||
153 | wcscspn.3 wcsdup.3 wcslcpy.3 wcslen.3 wcspbrk.3 wcsrchr.3 wcsspn.3 \ | 154 | wcscspn.3 wcsdup.3 wcslcpy.3 wcslen.3 wcspbrk.3 wcsrchr.3 wcsspn.3 \ |
154 | wcsstr.3 wcstok.3 wcswidth.3 wmemchr.3 wmemcmp.3 wmemcpy.3 wmemmove.3 \ | 155 | wcsstr.3 wcstok.3 wcswidth.3 wmemchr.3 wmemcmp.3 wmemcpy.3 wmemmove.3 \ |
155 | wmemset.3 | 156 | wmemset.3 |
@@ -167,9 +168,9 @@ MLINKS+=strlen.3 strnlen.3 | |||
167 | MLINKS+=strstr.3 strcasestr.3 | 168 | MLINKS+=strstr.3 strcasestr.3 |
168 | MLINKS+=strtok.3 strtok_r.3 | 169 | MLINKS+=strtok.3 strtok_r.3 |
169 | MLINKS+=strerror.3 strerror_r.3 | 170 | MLINKS+=strerror.3 strerror_r.3 |
171 | MLINKS+=timingsafe_bcmp.3 timingsafe_memcmp.3 | ||
170 | MLINKS+=wcscasecmp.3 wcsncasecmp.3 | 172 | MLINKS+=wcscasecmp.3 wcsncasecmp.3 |
171 | MLINKS+=wcscat.3 wcsncat.3 | 173 | MLINKS+=wcscat.3 wcsncat.3 |
172 | MLINKS+=wcscmp.3 wcsncmp.3 | 174 | MLINKS+=wcscmp.3 wcsncmp.3 |
173 | MLINKS+=wcscpy.3 wcsncpy.3 | 175 | MLINKS+=wcscpy.3 wcsncpy.3 |
174 | MLINKS+=wcslcpy.3 wcslcat.3 | 176 | MLINKS+=wcslcpy.3 wcslcat.3 |
175 | MLINKS+=bcmp.3 timingsafe_bcmp.3 | ||
diff --git a/src/lib/libc/string/bcmp.3 b/src/lib/libc/string/bcmp.3 index 52584b4b83..720a8bf304 100644 --- a/src/lib/libc/string/bcmp.3 +++ b/src/lib/libc/string/bcmp.3 | |||
@@ -27,21 +27,18 @@ | |||
27 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 27 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
28 | .\" SUCH DAMAGE. | 28 | .\" SUCH DAMAGE. |
29 | .\" | 29 | .\" |
30 | .\" $OpenBSD: bcmp.3,v 1.10 2013/06/05 03:39:23 tedu Exp $ | 30 | .\" $OpenBSD: bcmp.3,v 1.11 2014/06/13 02:12:17 matthew Exp $ |
31 | .\" | 31 | .\" |
32 | .Dd $Mdocdate: June 5 2013 $ | 32 | .Dd $Mdocdate: June 13 2014 $ |
33 | .Dt BCMP 3 | 33 | .Dt BCMP 3 |
34 | .Os | 34 | .Os |
35 | .Sh NAME | 35 | .Sh NAME |
36 | .Nm bcmp , | 36 | .Nm bcmp |
37 | .Nm timingsafe_bcmp | ||
38 | .Nd compare byte string | 37 | .Nd compare byte string |
39 | .Sh SYNOPSIS | 38 | .Sh SYNOPSIS |
40 | .In string.h | 39 | .In string.h |
41 | .Ft int | 40 | .Ft int |
42 | .Fn bcmp "const void *b1" "const void *b2" "size_t len" | 41 | .Fn bcmp "const void *b1" "const void *b2" "size_t len" |
43 | .Ft int | ||
44 | .Fn timingsafe_bcmp "const void *b1" "const void *b2" "size_t len" | ||
45 | .Sh DESCRIPTION | 42 | .Sh DESCRIPTION |
46 | The | 43 | The |
47 | .Fn bcmp | 44 | .Fn bcmp |
@@ -56,33 +53,15 @@ bytes long. | |||
56 | Zero-length strings are always identical. | 53 | Zero-length strings are always identical. |
57 | .Pp | 54 | .Pp |
58 | The strings may overlap. | 55 | The strings may overlap. |
59 | .Pp | ||
60 | The | ||
61 | .Fn timingsafe_bcmp | ||
62 | function has the same semantics as | ||
63 | .Fn bcmp , | ||
64 | but its running time is independent of the contents of | ||
65 | .Fa b1 | ||
66 | and | ||
67 | .Fa b2 , | ||
68 | making it safe to use for comparing secret values such as cryptographic MACs. | ||
69 | In contrast, | ||
70 | .Fn bcmp | ||
71 | returns after finding the first differing byte, | ||
72 | making it vulnerable to timing attacks. | ||
73 | .Sh SEE ALSO | 56 | .Sh SEE ALSO |
74 | .Xr memcmp 3 , | 57 | .Xr memcmp 3 , |
75 | .Xr strcasecmp 3 , | 58 | .Xr strcasecmp 3 , |
76 | .Xr strcmp 3 , | 59 | .Xr strcmp 3 , |
77 | .Xr strcoll 3 , | 60 | .Xr strcoll 3 , |
78 | .Xr strxfrm 3 | 61 | .Xr strxfrm 3 , |
62 | .Xr timingsafe_bcmp 3 | ||
79 | .Sh HISTORY | 63 | .Sh HISTORY |
80 | The | 64 | The |
81 | .Fn bcmp | 65 | .Fn bcmp |
82 | function first appeared in | 66 | function first appeared in |
83 | .Bx 4.2 . | 67 | .Bx 4.2 . |
84 | .Pp | ||
85 | The | ||
86 | .Fn timingsafe_bcmp | ||
87 | function first appeared in | ||
88 | .Ox 4.9 . | ||
diff --git a/src/lib/libc/string/memcmp.3 b/src/lib/libc/string/memcmp.3 index ebd838825a..25d308e617 100644 --- a/src/lib/libc/string/memcmp.3 +++ b/src/lib/libc/string/memcmp.3 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: memcmp.3,v 1.8 2013/06/05 03:39:23 tedu Exp $ | 1 | .\" $OpenBSD: memcmp.3,v 1.9 2014/06/13 02:12:17 matthew Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Copyright (c) 1990, 1991 The Regents of the University of California. | 3 | .\" Copyright (c) 1990, 1991 The Regents of the University of California. |
4 | .\" All rights reserved. | 4 | .\" All rights reserved. |
@@ -31,7 +31,7 @@ | |||
31 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 31 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | .\" SUCH DAMAGE. | 32 | .\" SUCH DAMAGE. |
33 | .\" | 33 | .\" |
34 | .Dd $Mdocdate: June 5 2013 $ | 34 | .Dd $Mdocdate: June 13 2014 $ |
35 | .Dt MEMCMP 3 | 35 | .Dt MEMCMP 3 |
36 | .Os | 36 | .Os |
37 | .Sh NAME | 37 | .Sh NAME |
@@ -70,6 +70,7 @@ Zero-length strings are always identical. | |||
70 | .Xr strcmp 3 , | 70 | .Xr strcmp 3 , |
71 | .Xr strcoll 3 , | 71 | .Xr strcoll 3 , |
72 | .Xr strxfrm 3 , | 72 | .Xr strxfrm 3 , |
73 | .Xr timingsafe_memcmp 3 , | ||
73 | .Xr wmemcmp 3 | 74 | .Xr wmemcmp 3 |
74 | .Sh STANDARDS | 75 | .Sh STANDARDS |
75 | The | 76 | The |
diff --git a/src/lib/libc/string/timingsafe_bcmp.3 b/src/lib/libc/string/timingsafe_bcmp.3 new file mode 100644 index 0000000000..0886731ce7 --- /dev/null +++ b/src/lib/libc/string/timingsafe_bcmp.3 | |||
@@ -0,0 +1,92 @@ | |||
1 | .\" $OpenBSD: timingsafe_bcmp.3,v 1.1 2014/06/13 02:12:17 matthew Exp $ | ||
2 | .\" | ||
3 | .\" Copyright (c) 2014 Google Inc. | ||
4 | .\" | ||
5 | .\" Permission to use, copy, modify, and distribute this software for any | ||
6 | .\" purpose with or without fee is hereby granted, provided that the above | ||
7 | .\" copyright notice and this permission notice appear in all copies. | ||
8 | .\" | ||
9 | .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | .Dd $Mdocdate: June 13 2014 $ | ||
17 | .Dt TIMINGSAFE_BCMP 3 | ||
18 | .Os | ||
19 | .Sh NAME | ||
20 | .Nm timingsafe_bcmp , | ||
21 | .Nm timingsafe_memcmp | ||
22 | .Nd timing-safe byte sequence comparisons | ||
23 | .Sh SYNOPSIS | ||
24 | .In string.h | ||
25 | .Ft int | ||
26 | .Fn timingsafe_bcmp "const void *b1" "const void *b2" "size_t len" | ||
27 | .Ft int | ||
28 | .Fn timingsafe_memcmp "const void *b1" "const void *b2" "size_t len" | ||
29 | .Sh DESCRIPTION | ||
30 | The | ||
31 | .Fn timingsafe_bcmp | ||
32 | and | ||
33 | .Fn timingsafe_memcmp | ||
34 | functions lexicographically compare the first | ||
35 | .Fa len | ||
36 | bytes (each interpreted as an | ||
37 | .Vt unsigned char ) | ||
38 | pointed to by | ||
39 | .Fa b1 | ||
40 | and | ||
41 | .Fa b2 . | ||
42 | .Pp | ||
43 | Additionally, their running times are independent of the byte sequences compared, | ||
44 | making them safe to use for comparing secret values such as cryptographic MACs. | ||
45 | In contrast, | ||
46 | .Xr bcmp 3 | ||
47 | and | ||
48 | .Xr memcmp 3 | ||
49 | may short-circuit after finding the first differing byte. | ||
50 | .Sh RETURN VALUES | ||
51 | The | ||
52 | .Fn timingsafe_bcmp | ||
53 | function returns 0 or 1 if the byte sequence pointed to by | ||
54 | .Fa b1 | ||
55 | compares equal to or not equal to (respectively) | ||
56 | the byte sequence pointed to by | ||
57 | .Fa b2 . | ||
58 | .Pp | ||
59 | The | ||
60 | .Fn timingsafe_memcmp | ||
61 | function returns \-1, 0, or 1 if the byte sequence pointed to by | ||
62 | .Fa b1 | ||
63 | compares less than, equal to, or greater than (respectively) | ||
64 | the byte sequence pointed to by | ||
65 | .Fa b2 . | ||
66 | .Pp | ||
67 | Note that these return values are compatible with, but stricter than, | ||
68 | the ones specified for | ||
69 | .Xr bcmp 3 | ||
70 | and | ||
71 | .Xr memcmp 3 . | ||
72 | .Sh SEE ALSO | ||
73 | .Xr bcmp 3 , | ||
74 | .Xr memcmp 3 | ||
75 | .Sh STANDARDS | ||
76 | The | ||
77 | .Fn timingsafe_bcmp | ||
78 | and | ||
79 | .Fn timingsafe_memcmp | ||
80 | functions are | ||
81 | .Ox | ||
82 | extensions. | ||
83 | .Sh HISTORY | ||
84 | The | ||
85 | .Fn timingsafe_bcmp | ||
86 | function first appeared in | ||
87 | .Ox 4.9 . | ||
88 | .Pp | ||
89 | The | ||
90 | .Fn timingsafe_memcmp | ||
91 | function first appeared in | ||
92 | .Ox 5.6 . | ||
diff --git a/src/lib/libc/string/timingsafe_memcmp.c b/src/lib/libc/string/timingsafe_memcmp.c new file mode 100644 index 0000000000..04e2ac5e20 --- /dev/null +++ b/src/lib/libc/string/timingsafe_memcmp.c | |||
@@ -0,0 +1,46 @@ | |||
1 | /* $OpenBSD: timingsafe_memcmp.c,v 1.1 2014/06/13 02:12:17 matthew Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2014 Google Inc. | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include <limits.h> | ||
19 | #include <string.h> | ||
20 | |||
21 | int | ||
22 | timingsafe_memcmp(const void *b1, const void *b2, size_t len) | ||
23 | { | ||
24 | const unsigned char *p1 = b1, *p2 = b2; | ||
25 | size_t i; | ||
26 | int res = 0, done = 0; | ||
27 | |||
28 | for (i = 0; i < len; i++) { | ||
29 | /* lt is -1 if p1[i] < p2[i]; else 0. */ | ||
30 | int lt = (p1[i] - p2[i]) >> CHAR_BIT; | ||
31 | |||
32 | /* gt is -1 if p1[i] > p2[i]; else 0. */ | ||
33 | int gt = (p2[i] - p1[i]) >> CHAR_BIT; | ||
34 | |||
35 | /* cmp is 1 if p1[i] > p2[i]; -1 if p1[i] < p2[i]; else 0. */ | ||
36 | int cmp = lt - gt; | ||
37 | |||
38 | /* set res = cmp if !done. */ | ||
39 | res |= cmp & ~done; | ||
40 | |||
41 | /* set done if p1[i] != p2[i]. */ | ||
42 | done |= lt | gt; | ||
43 | } | ||
44 | |||
45 | return (res); | ||
46 | } | ||
diff --git a/src/regress/lib/libc/timingsafe/timingsafe.c b/src/regress/lib/libc/timingsafe/timingsafe.c index 9ecac93c09..e7807db258 100644 --- a/src/regress/lib/libc/timingsafe/timingsafe.c +++ b/src/regress/lib/libc/timingsafe/timingsafe.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: timingsafe.c,v 1.1 2014/06/13 01:55:02 matthew Exp $ */ | 1 | /* $OpenBSD: timingsafe.c,v 1.2 2014/06/13 02:12:17 matthew Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2014 Google Inc. | 3 | * Copyright (c) 2014 Google Inc. |
4 | * | 4 | * |
@@ -42,21 +42,17 @@ check() | |||
42 | /* Check for reflexivity. */ | 42 | /* Check for reflexivity. */ |
43 | ASSERT_EQ(0, timingsafe_bcmp(bufone, bufone, N)); | 43 | ASSERT_EQ(0, timingsafe_bcmp(bufone, bufone, N)); |
44 | ASSERT_EQ(0, timingsafe_bcmp(buftwo, buftwo, N)); | 44 | ASSERT_EQ(0, timingsafe_bcmp(buftwo, buftwo, N)); |
45 | #if notyet | ||
46 | ASSERT_EQ(0, timingsafe_memcmp(bufone, bufone, N)); | 45 | ASSERT_EQ(0, timingsafe_memcmp(bufone, bufone, N)); |
47 | ASSERT_EQ(0, timingsafe_memcmp(buftwo, buftwo, N)); | 46 | ASSERT_EQ(0, timingsafe_memcmp(buftwo, buftwo, N)); |
48 | #endif | ||
49 | 47 | ||
50 | /* Check that timingsafe_bcmp returns 0 iff memcmp returns 0. */ | 48 | /* Check that timingsafe_bcmp returns 0 iff memcmp returns 0. */ |
51 | ASSERT_EQ(cmp == 0, timingsafe_bcmp(bufone, buftwo, N) == 0); | 49 | ASSERT_EQ(cmp == 0, timingsafe_bcmp(bufone, buftwo, N) == 0); |
52 | 50 | ||
53 | #if notyet | ||
54 | /* Check that timingsafe_memcmp returns cmp... */ | 51 | /* Check that timingsafe_memcmp returns cmp... */ |
55 | ASSERT_EQ(cmp, timingsafe_memcmp(bufone, buftwo, N)); | 52 | ASSERT_EQ(cmp, timingsafe_memcmp(bufone, buftwo, N)); |
56 | 53 | ||
57 | /* ... or -cmp if the argument order is swapped. */ | 54 | /* ... or -cmp if the argument order is swapped. */ |
58 | ASSERT_EQ(-cmp, timingsafe_memcmp(buftwo, bufone, N)); | 55 | ASSERT_EQ(-cmp, timingsafe_memcmp(buftwo, bufone, N)); |
59 | #endif | ||
60 | } | 56 | } |
61 | 57 | ||
62 | int | 58 | int |