diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk index d9cc08a97..b137b73f9 100644 --- a/src/libstrongswan/Android.mk +++ b/src/libstrongswan/Android.mk @@ -36,7 +36,7 @@ pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \ processing/watcher.c resolver/resolver_manager.c resolver/rr_set.c \ selectors/traffic_selector.c settings/settings.c settings/settings_types.c \ -settings/settings_parser.c settings/settings_lexer.c \ +settings/settings_parser.c settings/settings_lexer.c utils/cpu_feature.c \ utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \ utils/lexparser.c utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \ utils/parser_helper.c utils/test.c utils/process.c utils/utils/strerror.c diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index 2521b3e77..f7380728a 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -34,7 +34,7 @@ pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \ processing/watcher.c resolver/resolver_manager.c resolver/rr_set.c \ selectors/traffic_selector.c settings/settings.c settings/settings_types.c \ -settings/settings_parser.y settings/settings_lexer.l \ +settings/settings_parser.y settings/settings_lexer.l utils/cpu_feature.c \ utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \ utils/lexparser.c utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \ utils/parser_helper.c utils/test.c utils/process.c utils/utils/strerror.c @@ -103,7 +103,7 @@ threading/mutex.h threading/condvar.h threading/spinlock.h threading/semaphore.h threading/rwlock.h threading/rwlock_condvar.h threading/lock_profiler.h \ utils/utils.h utils/chunk.h utils/debug.h utils/enum.h utils/identification.h \ utils/lexparser.h utils/optionsfrom.h utils/capabilities.h utils/backtrace.h \ -utils/leak_detective.h utils/printf_hook/printf_hook.h \ +utils/cpu_feature.h utils/leak_detective.h utils/printf_hook/printf_hook.h \ utils/printf_hook/printf_hook_vstr.h utils/printf_hook/printf_hook_builtin.h \ utils/parser_helper.h utils/test.h utils/integrity_checker.h utils/process.h \ utils/utils/strerror.h utils/compat/windows.h utils/compat/apple.h diff --git a/src/libstrongswan/plugins/padlock/padlock_plugin.c b/src/libstrongswan/plugins/padlock/padlock_plugin.c index 2005ef648..9ce210961 100644 --- a/src/libstrongswan/plugins/padlock/padlock_plugin.c +++ b/src/libstrongswan/plugins/padlock/padlock_plugin.c @@ -23,31 +23,12 @@ #include #include +#include #include typedef struct private_padlock_plugin_t private_padlock_plugin_t; typedef enum padlock_feature_t padlock_feature_t; -/** - * Feature flags of padlock, received via cpuid() - */ -enum padlock_feature_t { - PADLOCK_RESERVED_1 = (1<<0), - PADLOCK_RESERVED_2 = (1<<1), - PADLOCK_RNG_AVAILABLE = (1<<2), - PADLOCK_RNG_ENABLED = (1<<3), - PADLOCK_RESERVED_3 = (1<<4), - PADLOCK_RESERVED_4 = (1<<5), - PADLOCK_ACE_AVAILABLE = (1<<6), - PADLOCK_ACE_ENABLED = (1<<7), - PADLOCK_ACE2_AVAILABLE = (1<<8), - PADLOCK_ACE2_ENABLED = (1<<9), - PADLOCK_PHE_AVAILABLE = (1<<10), - PADLOCK_PHE_ENABLED = (1<<11), - PADLOCK_PMM_AVAILABLE = (1<<12), - PADLOCK_PMM_ENABLED = (1<<13), -}; - /** * private data of aes_plugin */ @@ -61,48 +42,9 @@ struct private_padlock_plugin_t { /** * features supported by Padlock */ - padlock_feature_t features; + cpu_feature_t features; }; -/** - * Get cpuid for info, return eax, ebx, ecx and edx. -fPIC requires to save ebx. - */ -#define cpuid(op, a, b, c, d)\ - asm (\ - "pushl %%ebx \n\t"\ - "cpuid \n\t"\ - "movl %%ebx, %1 \n\t"\ - "popl %%ebx \n\t"\ - : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ - : "a" (op)); - -/** - * Get features supported by Padlock - */ -static padlock_feature_t get_padlock_features() -{ - char vendor[3 * sizeof(int) + 1]; - int a, b, c, d; - - cpuid(0, a, b, c, d); - /* VendorID string is in b-d-c (yes, in this order) */ - snprintf(vendor, sizeof(vendor), "%.4s%.4s%.4s", &b, &d, &c); - - /* check if we have a VIA chip */ - if (streq(vendor, "CentaurHauls")) - { - cpuid(0xC0000000, a, b, c, d); - /* check Centaur Extended Feature Flags */ - if (a >= 0xC0000001) - { - cpuid(0xC0000001, a, b, c, d); - return d; - } - } - DBG1(DBG_LIB, "Padlock not found, CPU is %s", vendor); - return 0; -} - METHOD(plugin_t, get_name, char*, private_padlock_plugin_t *this) { @@ -132,15 +74,15 @@ METHOD(plugin_t, get_features, int, if (!count) { /* initialize only once */ - if (this->features & PADLOCK_RNG_ENABLED) + if (this->features & CPU_FEATURE_PADLOCK_RNG_ENABLED) { plugin_features_add(f, f_rng, countof(f_rng), &count); } - if (this->features & PADLOCK_ACE2_ENABLED) + if (this->features & CPU_FEATURE_PADLOCK_ACE2_ENABLED) { plugin_features_add(f, f_aes, countof(f_aes), &count); } - if (this->features & PADLOCK_PHE_ENABLED) + if (this->features & CPU_FEATURE_PADLOCK_PHE_ENABLED) { plugin_features_add(f, f_sha1, countof(f_sha1), &count); } @@ -170,25 +112,20 @@ plugin_t *padlock_plugin_create() .destroy = _destroy, }, }, - .features = get_padlock_features(), + .features = cpu_feature_get_all(), ); - if (!this->features) - { - free(this); - return NULL; - } - DBG1(DBG_LIB, "Padlock found, supports:%s%s%s%s%s, enabled:%s%s%s%s%s", - this->features & PADLOCK_RNG_AVAILABLE ? " RNG" : "", - this->features & PADLOCK_ACE_AVAILABLE ? " ACE" : "", - this->features & PADLOCK_ACE2_AVAILABLE ? " ACE2" : "", - this->features & PADLOCK_PHE_AVAILABLE ? " PHE" : "", - this->features & PADLOCK_PMM_AVAILABLE ? " PMM" : "", - this->features & PADLOCK_RNG_ENABLED ? " RNG" : "", - this->features & PADLOCK_ACE_ENABLED ? " ACE" : "", - this->features & PADLOCK_ACE2_ENABLED ? " ACE2" : "", - this->features & PADLOCK_PHE_ENABLED ? " PHE" : "", - this->features & PADLOCK_PMM_ENABLED ? " PMM" : ""); + DBG1(DBG_LIB, "Padlock features supported:%s%s%s%s%s, enabled:%s%s%s%s%s", + this->features & CPU_FEATURE_PADLOCK_RNG_AVAILABLE ? " RNG" : "", + this->features & CPU_FEATURE_PADLOCK_ACE_AVAILABLE ? " ACE" : "", + this->features & CPU_FEATURE_PADLOCK_ACE2_AVAILABLE ? " ACE2" : "", + this->features & CPU_FEATURE_PADLOCK_PHE_AVAILABLE ? " PHE" : "", + this->features & CPU_FEATURE_PADLOCK_PMM_AVAILABLE ? " PMM" : "", + this->features & CPU_FEATURE_PADLOCK_RNG_ENABLED ? " RNG" : "", + this->features & CPU_FEATURE_PADLOCK_ACE_ENABLED ? " ACE" : "", + this->features & CPU_FEATURE_PADLOCK_ACE2_ENABLED ? " ACE2" : "", + this->features & CPU_FEATURE_PADLOCK_PHE_ENABLED ? " PHE" : "", + this->features & CPU_FEATURE_PADLOCK_PMM_ENABLED ? " PMM" : ""); return &this->public.plugin; } diff --git a/src/libstrongswan/plugins/rdrand/rdrand_plugin.c b/src/libstrongswan/plugins/rdrand/rdrand_plugin.c index b416c872f..b63bc2f43 100644 --- a/src/libstrongswan/plugins/rdrand/rdrand_plugin.c +++ b/src/libstrongswan/plugins/rdrand/rdrand_plugin.c @@ -20,6 +20,7 @@ #include #include +#include typedef struct private_rdrand_plugin_t private_rdrand_plugin_t; typedef enum cpuid_feature_t cpuid_feature_t; @@ -35,56 +36,6 @@ struct private_rdrand_plugin_t { rdrand_plugin_t public; }; -/** - * CPU feature flags, returned via cpuid(1) - */ -enum cpuid_feature_t { - CPUID_RDRAND = (1<<30), -}; - -/** - * Get cpuid for info, return eax, ebx, ecx and edx. - * -fPIC requires to save ebx on IA-32. - */ -static void cpuid(u_int op, u_int *a, u_int *b, u_int *c, u_int *d) -{ -#ifdef __x86_64__ - asm("cpuid" : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d) : "a" (op)); -#else /* __i386__ */ - asm("pushl %%ebx;" - "cpuid;" - "movl %%ebx, %1;" - "popl %%ebx;" - : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d) : "a" (op)); -#endif /* __x86_64__ / __i386__*/ -} - -/** - * Check if we have RDRAND instruction - */ -static bool have_rdrand() -{ - char vendor[3 * sizeof(u_int32_t) + 1]; - u_int a, b, c, d; - - cpuid(0, &a, &b, &c, &d); - /* VendorID string is in b-d-c (yes, in this order) */ - snprintf(vendor, sizeof(vendor), "%.4s%.4s%.4s", &b, &d, &c); - - /* check if we have an Intel CPU */ - if (streq(vendor, "GenuineIntel")) - { - cpuid(1, &a, &b, &c, &d); - if (c & CPUID_RDRAND) - { - DBG2(DBG_LIB, "detected RDRAND support on %s CPU", vendor); - return TRUE; - } - } - DBG2(DBG_LIB, "no RDRAND support on %s CPU, disabled", vendor); - return FALSE; -} - METHOD(plugin_t, get_name, char*, private_rdrand_plugin_t *this) { @@ -102,10 +53,12 @@ METHOD(plugin_t, get_features, int, PLUGIN_DEPENDS(CRYPTER, ENCR_AES_CBC, 16), }; *features = f; - if (have_rdrand()) + if (cpu_feature_available(CPU_FEATURE_RDRAND)) { + DBG2(DBG_LIB, "detected RDRAND support, enabled"); return countof(f); } + DBG2(DBG_LIB, "no RDRAND support detected, disabled"); return 0; } diff --git a/src/libstrongswan/utils/cpu_feature.c b/src/libstrongswan/utils/cpu_feature.c new file mode 100644 index 000000000..d86ca6bd8 --- /dev/null +++ b/src/libstrongswan/utils/cpu_feature.c @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2015 Martin Willi + * Copyright (C) 2015 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of 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. See . + * + * This program 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. + */ + +#include "cpu_feature.h" + +#if defined __i386__ || defined(__x86_64__) + +typedef enum { + /* Generic CPUID(1) flags */ + CPUID1_EDX_MMX = (1 << 23), + CPUID1_EDX_SSE = (1 << 25), + CPUID1_EDX_SSE2 = (1 << 26), + CPUID1_ECX_SSE3 = (1 << 0), + CPUID1_ECX_PCLMULQDQ = (1 << 1), + CPUID1_ECX_SSSE3 = (1 << 9), + CPUID1_ECX_SSE41 = (1 << 19), + CPUID1_ECX_SSE42 = (1 << 20), + CPUID1_ECX_AESNI = (1 << 25), + CPUID1_ECX_AVX = (1 << 28), + CPUID1_ECX_RDRAND = (1 << 30), + + /* For CentaurHauls cpuid(0xC0000001) */ + CPUIDC1_EDX_RNG_AVAILABLE = (1 << 2), + CPUIDC1_EDX_RNG_ENABLED = (1 << 3), + CPUIDC1_EDX_ACE_AVAILABLE = (1 << 6), + CPUIDC1_EDX_ACE_ENABLED = (1 << 7), + CPUIDC1_EDX_ACE2_AVAILABLE = (1 << 8), + CPUIDC1_EDX_ACE2_ENABLED = (1 << 9), + CPUIDC1_EDX_PHE_AVAILABLE = (1 << 10), + CPUIDC1_EDX_PHE_ENABLED = (1 << 11), + CPUIDC1_EDX_PMM_AVAILABLE = (1 << 12), + CPUIDC1_EDX_PMM_ENABLED = (1 << 13), +} cpuid_flag_t; + +/** + * Get cpuid for info, return eax, ebx, ecx and edx. + * -fPIC requires to save ebx on IA-32. + */ +static void cpuid(u_int op, u_int *a, u_int *b, u_int *c, u_int *d) +{ +#ifdef __x86_64__ + asm("cpuid" : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d) : "a" (op)); +#else /* __i386__ */ + asm("pushl %%ebx;" + "cpuid;" + "movl %%ebx, %1;" + "popl %%ebx;" + : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d) : "a" (op)); +#endif /* __x86_64__ / __i386__*/ +} + +/** + * Return feature if flag in reg, flag-to-feature + */ +static inline cpu_feature_t f2f(u_int reg, cpuid_flag_t flag, cpu_feature_t f) +{ + if (reg & flag) + { + return f; + } + return 0; +} + +/** + * Get features for a Via "CentaurHauls" CPU + */ +static cpu_feature_t get_via_features() +{ + cpu_feature_t f = 0; + u_int a, b, c, d; + + cpuid(0xc0000001, &a, &b, &c, &d); + + f |= f2f(d, CPUIDC1_EDX_RNG_AVAILABLE, CPU_FEATURE_PADLOCK_RNG_AVAILABLE); + f |= f2f(d, CPUIDC1_EDX_RNG_ENABLED, CPU_FEATURE_PADLOCK_RNG_ENABLED); + f |= f2f(d, CPUIDC1_EDX_ACE_AVAILABLE, CPU_FEATURE_PADLOCK_ACE_AVAILABLE); + f |= f2f(d, CPUIDC1_EDX_ACE_ENABLED, CPU_FEATURE_PADLOCK_ACE_ENABLED); + f |= f2f(d, CPUIDC1_EDX_ACE2_AVAILABLE, CPU_FEATURE_PADLOCK_ACE2_AVAILABLE); + f |= f2f(d, CPUIDC1_EDX_ACE2_ENABLED, CPU_FEATURE_PADLOCK_ACE2_ENABLED); + f |= f2f(d, CPUIDC1_EDX_PHE_AVAILABLE, CPU_FEATURE_PADLOCK_PHE_AVAILABLE); + f |= f2f(d, CPUIDC1_EDX_PHE_ENABLED, CPU_FEATURE_PADLOCK_PHE_ENABLED); + f |= f2f(d, CPUIDC1_EDX_PMM_AVAILABLE, CPU_FEATURE_PADLOCK_PMM_AVAILABLE); + f |= f2f(d, CPUIDC1_EDX_PMM_ENABLED, CPU_FEATURE_PADLOCK_PMM_ENABLED); + + return f; +} + +/** + * See header. + */ +cpu_feature_t cpu_feature_get_all() +{ + char vendor[3 * sizeof(u_int32_t) + 1]; + cpu_feature_t f = 0; + u_int a, b, c, d; + + cpuid(0, &a, &b, &c, &d); + /* VendorID string is in b-d-c (yes, in this order) */ + snprintf(vendor, sizeof(vendor), "%.4s%.4s%.4s", &b, &d, &c); + + cpuid(1, &a, &b, &c, &d); + + /* check common x86 features for CPUID(1) */ + f |= f2f(d, CPUID1_EDX_MMX, CPU_FEATURE_MMX); + f |= f2f(d, CPUID1_EDX_SSE, CPU_FEATURE_SSE); + f |= f2f(d, CPUID1_EDX_SSE2, CPU_FEATURE_SSE2); + f |= f2f(c, CPUID1_ECX_SSE3, CPU_FEATURE_SSE3); + f |= f2f(c, CPUID1_ECX_PCLMULQDQ, CPU_FEATURE_PCLMULQDQ); + f |= f2f(c, CPUID1_ECX_SSSE3, CPU_FEATURE_SSSE3); + f |= f2f(c, CPUID1_ECX_SSE41, CPU_FEATURE_SSE41); + f |= f2f(c, CPUID1_ECX_SSE42, CPU_FEATURE_SSE42); + f |= f2f(c, CPUID1_ECX_AESNI, CPU_FEATURE_AESNI); + f |= f2f(c, CPUID1_ECX_AVX, CPU_FEATURE_AVX); + f |= f2f(c, CPUID1_ECX_RDRAND, CPU_FEATURE_RDRAND); + + if (streq(vendor, "CentaurHauls")) + { + cpuid(0xc0000000, &a, &b, &c, &d); + /* check Centaur Extended Feature Flags */ + if (a >= 0xc0000001) + { + f |= get_via_features(); + } + } + return f; +} + +#else /* !x86 */ + +/** + * See header. + */ +cpu_feature_t cpu_feature_get_all() +{ + return 0; +} + +#endif + +/** + * See header. + */ +bool cpu_feature_available(cpu_feature_t feature) +{ + return (cpu_feature_get_all() & feature) == feature; +} diff --git a/src/libstrongswan/utils/cpu_feature.h b/src/libstrongswan/utils/cpu_feature.h new file mode 100644 index 000000000..3a807fa2b --- /dev/null +++ b/src/libstrongswan/utils/cpu_feature.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2015 Martin Willi + * Copyright (C) 2015 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of 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. See . + * + * This program 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. + */ + +/** + * @defgroup cpu_feature cpu_feature + * @{ @ingroup utils + */ + +#ifndef CPU_FEATURE_H_ +#define CPU_FEATURE_H_ + +#include + +typedef enum { + /** x86/x64 extensions */ + CPU_FEATURE_MMX = (1 << 0), + CPU_FEATURE_SSE = (1 << 1), + CPU_FEATURE_SSE2 = (1 << 2), + CPU_FEATURE_SSE3 = (1 << 3), + CPU_FEATURE_SSSE3 = (1 << 4), + CPU_FEATURE_SSE41 = (1 << 5), + CPU_FEATURE_SSE42 = (1 << 6), + CPU_FEATURE_AVX = (1 << 7), + CPU_FEATURE_RDRAND = (1 << 8), + CPU_FEATURE_AESNI = (1 << 9), + CPU_FEATURE_PCLMULQDQ = (1 << 10), + /** Via Padlock Security features */ + CPU_FEATURE_PADLOCK_RNG_AVAILABLE = (1 << 22), + CPU_FEATURE_PADLOCK_RNG_ENABLED = (1 << 23), + CPU_FEATURE_PADLOCK_ACE_AVAILABLE = (1 << 24), + CPU_FEATURE_PADLOCK_ACE_ENABLED = (1 << 25), + CPU_FEATURE_PADLOCK_ACE2_AVAILABLE = (1 << 26), + CPU_FEATURE_PADLOCK_ACE2_ENABLED = (1 << 27), + CPU_FEATURE_PADLOCK_PHE_AVAILABLE = (1 << 28), + CPU_FEATURE_PADLOCK_PHE_ENABLED = (1 << 29), + CPU_FEATURE_PADLOCK_PMM_AVAILABLE = (1 << 30), + CPU_FEATURE_PADLOCK_PMM_ENABLED = (1 << 31), +} cpu_feature_t; + +/** + * Get a bitmask for all supported CPU features + */ +cpu_feature_t cpu_feature_get_all(); + +/** + * Check if a given set of CPU features is available. + */ +bool cpu_feature_available(cpu_feature_t feature); + +#endif /** CPU_FEATURE_H_ @}*/