summaryrefslogtreecommitdiff
path: root/fat-arm.c
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2015-01-19 21:34:27 +0100
committerNiels Möller <nisse@lysator.liu.se>2015-01-19 21:34:27 +0100
commit3d0fd448340a79a73c8937c2e9aa0b828a81aa83 (patch)
tree1a2af280309b6e0d3b43edbaefa75dec882c9ec3 /fat-arm.c
parentb6939cf5b97aaa8e662e0a9b0083657937e25064 (diff)
downloadnettle-3d0fd448340a79a73c8937c2e9aa0b828a81aa83.tar.gz
Initial fat library support for arm.
Diffstat (limited to 'fat-arm.c')
-rw-r--r--fat-arm.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/fat-arm.c b/fat-arm.c
new file mode 100644
index 00000000..9ddf582f
--- /dev/null
+++ b/fat-arm.c
@@ -0,0 +1,164 @@
+/* fat-arm.c
+
+ Copyright (C) 2015 Niels Möller
+
+ This file is part of GNU Nettle.
+
+ GNU Nettle is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+
+ GNU Nettle is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see http://www.gnu.org/licenses/.
+*/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "nettle-types.h"
+
+#include "aes-internal.h"
+#include "fat-setup.h"
+
+struct arm_features
+{
+ /* /proc/cpuinfo "CPU Architecture" doesn't correspond exactly to
+ ARM architecture version, but it's good enough for our purposes.
+ Will be set to 5, 6, 7 or 8. */
+ unsigned arch_version;
+ int have_neon;
+};
+
+static void
+get_arm_features (struct arm_features *features)
+{
+ FILE *f;
+ char line[200];
+ int seen_arch = 0;
+ int seen_features = 0;
+
+ features->arch_version = 5;
+ features->have_neon = 0;
+
+ f = fopen ("/proc/cpuinfo", "r");
+ if (!f)
+ return;
+ while (seen_features + seen_arch < 2
+ && fgets (line, sizeof(line), f))
+ {
+ char *sep;
+ char *p;
+ sep = strchr (line, ':');
+ if (!sep)
+ continue;
+ for (p = sep; p - line > 0 && p[-1] == '\t'; p--)
+ ;
+
+ *p = '\0';
+ p = sep+1;
+
+ if (strcmp (line, "Features") == 0)
+ {
+ features->have_neon = (strstr (p, " neon ") != NULL);
+ seen_features = 1;
+ }
+ else if (strcmp (line, "CPU architecture") == 0)
+ {
+ /* Don't use strtol, since it's locale dependent. */
+ while (p[0] == ' ')
+ p++;
+ if (p[0] > '5' && p[0] <= '9')
+ features->arch_version = p[0] - '0';
+ else if (strcmp (p, "AArch64") == 0)
+ features->arch_version = 8;
+ seen_arch = 1;
+ }
+ }
+ if (features->arch_version >= 8)
+ {
+ /* Neon is not required, and maybe not listed in feature flags */
+ features->have_neon = 1;
+ }
+ fclose (f);
+}
+
+DECLARE_FAT_FUNC(_nettle_aes_encrypt, aes_crypt_internal_func)
+DECLARE_FAT_FUNC_VAR(aes_encrypt, aes_crypt_internal_func, arm)
+DECLARE_FAT_FUNC_VAR(aes_encrypt, aes_crypt_internal_func, armv6)
+
+DECLARE_FAT_FUNC(_nettle_aes_decrypt, aes_crypt_internal_func)
+DECLARE_FAT_FUNC_VAR(aes_decrypt, aes_crypt_internal_func, arm)
+DECLARE_FAT_FUNC_VAR(aes_decrypt, aes_crypt_internal_func, armv6)
+
+static void CONSTRUCTOR
+fat_init (void)
+{
+ static volatile int initialized = 0;
+ struct arm_features features;
+ int verbose;
+
+ if (initialized)
+ return;
+
+ get_arm_features (&features);
+
+ verbose = getenv (ENV_VERBOSE) != NULL;
+ if (verbose)
+ fprintf (stderr,
+ "libnettle: cpu arch: %u, neon: %s\n",
+ features.arch_version, features.have_neon ? "yes" : "no");
+
+ if (features.arch_version >= 6)
+ {
+ if (verbose)
+ fprintf (stderr, "libnettle: enabling armv6 code.\n");
+ _nettle_aes_encrypt_vec = _nettle_aes_encrypt_armv6;
+ _nettle_aes_decrypt_vec = _nettle_aes_decrypt_armv6;
+ }
+ else
+ {
+ if (verbose)
+ fprintf (stderr, "libnettle: not enabling armv6 code.\n");
+ _nettle_aes_encrypt_vec = _nettle_aes_encrypt_arm;
+ _nettle_aes_decrypt_vec = _nettle_aes_decrypt_arm;
+ }
+ /* FIXME: Needs memory barrier, to enforce store ordering. */
+ initialized = 1;
+}
+
+DEFINE_FAT_FUNC(_nettle_aes_encrypt, void,
+ (unsigned rounds, const uint32_t *keys,
+ const struct aes_table *T,
+ size_t length, uint8_t *dst,
+ const uint8_t *src),
+ (rounds, keys, T, length, dst, src))
+
+DEFINE_FAT_FUNC(_nettle_aes_decrypt, void,
+ (unsigned rounds, const uint32_t *keys,
+ const struct aes_table *T,
+ size_t length, uint8_t *dst,
+ const uint8_t *src),
+ (rounds, keys, T, length, dst, src))