Line | Count | Source (jump to first uncovered line) |
1 | | /* fat-x86_64.c |
2 | | |
3 | | Copyright (C) 2015 Niels Möller |
4 | | |
5 | | This file is part of GNU Nettle. |
6 | | |
7 | | GNU Nettle is free software: you can redistribute it and/or |
8 | | modify it under the terms of either: |
9 | | |
10 | | * the GNU Lesser General Public License as published by the Free |
11 | | Software Foundation; either version 3 of the License, or (at your |
12 | | option) any later version. |
13 | | |
14 | | or |
15 | | |
16 | | * the GNU General Public License as published by the Free |
17 | | Software Foundation; either version 2 of the License, or (at your |
18 | | option) any later version. |
19 | | |
20 | | or both in parallel, as here. |
21 | | |
22 | | GNU Nettle is distributed in the hope that it will be useful, |
23 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
24 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
25 | | General Public License for more details. |
26 | | |
27 | | You should have received copies of the GNU General Public License and |
28 | | the GNU Lesser General Public License along with this program. If |
29 | | not, see http://www.gnu.org/licenses/. |
30 | | */ |
31 | | |
32 | | #define _GNU_SOURCE |
33 | | |
34 | | #if HAVE_CONFIG_H |
35 | | # include "config.h" |
36 | | #endif |
37 | | |
38 | | #include <assert.h> |
39 | | #include <stdio.h> |
40 | | #include <stdlib.h> |
41 | | #include <string.h> |
42 | | |
43 | | #include "nettle-types.h" |
44 | | |
45 | | #include "aes-internal.h" |
46 | | #include "ghash-internal.h" |
47 | | #include "memxor.h" |
48 | | #include "fat-setup.h" |
49 | | |
50 | | void _nettle_cpuid (uint32_t input, uint32_t regs[4]); |
51 | | |
52 | | struct x86_features |
53 | | { |
54 | | enum x86_vendor { X86_OTHER, X86_INTEL, X86_AMD } vendor; |
55 | | int have_aesni; |
56 | | int have_sha_ni; |
57 | | int have_pclmul; |
58 | | }; |
59 | | |
60 | | #define SKIP(s, slen, literal, llen) \ |
61 | 0 | (((slen) >= (llen) && memcmp ((s), (literal), llen) == 0) \ |
62 | 0 | ? ((slen) -= (llen), (s) += (llen), 1) : 0) |
63 | | #define MATCH(s, slen, literal, llen) \ |
64 | 0 | ((slen) == (llen) && memcmp ((s), (literal), llen) == 0) |
65 | | |
66 | | static void |
67 | | get_x86_features (struct x86_features *features) |
68 | 2 | { |
69 | 2 | const char *s; |
70 | 2 | features->vendor = X86_OTHER; |
71 | 2 | features->have_aesni = 0; |
72 | 2 | features->have_sha_ni = 0; |
73 | 2 | features->have_pclmul = 0; |
74 | | |
75 | 2 | s = secure_getenv (ENV_OVERRIDE); |
76 | 2 | if (s) |
77 | 0 | for (;;) |
78 | 0 | { |
79 | 0 | const char *sep = strchr (s, ','); |
80 | 0 | size_t length = sep ? (size_t) (sep - s) : strlen(s); |
81 | |
|
82 | 0 | if (SKIP (s, length, "vendor:", 7)) |
83 | 0 | { |
84 | 0 | if (MATCH(s, length, "intel", 5)) |
85 | 0 | features->vendor = X86_INTEL; |
86 | 0 | else if (MATCH(s, length, "amd", 3)) |
87 | 0 | features->vendor = X86_AMD; |
88 | | |
89 | 0 | } |
90 | 0 | else if (MATCH (s, length, "aesni", 5)) |
91 | 0 | features->have_aesni = 1; |
92 | 0 | else if (MATCH (s, length, "sha_ni", 6)) |
93 | 0 | features->have_sha_ni = 1; |
94 | 0 | else if (MATCH (s, length, "pclmul", 6)) |
95 | 0 | features->have_pclmul = 1; |
96 | 0 | if (!sep) |
97 | 0 | break; |
98 | 0 | s = sep + 1; |
99 | 0 | } |
100 | 2 | else |
101 | 2 | { |
102 | 2 | uint32_t cpuid_data[4]; |
103 | 2 | _nettle_cpuid (0, cpuid_data); |
104 | 2 | if (memcmp (cpuid_data + 1, "Genu" "ntel" "ineI", 12) == 0) |
105 | 0 | features->vendor = X86_INTEL; |
106 | 2 | else if (memcmp (cpuid_data + 1, "Auth" "cAMD" "enti", 12) == 0) |
107 | 2 | features->vendor = X86_AMD; |
108 | | |
109 | 2 | _nettle_cpuid (1, cpuid_data); |
110 | 2 | if (cpuid_data[2] & 0x2) |
111 | 2 | features->have_pclmul = 1; |
112 | 2 | if (cpuid_data[2] & 0x02000000) |
113 | 2 | features->have_aesni = 1; |
114 | | |
115 | 2 | _nettle_cpuid (7, cpuid_data); |
116 | 2 | if (cpuid_data[1] & 0x20000000) |
117 | 2 | features->have_sha_ni = 1; |
118 | 2 | } |
119 | 2 | } |
120 | | |
121 | | DECLARE_FAT_FUNC(nettle_aes128_encrypt, aes128_crypt_func) |
122 | | DECLARE_FAT_FUNC(nettle_aes128_decrypt, aes128_crypt_func) |
123 | | DECLARE_FAT_FUNC_VAR(aes128_encrypt, aes128_crypt_func, c) |
124 | | DECLARE_FAT_FUNC_VAR(aes128_encrypt, aes128_crypt_func, aesni) |
125 | | DECLARE_FAT_FUNC_VAR(aes128_decrypt, aes128_crypt_func, c) |
126 | | DECLARE_FAT_FUNC_VAR(aes128_decrypt, aes128_crypt_func, aesni) |
127 | | DECLARE_FAT_FUNC(nettle_aes192_encrypt, aes192_crypt_func) |
128 | | DECLARE_FAT_FUNC(nettle_aes192_decrypt, aes192_crypt_func) |
129 | | DECLARE_FAT_FUNC_VAR(aes192_encrypt, aes192_crypt_func, c) |
130 | | DECLARE_FAT_FUNC_VAR(aes192_encrypt, aes192_crypt_func, aesni) |
131 | | DECLARE_FAT_FUNC_VAR(aes192_decrypt, aes192_crypt_func, c) |
132 | | DECLARE_FAT_FUNC_VAR(aes192_decrypt, aes192_crypt_func, aesni) |
133 | | DECLARE_FAT_FUNC(nettle_aes256_encrypt, aes256_crypt_func) |
134 | | DECLARE_FAT_FUNC(nettle_aes256_decrypt, aes256_crypt_func) |
135 | | DECLARE_FAT_FUNC_VAR(aes256_encrypt, aes256_crypt_func, c) |
136 | | DECLARE_FAT_FUNC_VAR(aes256_encrypt, aes256_crypt_func, aesni) |
137 | | DECLARE_FAT_FUNC_VAR(aes256_decrypt, aes256_crypt_func, c) |
138 | | DECLARE_FAT_FUNC_VAR(aes256_decrypt, aes256_crypt_func, aesni) |
139 | | |
140 | | DECLARE_FAT_FUNC(nettle_cbc_aes128_encrypt, cbc_aes128_encrypt_func); |
141 | | DECLARE_FAT_FUNC_VAR(cbc_aes128_encrypt, cbc_aes128_encrypt_func, c); |
142 | | DECLARE_FAT_FUNC_VAR(cbc_aes128_encrypt, cbc_aes128_encrypt_func, aesni); |
143 | | DECLARE_FAT_FUNC(nettle_cbc_aes192_encrypt, cbc_aes192_encrypt_func); |
144 | | DECLARE_FAT_FUNC_VAR(cbc_aes192_encrypt, cbc_aes192_encrypt_func, c); |
145 | | DECLARE_FAT_FUNC_VAR(cbc_aes192_encrypt, cbc_aes192_encrypt_func, aesni); |
146 | | DECLARE_FAT_FUNC(nettle_cbc_aes256_encrypt, cbc_aes256_encrypt_func); |
147 | | DECLARE_FAT_FUNC_VAR(cbc_aes256_encrypt, cbc_aes256_encrypt_func, c); |
148 | | DECLARE_FAT_FUNC_VAR(cbc_aes256_encrypt, cbc_aes256_encrypt_func, aesni); |
149 | | |
150 | | DECLARE_FAT_FUNC(nettle_memxor, memxor_func) |
151 | | DECLARE_FAT_FUNC_VAR(memxor, memxor_func, x86_64) |
152 | | DECLARE_FAT_FUNC_VAR(memxor, memxor_func, sse2) |
153 | | |
154 | | DECLARE_FAT_FUNC(nettle_sha1_compress, sha1_compress_func) |
155 | | DECLARE_FAT_FUNC_VAR(sha1_compress, sha1_compress_func, x86_64) |
156 | | DECLARE_FAT_FUNC_VAR(sha1_compress, sha1_compress_func, sha_ni) |
157 | | |
158 | | DECLARE_FAT_FUNC(_nettle_sha256_compress_n, sha256_compress_n_func) |
159 | | DECLARE_FAT_FUNC_VAR(sha256_compress_n, sha256_compress_n_func, x86_64) |
160 | | DECLARE_FAT_FUNC_VAR(sha256_compress_n, sha256_compress_n_func, sha_ni) |
161 | | |
162 | | DECLARE_FAT_FUNC(_nettle_ghash_set_key, ghash_set_key_func) |
163 | | DECLARE_FAT_FUNC_VAR(ghash_set_key, ghash_set_key_func, c) |
164 | | DECLARE_FAT_FUNC_VAR(ghash_set_key, ghash_set_key_func, pclmul) |
165 | | |
166 | | DECLARE_FAT_FUNC(_nettle_ghash_update, ghash_update_func) |
167 | | DECLARE_FAT_FUNC_VAR(ghash_update, ghash_update_func, table) |
168 | | DECLARE_FAT_FUNC_VAR(ghash_update, ghash_update_func, pclmul) |
169 | | |
170 | | |
171 | | /* This function should usually be called only once, at startup. But |
172 | | it is idempotent, and on x86, pointer updates are atomic, so |
173 | | there's no danger if it is called simultaneously from multiple |
174 | | threads. */ |
175 | | static void CONSTRUCTOR |
176 | | fat_init (void) |
177 | 2 | { |
178 | 2 | struct x86_features features; |
179 | 2 | int verbose; |
180 | | |
181 | | /* FIXME: Replace all getenv calls by getenv_secure? */ |
182 | 2 | verbose = getenv (ENV_VERBOSE) != NULL; |
183 | 2 | if (verbose) |
184 | 0 | fprintf (stderr, "libnettle: fat library initialization.\n"); |
185 | | |
186 | 2 | get_x86_features (&features); |
187 | 2 | if (verbose) |
188 | 0 | { |
189 | 0 | const char * const vendor_names[3] = |
190 | 0 | { "other", "intel", "amd" }; |
191 | 0 | fprintf (stderr, "libnettle: cpu features: vendor:%s%s%s%s\n", |
192 | 0 | vendor_names[features.vendor], |
193 | 0 | features.have_aesni ? ",aesni" : "", |
194 | 0 | features.have_sha_ni ? ",sha_ni" : "", |
195 | 0 | features.have_pclmul ? ",pclmul" : ""); |
196 | 0 | } |
197 | 2 | if (features.have_aesni) |
198 | 2 | { |
199 | 2 | if (verbose) |
200 | 0 | fprintf (stderr, "libnettle: using aes instructions.\n"); |
201 | 2 | nettle_aes128_encrypt_vec = _nettle_aes128_encrypt_aesni; |
202 | 2 | nettle_aes128_decrypt_vec = _nettle_aes128_decrypt_aesni; |
203 | 2 | nettle_aes192_encrypt_vec = _nettle_aes192_encrypt_aesni; |
204 | 2 | nettle_aes192_decrypt_vec = _nettle_aes192_decrypt_aesni; |
205 | 2 | nettle_aes256_encrypt_vec = _nettle_aes256_encrypt_aesni; |
206 | 2 | nettle_aes256_decrypt_vec = _nettle_aes256_decrypt_aesni; |
207 | 2 | nettle_cbc_aes128_encrypt_vec = _nettle_cbc_aes128_encrypt_aesni; |
208 | 2 | nettle_cbc_aes192_encrypt_vec = _nettle_cbc_aes192_encrypt_aesni; |
209 | 2 | nettle_cbc_aes256_encrypt_vec = _nettle_cbc_aes256_encrypt_aesni; |
210 | 2 | } |
211 | 0 | else |
212 | 0 | { |
213 | 0 | if (verbose) |
214 | 0 | fprintf (stderr, "libnettle: not using aes instructions.\n"); |
215 | 0 | nettle_aes128_encrypt_vec = _nettle_aes128_encrypt_c; |
216 | 0 | nettle_aes128_decrypt_vec = _nettle_aes128_decrypt_c; |
217 | 0 | nettle_aes192_encrypt_vec = _nettle_aes192_encrypt_c; |
218 | 0 | nettle_aes192_decrypt_vec = _nettle_aes192_decrypt_c; |
219 | 0 | nettle_aes256_encrypt_vec = _nettle_aes256_encrypt_c; |
220 | 0 | nettle_aes256_decrypt_vec = _nettle_aes256_decrypt_c; |
221 | 0 | nettle_cbc_aes128_encrypt_vec = _nettle_cbc_aes128_encrypt_c; |
222 | 0 | nettle_cbc_aes192_encrypt_vec = _nettle_cbc_aes192_encrypt_c; |
223 | 0 | nettle_cbc_aes256_encrypt_vec = _nettle_cbc_aes256_encrypt_c; |
224 | 0 | } |
225 | | |
226 | 2 | if (features.have_sha_ni) |
227 | 2 | { |
228 | 2 | if (verbose) |
229 | 0 | fprintf (stderr, "libnettle: using sha_ni instructions.\n"); |
230 | 2 | nettle_sha1_compress_vec = _nettle_sha1_compress_sha_ni; |
231 | 2 | _nettle_sha256_compress_n_vec = _nettle_sha256_compress_n_sha_ni; |
232 | 2 | } |
233 | 0 | else |
234 | 0 | { |
235 | 0 | if (verbose) |
236 | 0 | fprintf (stderr, "libnettle: not using sha_ni instructions.\n"); |
237 | 0 | nettle_sha1_compress_vec = _nettle_sha1_compress_x86_64; |
238 | 0 | _nettle_sha256_compress_n_vec = _nettle_sha256_compress_n_x86_64; |
239 | 0 | } |
240 | | |
241 | 2 | if (features.have_pclmul) |
242 | 2 | { |
243 | 2 | if (verbose) |
244 | 0 | fprintf (stderr, "libnettle: using pclmulqdq instructions.\n"); |
245 | 2 | _nettle_ghash_set_key_vec = _nettle_ghash_set_key_pclmul; |
246 | 2 | _nettle_ghash_update_vec = _nettle_ghash_update_pclmul; |
247 | 2 | } |
248 | 0 | else |
249 | 0 | { |
250 | 0 | if (verbose) |
251 | 0 | fprintf (stderr, "libnettle: not using pclmulqdq instructions.\n"); |
252 | 0 | _nettle_ghash_set_key_vec = _nettle_ghash_set_key_c; |
253 | 0 | _nettle_ghash_update_vec = _nettle_ghash_update_table; |
254 | 0 | } |
255 | | |
256 | 2 | if (features.vendor == X86_INTEL) |
257 | 0 | { |
258 | 0 | if (verbose) |
259 | 0 | fprintf (stderr, "libnettle: intel SSE2 will be used for memxor.\n"); |
260 | 0 | nettle_memxor_vec = _nettle_memxor_sse2; |
261 | 0 | } |
262 | 2 | else |
263 | 2 | { |
264 | 2 | if (verbose) |
265 | 0 | fprintf (stderr, "libnettle: intel SSE2 will not be used for memxor.\n"); |
266 | 2 | nettle_memxor_vec = _nettle_memxor_x86_64; |
267 | 2 | } |
268 | 2 | } |
269 | | |
270 | | DEFINE_FAT_FUNC(nettle_aes128_encrypt, void, |
271 | | (const struct aes128_ctx *ctx, size_t length, |
272 | | uint8_t *dst,const uint8_t *src), |
273 | | (ctx, length, dst, src)) |
274 | | DEFINE_FAT_FUNC(nettle_aes128_decrypt, void, |
275 | | (const struct aes128_ctx *ctx, size_t length, |
276 | | uint8_t *dst,const uint8_t *src), |
277 | | (ctx, length, dst, src)) |
278 | | |
279 | | DEFINE_FAT_FUNC(nettle_aes192_encrypt, void, |
280 | | (const struct aes192_ctx *ctx, size_t length, |
281 | | uint8_t *dst,const uint8_t *src), |
282 | | (ctx, length, dst, src)) |
283 | | DEFINE_FAT_FUNC(nettle_aes192_decrypt, void, |
284 | | (const struct aes192_ctx *ctx, size_t length, |
285 | | uint8_t *dst,const uint8_t *src), |
286 | | (ctx, length, dst, src)) |
287 | | |
288 | | DEFINE_FAT_FUNC(nettle_aes256_encrypt, void, |
289 | | (const struct aes256_ctx *ctx, size_t length, |
290 | | uint8_t *dst,const uint8_t *src), |
291 | | (ctx, length, dst, src)) |
292 | | DEFINE_FAT_FUNC(nettle_aes256_decrypt, void, |
293 | | (const struct aes256_ctx *ctx, size_t length, |
294 | | uint8_t *dst,const uint8_t *src), |
295 | | (ctx, length, dst, src)) |
296 | | |
297 | | DEFINE_FAT_FUNC(nettle_cbc_aes128_encrypt, void, |
298 | | (const struct aes128_ctx *ctx, uint8_t *iv, |
299 | | size_t length, uint8_t *dst, const uint8_t *src), |
300 | | (ctx, iv, length, dst, src)) |
301 | | DEFINE_FAT_FUNC(nettle_cbc_aes192_encrypt, void, |
302 | | (const struct aes192_ctx *ctx, uint8_t *iv, |
303 | | size_t length, uint8_t *dst, const uint8_t *src), |
304 | | (ctx, iv, length, dst, src)) |
305 | | DEFINE_FAT_FUNC(nettle_cbc_aes256_encrypt, void, |
306 | | (const struct aes256_ctx *ctx, uint8_t *iv, |
307 | | size_t length, uint8_t *dst, const uint8_t *src), |
308 | | (ctx, iv, length, dst, src)) |
309 | | |
310 | | DEFINE_FAT_FUNC(nettle_memxor, void *, |
311 | | (void *dst, const void *src, size_t n), |
312 | | (dst, src, n)) |
313 | | |
314 | | DEFINE_FAT_FUNC(nettle_sha1_compress, void, |
315 | | (uint32_t *state, const uint8_t *input), |
316 | | (state, input)) |
317 | | |
318 | | DEFINE_FAT_FUNC(_nettle_sha256_compress_n, const uint8_t *, |
319 | | (uint32_t *state, const uint32_t *k, |
320 | | size_t blocks, const uint8_t *input), |
321 | | (state, k, blocks, input)) |
322 | | |
323 | | DEFINE_FAT_FUNC(_nettle_ghash_set_key, void, |
324 | | (struct gcm_key *ctx, const union nettle_block16 *key), |
325 | | (ctx, key)) |
326 | | DEFINE_FAT_FUNC(_nettle_ghash_update, const uint8_t *, |
327 | | (const struct gcm_key *ctx, union nettle_block16 *state, |
328 | | size_t blocks, const uint8_t *data), |
329 | | (ctx, state, blocks, data)) |