Add flag to inhibit checking for alternate certificate chains. Setting this
[openssl.git] / crypto / ppccap.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <setjmp.h>
5 #include <signal.h>
6 #include <unistd.h>
7 #if defined(__linux) || defined(_AIX)
8 # include <sys/utsname.h>
9 #endif
10 #include <crypto.h>
11 #include <openssl/bn.h>
12
13 #include "ppc_arch.h"
14
15 unsigned int OPENSSL_ppccap_P = 0;
16
17 static sigset_t all_masked;
18
19 #ifdef OPENSSL_BN_ASM_MONT
20 int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
21                 const BN_ULONG *np, const BN_ULONG *n0, int num)
22 {
23     int bn_mul_mont_fpu64(BN_ULONG *rp, const BN_ULONG *ap,
24                           const BN_ULONG *bp, const BN_ULONG *np,
25                           const BN_ULONG *n0, int num);
26     int bn_mul_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
27                         const BN_ULONG *np, const BN_ULONG *n0, int num);
28
29     if (sizeof(size_t) == 4) {
30 # if 1 || (defined(__APPLE__) && defined(__MACH__))
31         if (num >= 8 && (num & 3) == 0 && (OPENSSL_ppccap_P & PPC_FPU64))
32             return bn_mul_mont_fpu64(rp, ap, bp, np, n0, num);
33 # else
34         /*
35          * boundary of 32 was experimentally determined on Linux 2.6.22,
36          * might have to be adjusted on AIX...
37          */
38         if (num >= 32 && (num & 3) == 0 && (OPENSSL_ppccap_P & PPC_FPU64)) {
39             sigset_t oset;
40             int ret;
41
42             sigprocmask(SIG_SETMASK, &all_masked, &oset);
43             ret = bn_mul_mont_fpu64(rp, ap, bp, np, n0, num);
44             sigprocmask(SIG_SETMASK, &oset, NULL);
45
46             return ret;
47         }
48 # endif
49     } else if ((OPENSSL_ppccap_P & PPC_FPU64))
50         /*
51          * this is a "must" on POWER6, but run-time detection is not
52          * implemented yet...
53          */
54         return bn_mul_mont_fpu64(rp, ap, bp, np, n0, num);
55
56     return bn_mul_mont_int(rp, ap, bp, np, n0, num);
57 }
58 #endif
59
60 void sha256_block_p8(void *ctx, const void *inp, size_t len);
61 void sha256_block_ppc(void *ctx, const void *inp, size_t len);
62 void sha256_block_data_order(void *ctx, const void *inp, size_t len)
63 {
64     OPENSSL_ppccap_P & PPC_CRYPTO207 ? sha256_block_p8(ctx, inp, len) :
65         sha256_block_ppc(ctx, inp, len);
66 }
67
68 void sha512_block_p8(void *ctx, const void *inp, size_t len);
69 void sha512_block_ppc(void *ctx, const void *inp, size_t len);
70 void sha512_block_data_order(void *ctx, const void *inp, size_t len)
71 {
72     OPENSSL_ppccap_P & PPC_CRYPTO207 ? sha512_block_p8(ctx, inp, len) :
73         sha512_block_ppc(ctx, inp, len);
74 }
75
76 static sigjmp_buf ill_jmp;
77 static void ill_handler(int sig)
78 {
79     siglongjmp(ill_jmp, sig);
80 }
81
82 void OPENSSL_ppc64_probe(void);
83 void OPENSSL_altivec_probe(void);
84 void OPENSSL_crypto207_probe(void);
85
86 void OPENSSL_cpuid_setup(void)
87 {
88     char *e;
89     struct sigaction ill_oact, ill_act;
90     sigset_t oset;
91     static int trigger = 0;
92
93     if (trigger)
94         return;
95     trigger = 1;
96
97     sigfillset(&all_masked);
98     sigdelset(&all_masked, SIGILL);
99     sigdelset(&all_masked, SIGTRAP);
100 #ifdef SIGEMT
101     sigdelset(&all_masked, SIGEMT);
102 #endif
103     sigdelset(&all_masked, SIGFPE);
104     sigdelset(&all_masked, SIGBUS);
105     sigdelset(&all_masked, SIGSEGV);
106
107     if ((e = getenv("OPENSSL_ppccap"))) {
108         OPENSSL_ppccap_P = strtoul(e, NULL, 0);
109         return;
110     }
111
112     OPENSSL_ppccap_P = 0;
113
114 #if defined(_AIX)
115     if (sizeof(size_t) == 4) {
116         struct utsname uts;
117 # if defined(_SC_AIX_KERNEL_BITMODE)
118         if (sysconf(_SC_AIX_KERNEL_BITMODE) != 64)
119             return;
120 # endif
121         if (uname(&uts) != 0 || atoi(uts.version) < 6)
122             return;
123     }
124 #endif
125
126     memset(&ill_act, 0, sizeof(ill_act));
127     ill_act.sa_handler = ill_handler;
128     ill_act.sa_mask = all_masked;
129
130     sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
131     sigaction(SIGILL, &ill_act, &ill_oact);
132
133     if (sizeof(size_t) == 4) {
134 #ifdef __linux
135         struct utsname uts;
136         if (uname(&uts) == 0 && strcmp(uts.machine, "ppc64") == 0)
137 #endif
138             if (sigsetjmp(ill_jmp, 1) == 0) {
139                 OPENSSL_ppc64_probe();
140                 OPENSSL_ppccap_P |= PPC_FPU64;
141             }
142     } else {
143         /*
144          * Wanted code detecting POWER6 CPU and setting PPC_FPU64
145          */
146     }
147
148     if (sigsetjmp(ill_jmp, 1) == 0) {
149         OPENSSL_altivec_probe();
150         OPENSSL_ppccap_P |= PPC_ALTIVEC;
151         if (sigsetjmp(ill_jmp, 1) == 0) {
152             OPENSSL_crypto207_probe();
153             OPENSSL_ppccap_P |= PPC_CRYPTO207;
154         }
155     }
156
157     sigaction(SIGILL, &ill_oact, NULL);
158     sigprocmask(SIG_SETMASK, &oset, NULL);
159 }