Add GOST R 34.11-94 to nettle_hashes
[gd/nettle] / fat-x86_64.c
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 "memxor.h"
47 #include "fat-setup.h"
48
49 void _nettle_cpuid (uint32_t input, uint32_t regs[4]);
50
51 struct x86_features
52 {
53   enum x86_vendor { X86_OTHER, X86_INTEL, X86_AMD } vendor;
54   int have_aesni;
55   int have_sha_ni;
56 };
57
58 #define SKIP(s, slen, literal, llen)                            \
59   (((slen) >= (llen) && memcmp ((s), (literal), llen) == 0)     \
60    ? ((slen) -= (llen), (s) += (llen), 1) : 0)
61 #define MATCH(s, slen, literal, llen)                           \
62   ((slen) == (llen) && memcmp ((s), (literal), llen) == 0)
63
64 static void
65 get_x86_features (struct x86_features *features)
66 {
67   const char *s;
68   features->vendor = X86_OTHER;
69   features->have_aesni = 0;
70   features->have_sha_ni = 0;
71
72   s = secure_getenv (ENV_OVERRIDE);
73   if (s)
74     for (;;)
75       {
76         const char *sep = strchr (s, ',');
77         size_t length = sep ? (size_t) (sep - s) : strlen(s);
78
79         if (SKIP (s, length, "vendor:", 7))
80           {
81             if (MATCH(s, length, "intel", 5))
82               features->vendor = X86_INTEL;
83             else if (MATCH(s, length, "amd", 3))
84               features->vendor = X86_AMD;
85             
86           }
87         else if (MATCH (s, length, "aesni", 5))
88           features->have_aesni = 1;
89         else if (MATCH (s, length, "sha_ni", 6))
90           features->have_sha_ni = 1;
91         if (!sep)
92           break;
93         s = sep + 1;
94       }
95   else
96     {
97       uint32_t cpuid_data[4];
98       _nettle_cpuid (0, cpuid_data);
99       if (memcmp (cpuid_data + 1, "Genu" "ntel" "ineI", 12) == 0)
100         features->vendor = X86_INTEL;
101       else if (memcmp (cpuid_data + 1, "Auth" "cAMD" "enti", 12) == 0)
102         features->vendor = X86_AMD;
103
104       _nettle_cpuid (1, cpuid_data);
105       if (cpuid_data[2] & 0x02000000)
106        features->have_aesni = 1;
107
108       _nettle_cpuid (7, cpuid_data);
109       if (cpuid_data[1] & 0x20000000)
110        features->have_sha_ni = 1;
111     }
112 }
113
114 DECLARE_FAT_FUNC(_nettle_aes_encrypt, aes_crypt_internal_func)
115 DECLARE_FAT_FUNC_VAR(aes_encrypt, aes_crypt_internal_func, x86_64)
116 DECLARE_FAT_FUNC_VAR(aes_encrypt, aes_crypt_internal_func, aesni)
117
118 DECLARE_FAT_FUNC(_nettle_aes_decrypt, aes_crypt_internal_func)
119 DECLARE_FAT_FUNC_VAR(aes_decrypt, aes_crypt_internal_func, x86_64)
120 DECLARE_FAT_FUNC_VAR(aes_decrypt, aes_crypt_internal_func, aesni)
121
122 DECLARE_FAT_FUNC(nettle_memxor, memxor_func)
123 DECLARE_FAT_FUNC_VAR(memxor, memxor_func, x86_64)
124 DECLARE_FAT_FUNC_VAR(memxor, memxor_func, sse2)
125
126 DECLARE_FAT_FUNC(nettle_sha1_compress, sha1_compress_func)
127 DECLARE_FAT_FUNC_VAR(sha1_compress, sha1_compress_func, x86_64)
128 DECLARE_FAT_FUNC_VAR(sha1_compress, sha1_compress_func, sha_ni)
129
130 DECLARE_FAT_FUNC(_nettle_sha256_compress, sha256_compress_func)
131 DECLARE_FAT_FUNC_VAR(sha256_compress, sha256_compress_func, x86_64)
132 DECLARE_FAT_FUNC_VAR(sha256_compress, sha256_compress_func, sha_ni)
133
134 /* This function should usually be called only once, at startup. But
135    it is idempotent, and on x86, pointer updates are atomic, so
136    there's no danger if it is called simultaneously from multiple
137    threads. */
138 static void CONSTRUCTOR
139 fat_init (void)
140 {
141   struct x86_features features;
142   int verbose;
143
144   /* FIXME: Replace all getenv calls by getenv_secure? */
145   verbose = getenv (ENV_VERBOSE) != NULL;
146   if (verbose)
147     fprintf (stderr, "libnettle: fat library initialization.\n");
148
149   get_x86_features (&features);
150   if (verbose)
151     {
152       const char * const vendor_names[3] =
153         { "other", "intel", "amd" };
154       fprintf (stderr, "libnettle: cpu features: vendor:%s%s%s\n",
155                vendor_names[features.vendor],
156                features.have_aesni ? ",aesni" : "",
157                features.have_sha_ni ? ",sha_ni" : "");
158     }
159   if (features.have_aesni)
160     {
161       if (verbose)
162         fprintf (stderr, "libnettle: using aes instructions.\n");
163       _nettle_aes_encrypt_vec = _nettle_aes_encrypt_aesni;
164       _nettle_aes_decrypt_vec = _nettle_aes_decrypt_aesni;
165     }
166   else
167     {
168       if (verbose)
169         fprintf (stderr, "libnettle: not using aes instructions.\n");
170       _nettle_aes_encrypt_vec = _nettle_aes_encrypt_x86_64;
171       _nettle_aes_decrypt_vec = _nettle_aes_decrypt_x86_64;
172     }
173
174   if (features.have_sha_ni)
175     {
176       if (verbose)
177         fprintf (stderr, "libnettle: using sha_ni instructions.\n");
178       nettle_sha1_compress_vec = _nettle_sha1_compress_sha_ni;
179       _nettle_sha256_compress_vec = _nettle_sha256_compress_sha_ni;
180     }
181   else
182     {
183       if (verbose)
184         fprintf (stderr, "libnettle: not using sha_ni instructions.\n");
185       nettle_sha1_compress_vec = _nettle_sha1_compress_x86_64;
186       _nettle_sha256_compress_vec = _nettle_sha256_compress_x86_64;
187     }
188   if (features.vendor == X86_INTEL)
189     {
190       if (verbose)
191         fprintf (stderr, "libnettle: intel SSE2 will be used for memxor.\n");
192       nettle_memxor_vec = _nettle_memxor_sse2;
193     }
194   else
195     {
196       if (verbose)
197         fprintf (stderr, "libnettle: intel SSE2 will not be used for memxor.\n");
198       nettle_memxor_vec = _nettle_memxor_x86_64;
199     }
200 }
201
202 DEFINE_FAT_FUNC(_nettle_aes_encrypt, void,
203                 (unsigned rounds, const uint32_t *keys,
204                  const struct aes_table *T,
205                  size_t length, uint8_t *dst,
206                  const uint8_t *src),
207                 (rounds, keys, T, length, dst, src))
208
209 DEFINE_FAT_FUNC(_nettle_aes_decrypt, void,
210                 (unsigned rounds, const uint32_t *keys,
211                  const struct aes_table *T,
212                  size_t length, uint8_t *dst,
213                  const uint8_t *src),
214                 (rounds, keys, T, length, dst, src))
215
216 DEFINE_FAT_FUNC(nettle_memxor, void *,
217                 (void *dst, const void *src, size_t n),
218                 (dst, src, n))
219
220 DEFINE_FAT_FUNC(nettle_sha1_compress, void,
221                 (uint32_t *state, const uint8_t *input),
222                 (state, input))
223
224 DEFINE_FAT_FUNC(_nettle_sha256_compress, void,
225                 (uint32_t *state, const uint8_t *input, const uint32_t *k),
226                 (state, input, k))