1 | /*
|
---|
2 | * Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | *
|
---|
4 | * Licensed under the OpenSSL license (the "License"). You may not use
|
---|
5 | * this file except in compliance with the License. You can obtain a copy
|
---|
6 | * in the file LICENSE in the source distribution or at
|
---|
7 | * https://www.openssl.org/source/license.html
|
---|
8 | */
|
---|
9 |
|
---|
10 | #include <stdio.h>
|
---|
11 | #include <stdlib.h>
|
---|
12 | #include <string.h>
|
---|
13 | #include <setjmp.h>
|
---|
14 | #include <signal.h>
|
---|
15 | #include <sys/time.h>
|
---|
16 | #include <unistd.h>
|
---|
17 | #include <openssl/bn.h>
|
---|
18 | #include "internal/cryptlib.h"
|
---|
19 |
|
---|
20 | #include "sparc_arch.h"
|
---|
21 |
|
---|
22 | #if defined(__GNUC__) && defined(__linux)
|
---|
23 | __attribute__ ((visibility("hidden")))
|
---|
24 | #endif
|
---|
25 | unsigned int OPENSSL_sparcv9cap_P[2] = { SPARCV9_TICK_PRIVILEGED, 0 };
|
---|
26 |
|
---|
27 | int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
---|
28 | const BN_ULONG *np, const BN_ULONG *n0, int num)
|
---|
29 | {
|
---|
30 | int bn_mul_mont_vis3(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
---|
31 | const BN_ULONG *np, const BN_ULONG *n0, int num);
|
---|
32 | int bn_mul_mont_fpu(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
---|
33 | const BN_ULONG *np, const BN_ULONG *n0, int num);
|
---|
34 | int bn_mul_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
---|
35 | const BN_ULONG *np, const BN_ULONG *n0, int num);
|
---|
36 |
|
---|
37 | if (!(num & 1) && num >= 6) {
|
---|
38 | if ((num & 15) == 0 && num <= 64 &&
|
---|
39 | (OPENSSL_sparcv9cap_P[1] & (CFR_MONTMUL | CFR_MONTSQR)) ==
|
---|
40 | (CFR_MONTMUL | CFR_MONTSQR)) {
|
---|
41 | typedef int (*bn_mul_mont_f) (BN_ULONG *rp, const BN_ULONG *ap,
|
---|
42 | const BN_ULONG *bp,
|
---|
43 | const BN_ULONG *np,
|
---|
44 | const BN_ULONG *n0);
|
---|
45 | int bn_mul_mont_t4_8(BN_ULONG *rp, const BN_ULONG *ap,
|
---|
46 | const BN_ULONG *bp, const BN_ULONG *np,
|
---|
47 | const BN_ULONG *n0);
|
---|
48 | int bn_mul_mont_t4_16(BN_ULONG *rp, const BN_ULONG *ap,
|
---|
49 | const BN_ULONG *bp, const BN_ULONG *np,
|
---|
50 | const BN_ULONG *n0);
|
---|
51 | int bn_mul_mont_t4_24(BN_ULONG *rp, const BN_ULONG *ap,
|
---|
52 | const BN_ULONG *bp, const BN_ULONG *np,
|
---|
53 | const BN_ULONG *n0);
|
---|
54 | int bn_mul_mont_t4_32(BN_ULONG *rp, const BN_ULONG *ap,
|
---|
55 | const BN_ULONG *bp, const BN_ULONG *np,
|
---|
56 | const BN_ULONG *n0);
|
---|
57 | static const bn_mul_mont_f funcs[4] = {
|
---|
58 | bn_mul_mont_t4_8, bn_mul_mont_t4_16,
|
---|
59 | bn_mul_mont_t4_24, bn_mul_mont_t4_32
|
---|
60 | };
|
---|
61 | bn_mul_mont_f worker = funcs[num / 16 - 1];
|
---|
62 |
|
---|
63 | if ((*worker) (rp, ap, bp, np, n0))
|
---|
64 | return 1;
|
---|
65 | /* retry once and fall back */
|
---|
66 | if ((*worker) (rp, ap, bp, np, n0))
|
---|
67 | return 1;
|
---|
68 | return bn_mul_mont_vis3(rp, ap, bp, np, n0, num);
|
---|
69 | }
|
---|
70 | if ((OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3))
|
---|
71 | return bn_mul_mont_vis3(rp, ap, bp, np, n0, num);
|
---|
72 | else if (num >= 8 &&
|
---|
73 | /*
|
---|
74 | * bn_mul_mont_fpu doesn't use FMADD, we just use the
|
---|
75 | * flag to detect when FPU path is preferable in cases
|
---|
76 | * when current heuristics is unreliable. [it works
|
---|
77 | * out because FMADD-capable processors where FPU
|
---|
78 | * code path is undesirable are also VIS3-capable and
|
---|
79 | * VIS3 code path takes precedence.]
|
---|
80 | */
|
---|
81 | ( (OPENSSL_sparcv9cap_P[0] & SPARCV9_FMADD) ||
|
---|
82 | (OPENSSL_sparcv9cap_P[0] &
|
---|
83 | (SPARCV9_PREFER_FPU | SPARCV9_VIS1)) ==
|
---|
84 | (SPARCV9_PREFER_FPU | SPARCV9_VIS1) ))
|
---|
85 | return bn_mul_mont_fpu(rp, ap, bp, np, n0, num);
|
---|
86 | }
|
---|
87 | return bn_mul_mont_int(rp, ap, bp, np, n0, num);
|
---|
88 | }
|
---|
89 |
|
---|
90 | unsigned long _sparcv9_rdtick(void);
|
---|
91 | void _sparcv9_vis1_probe(void);
|
---|
92 | unsigned long _sparcv9_vis1_instrument(void);
|
---|
93 | void _sparcv9_vis2_probe(void);
|
---|
94 | void _sparcv9_fmadd_probe(void);
|
---|
95 | unsigned long _sparcv9_rdcfr(void);
|
---|
96 | void _sparcv9_vis3_probe(void);
|
---|
97 | void _sparcv9_fjaesx_probe(void);
|
---|
98 | unsigned long _sparcv9_random(void);
|
---|
99 | size_t _sparcv9_vis1_instrument_bus(unsigned int *, size_t);
|
---|
100 | size_t _sparcv9_vis1_instrument_bus2(unsigned int *, size_t, size_t);
|
---|
101 |
|
---|
102 | uint32_t OPENSSL_rdtsc(void)
|
---|
103 | {
|
---|
104 | if (OPENSSL_sparcv9cap_P[0] & SPARCV9_TICK_PRIVILEGED)
|
---|
105 | #if defined(__sun) && defined(__SVR4)
|
---|
106 | return gethrtime();
|
---|
107 | #else
|
---|
108 | return 0;
|
---|
109 | #endif
|
---|
110 | else
|
---|
111 | return _sparcv9_rdtick();
|
---|
112 | }
|
---|
113 |
|
---|
114 | size_t OPENSSL_instrument_bus(unsigned int *out, size_t cnt)
|
---|
115 | {
|
---|
116 | if ((OPENSSL_sparcv9cap_P[0] & (SPARCV9_TICK_PRIVILEGED | SPARCV9_BLK)) ==
|
---|
117 | SPARCV9_BLK)
|
---|
118 | return _sparcv9_vis1_instrument_bus(out, cnt);
|
---|
119 | else
|
---|
120 | return 0;
|
---|
121 | }
|
---|
122 |
|
---|
123 | size_t OPENSSL_instrument_bus2(unsigned int *out, size_t cnt, size_t max)
|
---|
124 | {
|
---|
125 | if ((OPENSSL_sparcv9cap_P[0] & (SPARCV9_TICK_PRIVILEGED | SPARCV9_BLK)) ==
|
---|
126 | SPARCV9_BLK)
|
---|
127 | return _sparcv9_vis1_instrument_bus2(out, cnt, max);
|
---|
128 | else
|
---|
129 | return 0;
|
---|
130 | }
|
---|
131 |
|
---|
132 | static sigjmp_buf common_jmp;
|
---|
133 | static void common_handler(int sig)
|
---|
134 | {
|
---|
135 | siglongjmp(common_jmp, sig);
|
---|
136 | }
|
---|
137 |
|
---|
138 | #if defined(__sun) && defined(__SVR4)
|
---|
139 | # if defined(__GNUC__) && __GNUC__>=2
|
---|
140 | extern unsigned int getisax(unsigned int vec[], unsigned int sz) __attribute__ ((weak));
|
---|
141 | # elif defined(__SUNPRO_C)
|
---|
142 | #pragma weak getisax
|
---|
143 | extern unsigned int getisax(unsigned int vec[], unsigned int sz);
|
---|
144 | # else
|
---|
145 | static unsigned int (*getisax) (unsigned int vec[], unsigned int sz) = NULL;
|
---|
146 | # endif
|
---|
147 | #endif
|
---|
148 |
|
---|
149 | void OPENSSL_cpuid_setup(void)
|
---|
150 | {
|
---|
151 | char *e;
|
---|
152 | struct sigaction common_act, ill_oact, bus_oact;
|
---|
153 | sigset_t all_masked, oset;
|
---|
154 | static int trigger = 0;
|
---|
155 |
|
---|
156 | if (trigger)
|
---|
157 | return;
|
---|
158 | trigger = 1;
|
---|
159 |
|
---|
160 | if ((e = getenv("OPENSSL_sparcv9cap"))) {
|
---|
161 | OPENSSL_sparcv9cap_P[0] = strtoul(e, NULL, 0);
|
---|
162 | if ((e = strchr(e, ':')))
|
---|
163 | OPENSSL_sparcv9cap_P[1] = strtoul(e + 1, NULL, 0);
|
---|
164 | return;
|
---|
165 | }
|
---|
166 |
|
---|
167 | #if defined(__sun) && defined(__SVR4)
|
---|
168 | if (getisax != NULL) {
|
---|
169 | unsigned int vec[2] = { 0, 0 };
|
---|
170 |
|
---|
171 | if (getisax (vec,2)) {
|
---|
172 | if (vec[0]&0x00020) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS1;
|
---|
173 | if (vec[0]&0x00040) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS2;
|
---|
174 | if (vec[0]&0x00080) OPENSSL_sparcv9cap_P[0] |= SPARCV9_BLK;
|
---|
175 | if (vec[0]&0x00100) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FMADD;
|
---|
176 | if (vec[0]&0x00400) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS3;
|
---|
177 | if (vec[0]&0x01000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJHPCACE;
|
---|
178 | if (vec[0]&0x02000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJDESX;
|
---|
179 | if (vec[0]&0x08000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_IMA;
|
---|
180 | if (vec[0]&0x10000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJAESX;
|
---|
181 | if (vec[1]&0x00008) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS4;
|
---|
182 |
|
---|
183 | /* reconstruct %cfr copy */
|
---|
184 | OPENSSL_sparcv9cap_P[1] = (vec[0]>>17)&0x3ff;
|
---|
185 | OPENSSL_sparcv9cap_P[1] |= (OPENSSL_sparcv9cap_P[1]&CFR_MONTMUL)<<1;
|
---|
186 | if (vec[0]&0x20000000) OPENSSL_sparcv9cap_P[1] |= CFR_CRC32C;
|
---|
187 | if (vec[1]&0x00000020) OPENSSL_sparcv9cap_P[1] |= CFR_XMPMUL;
|
---|
188 | if (vec[1]&0x00000040)
|
---|
189 | OPENSSL_sparcv9cap_P[1] |= CFR_XMONTMUL|CFR_XMONTSQR;
|
---|
190 |
|
---|
191 | /* Some heuristics */
|
---|
192 | /* all known VIS2-capable CPUs have unprivileged tick counter */
|
---|
193 | if (OPENSSL_sparcv9cap_P[0]&SPARCV9_VIS2)
|
---|
194 | OPENSSL_sparcv9cap_P[0] &= ~SPARCV9_TICK_PRIVILEGED;
|
---|
195 |
|
---|
196 | OPENSSL_sparcv9cap_P[0] |= SPARCV9_PREFER_FPU;
|
---|
197 |
|
---|
198 | /* detect UltraSPARC-Tx, see sparccpud.S for details... */
|
---|
199 | if ((OPENSSL_sparcv9cap_P[0]&SPARCV9_VIS1) &&
|
---|
200 | _sparcv9_vis1_instrument() >= 12)
|
---|
201 | OPENSSL_sparcv9cap_P[0] &= ~(SPARCV9_VIS1 | SPARCV9_PREFER_FPU);
|
---|
202 | }
|
---|
203 |
|
---|
204 | if (sizeof(size_t) == 8)
|
---|
205 | OPENSSL_sparcv9cap_P[0] |= SPARCV9_64BIT_STACK;
|
---|
206 |
|
---|
207 | return;
|
---|
208 | }
|
---|
209 | #endif
|
---|
210 |
|
---|
211 | /* Initial value, fits UltraSPARC-I&II... */
|
---|
212 | OPENSSL_sparcv9cap_P[0] = SPARCV9_PREFER_FPU | SPARCV9_TICK_PRIVILEGED;
|
---|
213 |
|
---|
214 | sigfillset(&all_masked);
|
---|
215 | sigdelset(&all_masked, SIGILL);
|
---|
216 | sigdelset(&all_masked, SIGTRAP);
|
---|
217 | # ifdef SIGEMT
|
---|
218 | sigdelset(&all_masked, SIGEMT);
|
---|
219 | # endif
|
---|
220 | sigdelset(&all_masked, SIGFPE);
|
---|
221 | sigdelset(&all_masked, SIGBUS);
|
---|
222 | sigdelset(&all_masked, SIGSEGV);
|
---|
223 | sigprocmask(SIG_SETMASK, &all_masked, &oset);
|
---|
224 |
|
---|
225 | memset(&common_act, 0, sizeof(common_act));
|
---|
226 | common_act.sa_handler = common_handler;
|
---|
227 | common_act.sa_mask = all_masked;
|
---|
228 |
|
---|
229 | sigaction(SIGILL, &common_act, &ill_oact);
|
---|
230 | sigaction(SIGBUS, &common_act, &bus_oact); /* T1 fails 16-bit ldda [on
|
---|
231 | * Linux] */
|
---|
232 |
|
---|
233 | if (sigsetjmp(common_jmp, 1) == 0) {
|
---|
234 | _sparcv9_rdtick();
|
---|
235 | OPENSSL_sparcv9cap_P[0] &= ~SPARCV9_TICK_PRIVILEGED;
|
---|
236 | }
|
---|
237 |
|
---|
238 | if (sigsetjmp(common_jmp, 1) == 0) {
|
---|
239 | _sparcv9_vis1_probe();
|
---|
240 | OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS1 | SPARCV9_BLK;
|
---|
241 | /* detect UltraSPARC-Tx, see sparccpud.S for details... */
|
---|
242 | if (_sparcv9_vis1_instrument() >= 12)
|
---|
243 | OPENSSL_sparcv9cap_P[0] &= ~(SPARCV9_VIS1 | SPARCV9_PREFER_FPU);
|
---|
244 | else {
|
---|
245 | _sparcv9_vis2_probe();
|
---|
246 | OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS2;
|
---|
247 | }
|
---|
248 | }
|
---|
249 |
|
---|
250 | if (sigsetjmp(common_jmp, 1) == 0) {
|
---|
251 | _sparcv9_fmadd_probe();
|
---|
252 | OPENSSL_sparcv9cap_P[0] |= SPARCV9_FMADD;
|
---|
253 | }
|
---|
254 |
|
---|
255 | /*
|
---|
256 | * VIS3 flag is tested independently from VIS1, unlike VIS2 that is,
|
---|
257 | * because VIS3 defines even integer instructions.
|
---|
258 | */
|
---|
259 | if (sigsetjmp(common_jmp, 1) == 0) {
|
---|
260 | _sparcv9_vis3_probe();
|
---|
261 | OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS3;
|
---|
262 | }
|
---|
263 |
|
---|
264 | if (sigsetjmp(common_jmp, 1) == 0) {
|
---|
265 | _sparcv9_fjaesx_probe();
|
---|
266 | OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJAESX;
|
---|
267 | }
|
---|
268 |
|
---|
269 | /*
|
---|
270 | * In wait for better solution _sparcv9_rdcfr is masked by
|
---|
271 | * VIS3 flag, because it goes to uninterruptible endless
|
---|
272 | * loop on UltraSPARC II running Solaris. Things might be
|
---|
273 | * different on Linux...
|
---|
274 | */
|
---|
275 | if ((OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3) &&
|
---|
276 | sigsetjmp(common_jmp, 1) == 0) {
|
---|
277 | OPENSSL_sparcv9cap_P[1] = (unsigned int)_sparcv9_rdcfr();
|
---|
278 | }
|
---|
279 |
|
---|
280 | sigaction(SIGBUS, &bus_oact, NULL);
|
---|
281 | sigaction(SIGILL, &ill_oact, NULL);
|
---|
282 |
|
---|
283 | sigprocmask(SIG_SETMASK, &oset, NULL);
|
---|
284 |
|
---|
285 | if (sizeof(size_t) == 8)
|
---|
286 | OPENSSL_sparcv9cap_P[0] |= SPARCV9_64BIT_STACK;
|
---|
287 | # ifdef __linux
|
---|
288 | else {
|
---|
289 | int ret = syscall(340);
|
---|
290 |
|
---|
291 | if (ret >= 0 && ret & 1)
|
---|
292 | OPENSSL_sparcv9cap_P[0] |= SPARCV9_64BIT_STACK;
|
---|
293 | }
|
---|
294 | # endif
|
---|
295 | }
|
---|