xref: /freebsd/sys/crypto/openssl/ossl_x86.c (revision 9b1d87286c78266dc76d32a06ed19bf3e93c0a3b)
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  * $FreeBSD$
31fd86ae68SMitchell Horne  */
32fd86ae68SMitchell Horne 
33fd86ae68SMitchell Horne #include <sys/types.h>
34fd86ae68SMitchell Horne #include <sys/systm.h>
35fd86ae68SMitchell Horne 
36fd86ae68SMitchell Horne #include <machine/cpufunc.h>
37fd86ae68SMitchell Horne #include <machine/md_var.h>
38fd86ae68SMitchell Horne #include <x86/cputypes.h>
39fd86ae68SMitchell Horne #include <x86/specialreg.h>
40fd86ae68SMitchell Horne 
41fd86ae68SMitchell Horne #include <crypto/openssl/ossl.h>
429a3444d9SMark Johnston #include <crypto/openssl/ossl_aes_gcm.h>
43197ff4c3SKornel Duleba #include <crypto/openssl/ossl_cipher.h>
44fd86ae68SMitchell Horne 
45fd86ae68SMitchell Horne /*
46fd86ae68SMitchell Horne  * See OPENSSL_ia32cap(3).
47fd86ae68SMitchell Horne  *
48fd86ae68SMitchell Horne  * [0] = cpu_feature but with a few custom bits
49fd86ae68SMitchell Horne  * [1] = cpu_feature2 but with AMD XOP in bit 11
50fd86ae68SMitchell Horne  * [2] = cpu_stdext_feature
519ad8dc72SMark Johnston  * [3] = cpu_stdext_feature2
52fd86ae68SMitchell Horne  */
53fd86ae68SMitchell Horne unsigned int OPENSSL_ia32cap_P[4];
54197ff4c3SKornel Duleba #define AESNI_CAPABLE	(OPENSSL_ia32cap_P[1]&(1<<(57-32)))
55197ff4c3SKornel Duleba 
56197ff4c3SKornel Duleba ossl_cipher_setkey_t aesni_set_encrypt_key;
57197ff4c3SKornel Duleba ossl_cipher_setkey_t aesni_set_decrypt_key;
58fd86ae68SMitchell Horne 
599a3444d9SMark Johnston #ifdef __amd64__
609a3444d9SMark Johnston int ossl_vaes_vpclmulqdq_capable(void);
61*9b1d8728SMark Johnston ossl_cipher_setkey_t ossl_aes_gcm_setkey_aesni;
629a3444d9SMark Johnston ossl_cipher_setkey_t ossl_aes_gcm_setkey_avx512;
639a3444d9SMark Johnston #endif
649a3444d9SMark Johnston 
65fd86ae68SMitchell Horne void
66197ff4c3SKornel Duleba ossl_cpuid(struct ossl_softc *sc)
67fd86ae68SMitchell Horne {
68fd86ae68SMitchell Horne 	uint64_t xcr0;
69fd86ae68SMitchell Horne 	u_int regs[4];
70fd86ae68SMitchell Horne 	u_int max_cores;
71fd86ae68SMitchell Horne 
72fd86ae68SMitchell Horne 	/* Derived from OpenSSL_ia32_cpuid. */
73fd86ae68SMitchell Horne 
74fd86ae68SMitchell Horne 	OPENSSL_ia32cap_P[0] = cpu_feature & ~(CPUID_B20 | CPUID_IA64);
75fd86ae68SMitchell Horne 	if (cpu_vendor_id == CPU_VENDOR_INTEL) {
76fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[0] |= CPUID_IA64;
77fd86ae68SMitchell Horne 		if ((cpu_id & 0xf00) != 0xf00)
78fd86ae68SMitchell Horne 			OPENSSL_ia32cap_P[0] |= CPUID_B20;
79fd86ae68SMitchell Horne 	}
80fd86ae68SMitchell Horne 
81fd86ae68SMitchell Horne 	/* Only leave CPUID_HTT on if HTT is present. */
82fd86ae68SMitchell Horne 	if (cpu_vendor_id == CPU_VENDOR_AMD && cpu_exthigh >= 0x80000008) {
83fd86ae68SMitchell Horne 		max_cores = (cpu_procinfo2 & AMDID_CMP_CORES) + 1;
84fd86ae68SMitchell Horne 		if (cpu_feature & CPUID_HTT) {
85fd86ae68SMitchell Horne 			if ((cpu_procinfo & CPUID_HTT_CORES) >> 16 <= max_cores)
86fd86ae68SMitchell Horne 				OPENSSL_ia32cap_P[0] &= ~CPUID_HTT;
87fd86ae68SMitchell Horne 		}
88fd86ae68SMitchell Horne 	} else {
89fd86ae68SMitchell Horne 		if (cpu_high >= 4) {
90fd86ae68SMitchell Horne 			cpuid_count(4, 0, regs);
91fd86ae68SMitchell Horne 			max_cores = (regs[0] >> 26) & 0xfff;
92fd86ae68SMitchell Horne 		} else
93fd86ae68SMitchell Horne 			max_cores = -1;
94fd86ae68SMitchell Horne 	}
95fd86ae68SMitchell Horne 	if (max_cores == 0)
96fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[0] &= ~CPUID_HTT;
97fd86ae68SMitchell Horne 	else if ((cpu_procinfo & CPUID_HTT_CORES) >> 16 == 0)
98fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[0] &= ~CPUID_HTT;
99fd86ae68SMitchell Horne 
100fd86ae68SMitchell Horne 	OPENSSL_ia32cap_P[1] = cpu_feature2 & ~AMDID2_XOP;
101fd86ae68SMitchell Horne 	if (cpu_vendor_id == CPU_VENDOR_AMD)
102fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[1] |= amd_feature2 & AMDID2_XOP;
103fd86ae68SMitchell Horne 
104fd86ae68SMitchell Horne 	OPENSSL_ia32cap_P[2] = cpu_stdext_feature;
105fd86ae68SMitchell Horne 	if ((OPENSSL_ia32cap_P[1] & CPUID2_XSAVE) == 0)
106fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[2] &= ~(CPUID_STDEXT_AVX512F |
107fd86ae68SMitchell Horne 		    CPUID_STDEXT_AVX512DQ);
108fd86ae68SMitchell Horne 
109fd86ae68SMitchell Horne 	/* Disable AVX512F on Skylake-X. */
110fd86ae68SMitchell Horne 	if ((cpu_id & 0x0fff0ff0) == 0x00050650)
111fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[2] &= ~(CPUID_STDEXT_AVX512F);
112fd86ae68SMitchell Horne 
113fd86ae68SMitchell Horne 	if (cpu_feature2 & CPUID2_OSXSAVE)
114fd86ae68SMitchell Horne 		xcr0 = rxcr(0);
115fd86ae68SMitchell Horne 	else
116fd86ae68SMitchell Horne 		xcr0 = 0;
117fd86ae68SMitchell Horne 
118fd86ae68SMitchell Horne 	if ((xcr0 & (XFEATURE_AVX512 | XFEATURE_AVX)) !=
119fd86ae68SMitchell Horne 	    (XFEATURE_AVX512 | XFEATURE_AVX))
120fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[2] &= ~(CPUID_STDEXT_AVX512VL |
121fd86ae68SMitchell Horne 		    CPUID_STDEXT_AVX512BW | CPUID_STDEXT_AVX512IFMA |
122fd86ae68SMitchell Horne 		    CPUID_STDEXT_AVX512F);
123fd86ae68SMitchell Horne 	if ((xcr0 & XFEATURE_AVX) != XFEATURE_AVX) {
124fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[1] &= ~(CPUID2_AVX | AMDID2_XOP | CPUID2_FMA);
125fd86ae68SMitchell Horne 		OPENSSL_ia32cap_P[2] &= ~CPUID_STDEXT_AVX2;
126fd86ae68SMitchell Horne 	}
1279ad8dc72SMark Johnston 	OPENSSL_ia32cap_P[3] = cpu_stdext_feature2;
128197ff4c3SKornel Duleba 
1299a3444d9SMark Johnston 	if (!AESNI_CAPABLE)
130197ff4c3SKornel Duleba 		return;
1319a3444d9SMark Johnston 
132197ff4c3SKornel Duleba 	sc->has_aes = true;
133197ff4c3SKornel Duleba 	ossl_cipher_aes_cbc.set_encrypt_key = aesni_set_encrypt_key;
134197ff4c3SKornel Duleba 	ossl_cipher_aes_cbc.set_decrypt_key = aesni_set_decrypt_key;
1359a3444d9SMark Johnston 
1369a3444d9SMark Johnston #ifdef __amd64__
1379a3444d9SMark Johnston 	if (ossl_vaes_vpclmulqdq_capable()) {
1389a3444d9SMark Johnston 		ossl_cipher_aes_gcm.set_encrypt_key =
1399a3444d9SMark Johnston 		    ossl_aes_gcm_setkey_avx512;
1409a3444d9SMark Johnston 		ossl_cipher_aes_gcm.set_decrypt_key =
1419a3444d9SMark Johnston 		    ossl_aes_gcm_setkey_avx512;
1429a3444d9SMark Johnston 		sc->has_aes_gcm = true;
143*9b1d8728SMark Johnston 	} else if ((cpu_feature2 &
144*9b1d8728SMark Johnston 	    (CPUID2_AVX | CPUID2_PCLMULQDQ | CPUID2_MOVBE)) ==
145*9b1d8728SMark Johnston 	    (CPUID2_AVX | CPUID2_PCLMULQDQ | CPUID2_MOVBE)) {
146*9b1d8728SMark Johnston 		ossl_cipher_aes_gcm.set_encrypt_key = ossl_aes_gcm_setkey_aesni;
147*9b1d8728SMark Johnston 		ossl_cipher_aes_gcm.set_decrypt_key = ossl_aes_gcm_setkey_aesni;
148*9b1d8728SMark Johnston 		sc->has_aes_gcm = true;
1499a3444d9SMark Johnston 	} else {
1509a3444d9SMark Johnston 		sc->has_aes_gcm = false;
1519a3444d9SMark Johnston 	}
1529a3444d9SMark Johnston #else
1539a3444d9SMark Johnston 	sc->has_aes_gcm = false;
1549a3444d9SMark Johnston #endif
155fd86ae68SMitchell Horne }
156