/
niceSOFT
/
libgcrypt
Обзор
Документация
Войти
/
niceSOFT
/
libgcrypt
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/hwfeatures.c
352 строки
10 KB
Jussi Kivilinna
sm4: add Intel SM4 instructions accelerated AVX2 implementation
28 июн 2026, 15:18
28 июн 2026, 15:18
df44b48
Код
Авторство
О чём код?
/* hwfeatures.c - Detect hardware features. * Copyright (C) 2007, 2011 Free Software Foundation, Inc. * Copyright (C) 2012 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include <stdio.h> #include <ctype.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <unistd.h> #ifdef HAVE_SYSLOG # include <syslog.h> #endif /*HAVE_SYSLOG*/ #ifdef HAVE_W32_SYSTEM #include <winsock2.h> /* Due to the stupid mingw64 requirement to include this header before windows.h which is often implicitly included. */ #include <shlobj.h> #ifndef CSIDL_APPDATA #define CSIDL_APPDATA 0x001a #endif #ifndef CSIDL_LOCAL_APPDATA #define CSIDL_LOCAL_APPDATA 0x001c #endif #ifndef CSIDL_COMMON_APPDATA #define CSIDL_COMMON_APPDATA 0x0023 #endif #ifndef CSIDL_FLAG_CREATE #define CSIDL_FLAG_CREATE 0x8000 #endif #endif /*HAVE_W32_SYSTEM*/ #include "g10lib.h" #include "hwf-common.h" /* The name of a file used to globally disable selected features. * Note: Always used get_hwf_deny_file to get this name */ #define HWF_DENY_FILE "hwf.deny" /* A table to map hardware features to a string. * Note: Remember to add new HW features to 'doc/gcrypt.texi'. */ static struct { unsigned int flag; const char *desc; } hwflist[] = { #if defined(HAVE_CPU_ARCH_X86) { HWF_PADLOCK_RNG, "padlock-rng" }, { HWF_PADLOCK_AES, "padlock-aes" }, { HWF_PADLOCK_SHA, "padlock-sha" }, { HWF_PADLOCK_MMUL, "padlock-mmul"}, { HWF_INTEL_CPU, "intel-cpu" }, { HWF_INTEL_FAST_SHLD, "intel-fast-shld" }, { HWF_INTEL_BMI2, "intel-bmi2" }, { HWF_INTEL_SSSE3, "intel-ssse3" }, { HWF_INTEL_SSE4_1, "intel-sse4.1" }, { HWF_INTEL_PCLMUL, "intel-pclmul" }, { HWF_INTEL_AESNI, "intel-aesni" }, { HWF_INTEL_RDRAND, "intel-rdrand" }, { HWF_INTEL_AVX, "intel-avx" }, { HWF_INTEL_AVX2, "intel-avx2" }, { HWF_INTEL_RDTSC, "intel-rdtsc" }, { HWF_INTEL_SHAEXT, "intel-shaext" }, { HWF_INTEL_VAES_VPCLMUL, "intel-vaes-vpclmul" }, { HWF_INTEL_AVX512, "intel-avx512" }, { HWF_INTEL_GFNI, "intel-gfni" }, { HWF_INTEL_SHA512, "intel-sha512" }, { HWF_INTEL_SM3, "intel-sm3" }, { HWF_INTEL_SM4, "intel-sm4" }, /* Following removed HW feature strings are kept for API compatibility. */ { 0, "intel-fast-vpgather" }, #elif defined(HAVE_CPU_ARCH_ARM) { HWF_ARM_NEON, "arm-neon" }, { HWF_ARM_AES, "arm-aes" }, { HWF_ARM_SHA1, "arm-sha1" }, { HWF_ARM_SHA2, "arm-sha2" }, { HWF_ARM_PMULL, "arm-pmull" }, { HWF_ARM_SHA3, "arm-sha3" }, { HWF_ARM_SM3, "arm-sm3" }, { HWF_ARM_SM4, "arm-sm4" }, { HWF_ARM_SHA512, "arm-sha512" }, { HWF_ARM_SVE, "arm-sve" }, { HWF_ARM_SVE2, "arm-sve2" }, { HWF_ARM_SVEAES, "arm-sveaes" }, { HWF_ARM_SVEPMULL, "arm-svepmull" }, { HWF_ARM_SVESHA3, "arm-svesha3" }, { HWF_ARM_SVESM4, "arm-svesm4" }, #elif defined(HAVE_CPU_ARCH_PPC) { HWF_PPC_VCRYPTO, "ppc-vcrypto" }, { HWF_PPC_ARCH_3_00, "ppc-arch_3_00" }, { HWF_PPC_ARCH_2_07, "ppc-arch_2_07" }, { HWF_PPC_ARCH_3_10, "ppc-arch_3_10" }, #elif defined(HAVE_CPU_ARCH_S390X) { HWF_S390X_MSA, "s390x-msa" }, { HWF_S390X_MSA_4, "s390x-msa-4" }, { HWF_S390X_MSA_8, "s390x-msa-8" }, { HWF_S390X_MSA_9, "s390x-msa-9" }, { HWF_S390X_VX, "s390x-vx" }, #elif defined(HAVE_CPU_ARCH_RISCV) { HWF_RISCV_IMAFDC, "riscv-imafdc" }, { HWF_RISCV_B, "riscv-b" }, { HWF_RISCV_V, "riscv-v" }, { HWF_RISCV_ZBB, "riscv-zbb" }, { HWF_RISCV_ZBC, "riscv-zbc" }, { HWF_RISCV_ZVKB, "riscv-zvkb" }, { HWF_RISCV_ZVKG, "riscv-zvkg" }, { HWF_RISCV_ZVKNED, "riscv-zvkned" }, { HWF_RISCV_ZVKNHA, "riscv-zvknha" }, { HWF_RISCV_ZVKNHB, "riscv-zvknhb" }, #endif }; /* A bit vector with the hardware features which shall not be used. This variable must be set prior to any initialization. */ static unsigned int disabled_hw_features; /* A bit vector describing the hardware features currently available. */ static unsigned int hw_features; static const char * get_hwf_deny_file (void) { #ifdef HAVE_W32_SYSTEM static char *fname; if (!fname) { const char *sysconfdir = _gcry_get_sysconfdir(); fname = xmalloc (strlen (sysconfdir) + strlen (HWF_DENY_FILE) + 1); strcpy (fname, sysconfdir); strcat (fname, HWF_DENY_FILE); } return fname; #else return "/etc/gcrypt/" HWF_DENY_FILE; #endif } /* Disable a feature by name. This function must be called *before* _gcry_detect_hw_features is called. */ gpg_err_code_t _gcry_disable_hw_feature (const char *name) { int i; size_t n1, n2; while (name && *name) { n1 = strcspn (name, ":,"); if (!n1) ; else if (n1 == 3 && !strncmp (name, "all", 3)) disabled_hw_features = ~0; else { for (i=0; i < DIM (hwflist); i++) { n2 = strlen (hwflist[i].desc); if (n1 == n2 && !strncmp (hwflist[i].desc, name, n2)) { disabled_hw_features |= hwflist[i].flag; break; } } if (!(i < DIM (hwflist))) return GPG_ERR_INV_NAME; } name += n1; if (*name) name++; /* Skip delimiter ':' or ','. */ } return 0; } /* Return a bit vector describing the available hardware features. The HWF_ constants are used to test for them. */ unsigned int _gcry_get_hw_features (void) { return hw_features; } /* Enumerate all features. The caller is expected to start with an IDX of 0 and then increment IDX until NULL is returned. */ const char * _gcry_enum_hw_features (int idx, unsigned int *r_feature) { if (idx < 0 || idx >= DIM (hwflist)) return NULL; if (r_feature) *r_feature = hwflist[idx].flag; return hwflist[idx].desc; } /* Read a file with features which shall not be used. The file is a simple text file where empty lines and lines with the first non white-space character being '#' are ignored. */ static void parse_hwf_deny_file (void) { const char *fname = get_hwf_deny_file (); FILE *fp; char buffer[256]; char *p, *pend; int lnr = 0; fp = fopen (fname, "r"); if (!fp) return; for (;;) { if (!fgets (buffer, sizeof buffer, fp)) { if (!feof (fp)) { #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: error reading '%s', line %d", fname, lnr); #endif /*HAVE_SYSLOG*/ } fclose (fp); return; } lnr++; for (p=buffer; my_isascii (*p) && isspace (*p); p++) ; pend = strchr (p, '\n'); if (pend) *pend = 0; pend = p + (*p? (strlen (p)-1):0); for ( ;pend > p; pend--) if (my_isascii (*pend) && isspace (*pend)) *pend = 0; if (!*p || *p == '#') continue; if (_gcry_disable_hw_feature (p) == GPG_ERR_INV_NAME) { #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: unknown feature in '%s', line %d", fname, lnr); #endif /*HAVE_SYSLOG*/ } } } /* Detect the available hardware features. This function is called once right at startup and we assume that no other threads are running. */ void _gcry_detect_hw_features (void) { hw_features = 0; parse_hwf_deny_file (); #if defined (HAVE_CPU_ARCH_X86) { hw_features = _gcry_hwf_detect_x86 (); } #elif defined (HAVE_CPU_ARCH_ARM) { hw_features = _gcry_hwf_detect_arm (); } #elif defined (HAVE_CPU_ARCH_PPC) { hw_features = _gcry_hwf_detect_ppc (); } #elif defined (HAVE_CPU_ARCH_S390X) { hw_features = _gcry_hwf_detect_s390x (); } #elif defined (HAVE_CPU_ARCH_RISCV) { hw_features = _gcry_hwf_detect_riscv (); } #endif hw_features &= ~disabled_hw_features; } /* This is a helper function to return the system configuration * directory on Windows. On Windows the respective function is used * and if that fails a standard name is used. On Unix "/etc/gcrypt/" * is returned. There is always a traling slash. */ const char * _gcry_get_sysconfdir (void) { #ifdef HAVE_W32_SYSTEM static char *appdata; if (!appdata) { HRESULT (WINAPI *func)(HWND,int,HANDLE,DWORD,LPSTR); void *handle; char *buf; handle = LoadLibraryEx ("shell32.dll", NULL, 0); if (handle) { buf = xmalloc (MAX_PATH+17+1); /* Space for "/GNU/etc/gcrypt/" */ func = (void *)GetProcAddress (handle, "SHGetFolderPathA"); if (func && func (NULL, CSIDL_COMMON_APPDATA, NULL, 0, buf) >= 0) { appdata = xmalloc (strlen (buf) + 17 + 1); strcpy (appdata, buf); strcat (appdata, "/GNU/etc/gcrypt/"); } xfree (buf); FreeLibrary (handle); } if (!appdata) appdata = xstrdup ("c:/ProgramData/GNU/etc/gcrypt/"); } return appdata; #else /*!HAVE_W32_SYSTEM*/ return "/etc/gcrypt/"; #endif /*!HAVE_W32_SYSTEM*/ }