diff options
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/Makefile | 5 | ||||
-rw-r--r-- | crypto/memneq.c | 79 |
2 files changed, 54 insertions, 30 deletions
diff --git a/crypto/Makefile b/crypto/Makefile index 989c510da8cc..b29402a7b9b5 100644 --- a/crypto/Makefile +++ b/crypto/Makefile | |||
@@ -2,11 +2,6 @@ | |||
2 | # Cryptographic API | 2 | # Cryptographic API |
3 | # | 3 | # |
4 | 4 | ||
5 | # memneq MUST be built with -Os or -O0 to prevent early-return optimizations | ||
6 | # that will defeat memneq's actual purpose to prevent timing attacks. | ||
7 | CFLAGS_REMOVE_memneq.o := -O1 -O2 -O3 | ||
8 | CFLAGS_memneq.o := -Os | ||
9 | |||
10 | obj-$(CONFIG_CRYPTO) += crypto.o | 5 | obj-$(CONFIG_CRYPTO) += crypto.o |
11 | crypto-y := api.o cipher.o compress.o memneq.o | 6 | crypto-y := api.o cipher.o compress.o memneq.o |
12 | 7 | ||
diff --git a/crypto/memneq.c b/crypto/memneq.c index cd0162221c14..570f6f3401ce 100644 --- a/crypto/memneq.c +++ b/crypto/memneq.c | |||
@@ -72,6 +72,7 @@ __crypto_memneq_generic(const void *a, const void *b, size_t size) | |||
72 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) | 72 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) |
73 | while (size >= sizeof(unsigned long)) { | 73 | while (size >= sizeof(unsigned long)) { |
74 | neq |= *(unsigned long *)a ^ *(unsigned long *)b; | 74 | neq |= *(unsigned long *)a ^ *(unsigned long *)b; |
75 | OPTIMIZER_HIDE_VAR(neq); | ||
75 | a += sizeof(unsigned long); | 76 | a += sizeof(unsigned long); |
76 | b += sizeof(unsigned long); | 77 | b += sizeof(unsigned long); |
77 | size -= sizeof(unsigned long); | 78 | size -= sizeof(unsigned long); |
@@ -79,6 +80,7 @@ __crypto_memneq_generic(const void *a, const void *b, size_t size) | |||
79 | #endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ | 80 | #endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ |
80 | while (size > 0) { | 81 | while (size > 0) { |
81 | neq |= *(unsigned char *)a ^ *(unsigned char *)b; | 82 | neq |= *(unsigned char *)a ^ *(unsigned char *)b; |
83 | OPTIMIZER_HIDE_VAR(neq); | ||
82 | a += 1; | 84 | a += 1; |
83 | b += 1; | 85 | b += 1; |
84 | size -= 1; | 86 | size -= 1; |
@@ -89,33 +91,60 @@ __crypto_memneq_generic(const void *a, const void *b, size_t size) | |||
89 | /* Loop-free fast-path for frequently used 16-byte size */ | 91 | /* Loop-free fast-path for frequently used 16-byte size */ |
90 | static inline unsigned long __crypto_memneq_16(const void *a, const void *b) | 92 | static inline unsigned long __crypto_memneq_16(const void *a, const void *b) |
91 | { | 93 | { |
94 | unsigned long neq = 0; | ||
95 | |||
92 | #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | 96 | #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS |
93 | if (sizeof(unsigned long) == 8) | 97 | if (sizeof(unsigned long) == 8) { |
94 | return ((*(unsigned long *)(a) ^ *(unsigned long *)(b)) | 98 | neq |= *(unsigned long *)(a) ^ *(unsigned long *)(b); |
95 | | (*(unsigned long *)(a+8) ^ *(unsigned long *)(b+8))); | 99 | OPTIMIZER_HIDE_VAR(neq); |
96 | else if (sizeof(unsigned int) == 4) | 100 | neq |= *(unsigned long *)(a+8) ^ *(unsigned long *)(b+8); |
97 | return ((*(unsigned int *)(a) ^ *(unsigned int *)(b)) | 101 | OPTIMIZER_HIDE_VAR(neq); |
98 | | (*(unsigned int *)(a+4) ^ *(unsigned int *)(b+4)) | 102 | } else if (sizeof(unsigned int) == 4) { |
99 | | (*(unsigned int *)(a+8) ^ *(unsigned int *)(b+8)) | 103 | neq |= *(unsigned int *)(a) ^ *(unsigned int *)(b); |
100 | | (*(unsigned int *)(a+12) ^ *(unsigned int *)(b+12))); | 104 | OPTIMIZER_HIDE_VAR(neq); |
101 | else | 105 | neq |= *(unsigned int *)(a+4) ^ *(unsigned int *)(b+4); |
106 | OPTIMIZER_HIDE_VAR(neq); | ||
107 | neq |= *(unsigned int *)(a+8) ^ *(unsigned int *)(b+8); | ||
108 | OPTIMIZER_HIDE_VAR(neq); | ||
109 | neq |= *(unsigned int *)(a+12) ^ *(unsigned int *)(b+12); | ||
110 | OPTIMIZER_HIDE_VAR(neq); | ||
111 | } else { | ||
102 | #endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ | 112 | #endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ |
103 | return ((*(unsigned char *)(a) ^ *(unsigned char *)(b)) | 113 | neq |= *(unsigned char *)(a) ^ *(unsigned char *)(b); |
104 | | (*(unsigned char *)(a+1) ^ *(unsigned char *)(b+1)) | 114 | OPTIMIZER_HIDE_VAR(neq); |
105 | | (*(unsigned char *)(a+2) ^ *(unsigned char *)(b+2)) | 115 | neq |= *(unsigned char *)(a+1) ^ *(unsigned char *)(b+1); |
106 | | (*(unsigned char *)(a+3) ^ *(unsigned char *)(b+3)) | 116 | OPTIMIZER_HIDE_VAR(neq); |
107 | | (*(unsigned char *)(a+4) ^ *(unsigned char *)(b+4)) | 117 | neq |= *(unsigned char *)(a+2) ^ *(unsigned char *)(b+2); |
108 | | (*(unsigned char *)(a+5) ^ *(unsigned char *)(b+5)) | 118 | OPTIMIZER_HIDE_VAR(neq); |
109 | | (*(unsigned char *)(a+6) ^ *(unsigned char *)(b+6)) | 119 | neq |= *(unsigned char *)(a+3) ^ *(unsigned char *)(b+3); |
110 | | (*(unsigned char *)(a+7) ^ *(unsigned char *)(b+7)) | 120 | OPTIMIZER_HIDE_VAR(neq); |
111 | | (*(unsigned char *)(a+8) ^ *(unsigned char *)(b+8)) | 121 | neq |= *(unsigned char *)(a+4) ^ *(unsigned char *)(b+4); |
112 | | (*(unsigned char *)(a+9) ^ *(unsigned char *)(b+9)) | 122 | OPTIMIZER_HIDE_VAR(neq); |
113 | | (*(unsigned char *)(a+10) ^ *(unsigned char *)(b+10)) | 123 | neq |= *(unsigned char *)(a+5) ^ *(unsigned char *)(b+5); |
114 | | (*(unsigned char *)(a+11) ^ *(unsigned char *)(b+11)) | 124 | OPTIMIZER_HIDE_VAR(neq); |
115 | | (*(unsigned char *)(a+12) ^ *(unsigned char *)(b+12)) | 125 | neq |= *(unsigned char *)(a+6) ^ *(unsigned char *)(b+6); |
116 | | (*(unsigned char *)(a+13) ^ *(unsigned char *)(b+13)) | 126 | OPTIMIZER_HIDE_VAR(neq); |
117 | | (*(unsigned char *)(a+14) ^ *(unsigned char *)(b+14)) | 127 | neq |= *(unsigned char *)(a+7) ^ *(unsigned char *)(b+7); |
118 | | (*(unsigned char *)(a+15) ^ *(unsigned char *)(b+15))); | 128 | OPTIMIZER_HIDE_VAR(neq); |
129 | neq |= *(unsigned char *)(a+8) ^ *(unsigned char *)(b+8); | ||
130 | OPTIMIZER_HIDE_VAR(neq); | ||
131 | neq |= *(unsigned char *)(a+9) ^ *(unsigned char *)(b+9); | ||
132 | OPTIMIZER_HIDE_VAR(neq); | ||
133 | neq |= *(unsigned char *)(a+10) ^ *(unsigned char *)(b+10); | ||
134 | OPTIMIZER_HIDE_VAR(neq); | ||
135 | neq |= *(unsigned char *)(a+11) ^ *(unsigned char *)(b+11); | ||
136 | OPTIMIZER_HIDE_VAR(neq); | ||
137 | neq |= *(unsigned char *)(a+12) ^ *(unsigned char *)(b+12); | ||
138 | OPTIMIZER_HIDE_VAR(neq); | ||
139 | neq |= *(unsigned char *)(a+13) ^ *(unsigned char *)(b+13); | ||
140 | OPTIMIZER_HIDE_VAR(neq); | ||
141 | neq |= *(unsigned char *)(a+14) ^ *(unsigned char *)(b+14); | ||
142 | OPTIMIZER_HIDE_VAR(neq); | ||
143 | neq |= *(unsigned char *)(a+15) ^ *(unsigned char *)(b+15); | ||
144 | OPTIMIZER_HIDE_VAR(neq); | ||
145 | } | ||
146 | |||
147 | return neq; | ||
119 | } | 148 | } |
120 | 149 | ||
121 | /* Compare two areas of memory without leaking timing information, | 150 | /* Compare two areas of memory without leaking timing information, |