1156499d6e908f107501607ecb99c7a769d9e822
[platform/upstream/nettle.git] / fat-arm.c
1 /* fat-arm.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 #if HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <assert.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include "nettle-types.h"
42
43 #include "aes-internal.h"
44 #include "fat-setup.h"
45
46 struct arm_features
47 {
48   /* /proc/cpuinfo "CPU Architecture" doesn't correspond exactly to
49      ARM architecture version, but it's good enough for our purposes.
50      Will be set to 5, 6, 7 or 8. */
51   unsigned arch_version;
52   int have_neon;
53 };
54
55 #define SKIP(s, slen, literal, llen)                            \
56   (((slen) >= (llen) && memcmp ((s), (literal), llen) == 0)     \
57    ? ((slen) -= (llen), (s) += (llen), 1) : 0)
58 #define MATCH(s, slen, literal, llen)                           \
59   ((slen) == (llen) && memcmp ((s), (literal), llen) == 0)
60
61 static void
62 get_arm_features (struct arm_features *features)
63 {
64   const char *s;
65   features->arch_version = 5;
66   features->have_neon = 0;
67
68   s = secure_getenv (ENV_OVERRIDE);
69   if (s)
70     for (;;)
71       {
72         const char *sep = strchr (s, ',');
73         size_t length = sep ? (size_t) (sep - s) : strlen(s);
74
75         if (SKIP (s, length, "arch:", 5))
76           {
77             if (length == 1 && *s >= '0' && *s <= '9')
78               features->arch_version = *s - '0';
79           }
80         else if (MATCH (s, length, "neon", 4))
81           features->have_neon = 1;
82         if (!sep)
83           break;
84         s = sep + 1;
85       }
86   else
87     {
88       FILE *f;
89       char line[200];
90       int seen_arch = 0;
91       int seen_features = 0;
92
93       f = fopen ("/proc/cpuinfo", "r");
94       if (!f)
95         return;
96       while (seen_features + seen_arch < 2
97              && fgets (line, sizeof(line), f))
98         {
99           char *sep;
100           char *p;
101           sep = strchr (line, ':');
102           if (!sep)
103             continue;
104           for (p = sep; p - line > 0 && p[-1] == '\t'; p--)
105             ;
106
107           *p = '\0';
108           p = sep+1;
109
110           if (strcmp (line, "Features") == 0)
111             {
112               features->have_neon = (strstr (p, " neon ") != NULL);
113               seen_features = 1;
114             }
115           else if (strcmp (line, "CPU architecture") == 0)
116             {
117               /* Don't use strtol, since it's locale dependent. */
118               while (p[0] == ' ')
119                 p++;
120               if (p[0] > '5' && p[0] <= '9')
121                 features->arch_version = p[0] - '0';
122               else if (strcmp (p, "AArch64") == 0)
123                 features->arch_version = 8;
124               seen_arch = 1;
125             }
126         }
127       if (features->arch_version >= 8)
128         {
129           /* Neon is not required, and maybe not listed in feature flags */
130           features->have_neon = 1;
131         }
132       fclose (f);
133     }
134 }
135
136 DECLARE_FAT_FUNC(_nettle_aes_encrypt, aes_crypt_internal_func)
137 DECLARE_FAT_FUNC_VAR(aes_encrypt, aes_crypt_internal_func, arm)
138 DECLARE_FAT_FUNC_VAR(aes_encrypt, aes_crypt_internal_func, armv6)
139
140 DECLARE_FAT_FUNC(_nettle_aes_decrypt, aes_crypt_internal_func)
141 DECLARE_FAT_FUNC_VAR(aes_decrypt, aes_crypt_internal_func, arm)
142 DECLARE_FAT_FUNC_VAR(aes_decrypt, aes_crypt_internal_func, armv6)
143
144 DECLARE_FAT_FUNC(_nettle_salsa20_core, salsa20_core_func)
145 DECLARE_FAT_FUNC_VAR(salsa20_core, salsa20_core_func, c)
146 DECLARE_FAT_FUNC_VAR(salsa20_core, salsa20_core_func, neon)
147
148 DECLARE_FAT_FUNC(_nettle_sha1_compress, sha1_compress_func)
149 DECLARE_FAT_FUNC_VAR(sha1_compress, sha1_compress_func, c)
150 DECLARE_FAT_FUNC_VAR(sha1_compress, sha1_compress_func, armv6)
151
152 DECLARE_FAT_FUNC(_nettle_sha256_compress, sha256_compress_func)
153 DECLARE_FAT_FUNC_VAR(sha256_compress, sha256_compress_func, c)
154 DECLARE_FAT_FUNC_VAR(sha256_compress, sha256_compress_func, armv6)
155
156 DECLARE_FAT_FUNC(_nettle_sha512_compress, sha512_compress_func)
157 DECLARE_FAT_FUNC_VAR(sha512_compress, sha512_compress_func, c)
158 DECLARE_FAT_FUNC_VAR(sha512_compress, sha512_compress_func, neon)
159
160 DECLARE_FAT_FUNC(nettle_sha3_permute, sha3_permute_func)
161 DECLARE_FAT_FUNC_VAR(sha3_permute, sha3_permute_func, c)
162 DECLARE_FAT_FUNC_VAR(sha3_permute, sha3_permute_func, neon)
163
164 DECLARE_FAT_FUNC(_nettle_umac_nh, umac_nh_func)
165 DECLARE_FAT_FUNC_VAR(umac_nh, umac_nh_func, c);
166 DECLARE_FAT_FUNC_VAR(umac_nh, umac_nh_func, neon);
167
168 DECLARE_FAT_FUNC(_nettle_umac_nh_n, umac_nh_n_func)
169 DECLARE_FAT_FUNC_VAR(umac_nh_n, umac_nh_n_func, c);
170 DECLARE_FAT_FUNC_VAR(umac_nh_n, umac_nh_n_func, neon);
171
172 static void CONSTRUCTOR
173 fat_init (void)
174 {
175   struct arm_features features;
176   int verbose;
177
178   get_arm_features (&features);
179
180   verbose = getenv (ENV_VERBOSE) != NULL;
181   if (verbose)
182     fprintf (stderr, "libnettle: cpu features: arch:%d%s\n",
183              features.arch_version,
184              features.have_neon ? ",neon" : "");
185
186   if (features.arch_version >= 6)
187     {
188       if (verbose)
189         fprintf (stderr, "libnettle: enabling armv6 code.\n");
190       _nettle_aes_encrypt_vec = _nettle_aes_encrypt_armv6;
191       _nettle_aes_decrypt_vec = _nettle_aes_decrypt_armv6;
192       _nettle_sha1_compress_vec = _nettle_sha1_compress_armv6;
193       _nettle_sha256_compress_vec = _nettle_sha256_compress_armv6;
194     }
195   else
196     {
197       if (verbose)
198         fprintf (stderr, "libnettle: not enabling armv6 code.\n");
199       _nettle_aes_encrypt_vec = _nettle_aes_encrypt_arm;
200       _nettle_aes_decrypt_vec = _nettle_aes_decrypt_arm;
201       _nettle_sha1_compress_vec = _nettle_sha1_compress_c;
202       _nettle_sha256_compress_vec = _nettle_sha256_compress_c;
203     }
204   if (features.have_neon)
205     {
206       if (verbose)
207         fprintf (stderr, "libnettle: enabling neon code.\n");
208       _nettle_salsa20_core_vec = _nettle_salsa20_core_neon;
209       _nettle_sha512_compress_vec = _nettle_sha512_compress_neon;
210       nettle_sha3_permute_vec = _nettle_sha3_permute_neon;
211       _nettle_umac_nh_vec = _nettle_umac_nh_neon;
212       _nettle_umac_nh_n_vec = _nettle_umac_nh_n_neon;
213     }
214   else
215     {
216       if (verbose)
217         fprintf (stderr, "libnettle: not enabling neon code.\n");
218       _nettle_salsa20_core_vec = _nettle_salsa20_core_c;
219       _nettle_sha512_compress_vec = _nettle_sha512_compress_c;
220       nettle_sha3_permute_vec = _nettle_sha3_permute_c;
221       _nettle_umac_nh_vec = _nettle_umac_nh_c;
222       _nettle_umac_nh_n_vec = _nettle_umac_nh_n_c;
223     }
224 }
225   
226 DEFINE_FAT_FUNC(_nettle_aes_encrypt, void,
227                 (unsigned rounds, const uint32_t *keys,
228                  const struct aes_table *T,
229                  size_t length, uint8_t *dst,
230                  const uint8_t *src),
231                 (rounds, keys, T, length, dst, src))
232
233 DEFINE_FAT_FUNC(_nettle_aes_decrypt, void,
234                 (unsigned rounds, const uint32_t *keys,
235                  const struct aes_table *T,
236                  size_t length, uint8_t *dst,
237                  const uint8_t *src),
238                 (rounds, keys, T, length, dst, src))
239
240 DEFINE_FAT_FUNC(_nettle_salsa20_core, void,
241                 (uint32_t *dst, const uint32_t *src, unsigned rounds),
242                 (dst, src, rounds))
243
244 DEFINE_FAT_FUNC(_nettle_sha1_compress, void,
245                 (uint32_t *state, const uint8_t *input),
246                 (state, input))
247
248 DEFINE_FAT_FUNC(_nettle_sha256_compress, void,
249                 (uint32_t *state, const uint8_t *input, const uint32_t *k),
250                 (state, input, k))
251
252 DEFINE_FAT_FUNC(_nettle_sha512_compress, void,
253                 (uint64_t *state, const uint8_t *input, const uint64_t *k),
254                 (state, input, k))
255
256 DEFINE_FAT_FUNC(nettle_sha3_permute, void,
257                 (struct sha3_state *state), (state))
258
259 DEFINE_FAT_FUNC(_nettle_umac_nh, uint64_t,
260                 (const uint32_t *key, unsigned length, const uint8_t *msg),
261                 (key, length, msg))
262
263 DEFINE_FAT_FUNC(_nettle_umac_nh_n, void,
264                 (uint64_t *out, unsigned n, const uint32_t *key,
265                  unsigned length, const uint8_t *msg),
266                 (out, n, key, length, msg))
267