xref: /freebsd/sys/crypto/openssl/ossl_x86.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
1fd86ae68SMitchell Horne /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3fd86ae68SMitchell Horne  *
4fd86ae68SMitchell Horne  * Copyright (c) 2020 Netflix, Inc
5fd86ae68SMitchell Horne  *
6fd86ae68SMitchell Horne  * Redistribution and use in source and binary forms, with or without
7fd86ae68SMitchell Horne  * modification, are permitted provided that the following conditions
8fd86ae68SMitchell Horne  * are met:
9fd86ae68SMitchell Horne  * 1. Redistributions of source code must retain the above copyright
10fd86ae68SMitchell Horne  *    notice, this list of conditions and the following disclaimer,
11fd86ae68SMitchell Horne  *    without modification.
12fd86ae68SMitchell Horne  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
13fd86ae68SMitchell Horne  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
14fd86ae68SMitchell Horne  *    redistribution must be conditioned upon including a substantially
15fd86ae68SMitchell Horne  *    similar Disclaimer requirement for further binary redistribution.
16fd86ae68SMitchell Horne  *
17fd86ae68SMitchell Horne  * NO WARRANTY
18fd86ae68SMitchell Horne  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19fd86ae68SMitchell Horne  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20fd86ae68SMitchell Horne  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
21fd86ae68SMitchell Horne  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22fd86ae68SMitchell Horne  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
23fd86ae68SMitchell Horne  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24fd86ae68SMitchell Horne  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25fd86ae68SMitchell Horne  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26fd86ae68SMitchell Horne  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27fd86ae68SMitchell Horne  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28fd86ae68SMitchell Horne  * THE POSSIBILITY OF SUCH DAMAGES.
29fd86ae68SMitchell Horne  */
30fd86ae68SMitchell Horne 
31fd86ae68SMitchell Horne #include <sys/types.h>
32fd86ae68SMitchell Horne #include <sys/systm.h>
33fd86ae68SMitchell Horne 
34fd86ae68SMitchell Horne #include <machine/cpufunc.h>
35fd86ae68SMitchell Horne #include <machine/md_var.h>
36fd86ae68SMitchell Horne #include <x86/cputypes.h>
37fd86ae68SMitchell Horne #include <x86/specialreg.h>
38fd86ae68SMitchell Horne 
39fd86ae68SMitchell Horne #include <crypto/openssl/ossl.h>
409a3444d9SMark Johnston #include <crypto/openssl/ossl_aes_gcm.h>
41197ff4c3SKornel Duleba #include <crypto/openssl/ossl_cipher.h>
42fd86ae68SMitchell Horne 
43fd86ae68SMitchell Horne /*
44fd86ae68SMitchell Horne  * See OPENSSL_ia32cap(3).
45fd86ae68SMitchell Horne  *
46fd86ae68SMitchell Horne  * [0] = cpu_feature but with a few custom bits
47fd86ae68SMitchell Horne  * [1] = cpu_feature2 but with AMD XOP in bit 11
48fd86ae68SMitchell Horne  * [2] = cpu_stdext_feature
499ad8dc72SMark Johnston  * [3] = cpu_stdext_feature2
50fd86ae68SMitchell Horne  */
51fd86ae68SMitchell Horne unsigned int OPENSSL_ia32cap_P[4];
52197ff4c3SKornel Duleba #define AESNI_CAPABLE	(OPENSSL_ia32cap_P[1]&(1<<(57-32)))
53197ff4c3SKornel Duleba 
54197ff4c3SKornel Duleba ossl_cipher_setkey_t aesni_set_encrypt_key;
55197ff4c3SKornel Duleba ossl_cipher_setkey_t aesni_set_decrypt_key;
56fd86ae68SMitchell Horne 
579a3444d9SMark Johnston #ifdef __amd64__
589a3444d9SMark Johnston int ossl_vaes_vpclmulqdq_capable(void);
59*9b1d8728SMark Johnston ossl_cipher_setkey_t ossl_aes_gcm_setkey_aesni;
609a3444d9SMark Johnston ossl_cipher_setkey_t ossl_aes_gcm_setkey_avx512;
619a3444d9SMark Johnston #endif
629a3444d9SMark Johnston 
63fd86ae68SMitchell Horne void
ossl_cpuid(struct ossl_softc * sc)64197ff4c3SKornel Duleba ossl_cpuid(struct ossl_softc *sc)
65fd86ae68SMitchell Horne {
66fd86ae68SMitchell Horne 	uint64_t xcr0;
67fd86ae68SMitchell Horne 	u_int regs[4];
68fd86ae68SMitchell Horne 	u_int max_cores;
69fd86ae68SMitchell Horne 
70fd86ae68SMitchell Horne 	/* Derived from OpenSSL_ia32_cpuid. */
71fd86ae68SMitchell Horne 
72fd86ae68SMitchell Horne 	OPENSSL_ia32cap_P[0] = cpu_feature & ~(CPUID_B20 | CPUID_IA64);
73fd86ae68SMitchell Horne 	if (cpu_vendor_id == CPU_VENDOR_INTEL) {
74fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[0] |= CPUID_IA64;
75fd86ae68SMitchell Horne 		if ((cpu_id & 0xf00) != 0xf00)
76fd86ae68SMitchell Horne 			OPENSSL_ia32cap_P[0] |= CPUID_B20;
77fd86ae68SMitchell Horne 	}
78fd86ae68SMitchell Horne 
79fd86ae68SMitchell Horne 	/* Only leave CPUID_HTT on if HTT is present. */
80fd86ae68SMitchell Horne 	if (cpu_vendor_id == CPU_VENDOR_AMD && cpu_exthigh >= 0x80000008) {
81fd86ae68SMitchell Horne 		max_cores = (cpu_procinfo2 & AMDID_CMP_CORES) + 1;
82fd86ae68SMitchell Horne 		if (cpu_feature & CPUID_HTT) {
83fd86ae68SMitchell Horne 			if ((cpu_procinfo & CPUID_HTT_CORES) >> 16 <= max_cores)
84fd86ae68SMitchell Horne 				OPENSSL_ia32cap_P[0] &= ~CPUID_HTT;
85fd86ae68SMitchell Horne 		}
86fd86ae68SMitchell Horne 	} else {
87fd86ae68SMitchell Horne 		if (cpu_high >= 4) {
88fd86ae68SMitchell Horne 			cpuid_count(4, 0, regs);
89fd86ae68SMitchell Horne 			max_cores = (regs[0] >> 26) & 0xfff;
90fd86ae68SMitchell Horne 		} else
91fd86ae68SMitchell Horne 			max_cores = -1;
92fd86ae68SMitchell Horne 	}
93fd86ae68SMitchell Horne 	if (max_cores == 0)
94fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[0] &= ~CPUID_HTT;
95fd86ae68SMitchell Horne 	else if ((cpu_procinfo & CPUID_HTT_CORES) >> 16 == 0)
96fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[0] &= ~CPUID_HTT;
97fd86ae68SMitchell Horne 
98fd86ae68SMitchell Horne 	OPENSSL_ia32cap_P[1] = cpu_feature2 & ~AMDID2_XOP;
99fd86ae68SMitchell Horne 	if (cpu_vendor_id == CPU_VENDOR_AMD)
100fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[1] |= amd_feature2 & AMDID2_XOP;
101fd86ae68SMitchell Horne 
102fd86ae68SMitchell Horne 	OPENSSL_ia32cap_P[2] = cpu_stdext_feature;
103fd86ae68SMitchell Horne 	if ((OPENSSL_ia32cap_P[1] & CPUID2_XSAVE) == 0)
104fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[2] &= ~(CPUID_STDEXT_AVX512F |
105fd86ae68SMitchell Horne 		    CPUID_STDEXT_AVX512DQ);
106fd86ae68SMitchell Horne 
107fd86ae68SMitchell Horne 	/* Disable AVX512F on Skylake-X. */
108fd86ae68SMitchell Horne 	if ((cpu_id & 0x0fff0ff0) == 0x00050650)
109fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[2] &= ~(CPUID_STDEXT_AVX512F);
110fd86ae68SMitchell Horne 
111fd86ae68SMitchell Horne 	if (cpu_feature2 & CPUID2_OSXSAVE)
112fd86ae68SMitchell Horne 		xcr0 = rxcr(0);
113fd86ae68SMitchell Horne 	else
114fd86ae68SMitchell Horne 		xcr0 = 0;
115fd86ae68SMitchell Horne 
116fd86ae68SMitchell Horne 	if ((xcr0 & (XFEATURE_AVX512 | XFEATURE_AVX)) !=
117fd86ae68SMitchell Horne 	    (XFEATURE_AVX512 | XFEATURE_AVX))
118fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[2] &= ~(CPUID_STDEXT_AVX512VL |
119fd86ae68SMitchell Horne 		    CPUID_STDEXT_AVX512BW | CPUID_STDEXT_AVX512IFMA |
120fd86ae68SMitchell Horne 		    CPUID_STDEXT_AVX512F);
121fd86ae68SMitchell Horne 	if ((xcr0 & XFEATURE_AVX) != XFEATURE_AVX) {
122fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[1] &= ~(CPUID2_AVX | AMDID2_XOP | CPUID2_FMA);
123fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[2] &= ~CPUID_STDEXT_AVX2;
124fd86ae68SMitchell Horne 	}
1259ad8dc72SMark Johnston 	OPENSSL_ia32cap_P[3] = cpu_stdext_feature2;
126197ff4c3SKornel Duleba 
1279a3444d9SMark Johnston 	if (!AESNI_CAPABLE)
128197ff4c3SKornel Duleba 		return;
1299a3444d9SMark Johnston 
130197ff4c3SKornel Duleba 	sc->has_aes = true;
131197ff4c3SKornel Duleba 	ossl_cipher_aes_cbc.set_encrypt_key = aesni_set_encrypt_key;
132197ff4c3SKornel Duleba 	ossl_cipher_aes_cbc.set_decrypt_key = aesni_set_decrypt_key;
1339a3444d9SMark Johnston 
1349a3444d9SMark Johnston #ifdef __amd64__
1359a3444d9SMark Johnston 	if (ossl_vaes_vpclmulqdq_capable()) {
1369a3444d9SMark Johnston 		ossl_cipher_aes_gcm.set_encrypt_key =
1379a3444d9SMark Johnston 		    ossl_aes_gcm_setkey_avx512;
1389a3444d9SMark Johnston 		ossl_cipher_aes_gcm.set_decrypt_key =
1399a3444d9SMark Johnston 		    ossl_aes_gcm_setkey_avx512;
1409a3444d9SMark Johnston 		sc->has_aes_gcm = true;
141*9b1d8728SMark Johnston 	} else if ((cpu_feature2 &
142*9b1d8728SMark Johnston 	    (CPUID2_AVX | CPUID2_PCLMULQDQ | CPUID2_MOVBE)) ==
143*9b1d8728SMark Johnston 	    (CPUID2_AVX | CPUID2_PCLMULQDQ | CPUID2_MOVBE)) {
144*9b1d8728SMark Johnston 		ossl_cipher_aes_gcm.set_encrypt_key = ossl_aes_gcm_setkey_aesni;
145*9b1d8728SMark Johnston 		ossl_cipher_aes_gcm.set_decrypt_key = ossl_aes_gcm_setkey_aesni;
146*9b1d8728SMark Johnston 		sc->has_aes_gcm = true;
1479a3444d9SMark Johnston 	} else {
1489a3444d9SMark Johnston 		sc->has_aes_gcm = false;
1499a3444d9SMark Johnston 	}
1509a3444d9SMark Johnston #else
1519a3444d9SMark Johnston 	sc->has_aes_gcm = false;
1529a3444d9SMark Johnston #endif
153fd86ae68SMitchell Horne }
154