]>
Commit | Line | Data |
---|---|---|
19b8d06a | 1 | /* ==================================================================== |
48fc582f | 2 | * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. |
19b8d06a BM |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions | |
6 | * are met: | |
7 | * | |
8 | * 1. Redistributions of source code must retain the above copyright | |
0f113f3e | 9 | * notice, this list of conditions and the following disclaimer. |
19b8d06a BM |
10 | * |
11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in | |
13 | * the documentation and/or other materials provided with the | |
14 | * distribution. | |
15 | * | |
16 | * 3. All advertising materials mentioning features or use of this | |
17 | * software must display the following acknowledgment: | |
18 | * "This product includes software developed by the OpenSSL Project | |
19 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | |
20 | * | |
21 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
22 | * endorse or promote products derived from this software without | |
23 | * prior written permission. For written permission, please contact | |
24 | * openssl-core@openssl.org. | |
25 | * | |
26 | * 5. Products derived from this software may not be called "OpenSSL" | |
27 | * nor may "OpenSSL" appear in their names without prior written | |
28 | * permission of the OpenSSL Project. | |
29 | * | |
30 | * 6. Redistributions of any form whatsoever must retain the following | |
31 | * acknowledgment: | |
32 | * "This product includes software developed by the OpenSSL Project | |
33 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" | |
34 | * | |
35 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
36 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
37 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
38 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
39 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
40 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
41 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
42 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
43 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
44 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
45 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
46 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
47 | * ==================================================================== | |
48 | * | |
49 | * This product includes cryptographic software written by Eric Young | |
50 | * (eay@cryptsoft.com). This product includes software written by Tim | |
51 | * Hudson (tjh@cryptsoft.com). | |
52 | * | |
53 | */ | |
58964a49 | 54 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
d02b48c6 RE |
55 | * All rights reserved. |
56 | * | |
57 | * This package is an SSL implementation written | |
58 | * by Eric Young (eay@cryptsoft.com). | |
59 | * The implementation was written so as to conform with Netscapes SSL. | |
0f113f3e | 60 | * |
d02b48c6 RE |
61 | * This library is free for commercial and non-commercial use as long as |
62 | * the following conditions are aheared to. The following conditions | |
63 | * apply to all code found in this distribution, be it the RC4, RSA, | |
64 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation | |
65 | * included with this distribution is covered by the same copyright terms | |
66 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). | |
0f113f3e | 67 | * |
d02b48c6 RE |
68 | * Copyright remains Eric Young's, and as such any Copyright notices in |
69 | * the code are not to be removed. | |
70 | * If this package is used in a product, Eric Young should be given attribution | |
71 | * as the author of the parts of the library used. | |
72 | * This can be in the form of a textual message at program startup or | |
73 | * in documentation (online or textual) provided with the package. | |
0f113f3e | 74 | * |
d02b48c6 RE |
75 | * Redistribution and use in source and binary forms, with or without |
76 | * modification, are permitted provided that the following conditions | |
77 | * are met: | |
78 | * 1. Redistributions of source code must retain the copyright | |
79 | * notice, this list of conditions and the following disclaimer. | |
80 | * 2. Redistributions in binary form must reproduce the above copyright | |
81 | * notice, this list of conditions and the following disclaimer in the | |
82 | * documentation and/or other materials provided with the distribution. | |
83 | * 3. All advertising materials mentioning features or use of this software | |
84 | * must display the following acknowledgement: | |
85 | * "This product includes cryptographic software written by | |
86 | * Eric Young (eay@cryptsoft.com)" | |
87 | * The word 'cryptographic' can be left out if the rouines from the library | |
88 | * being used are not cryptographic related :-). | |
0f113f3e | 89 | * 4. If you include any Windows specific code (or a derivative thereof) from |
d02b48c6 RE |
90 | * the apps directory (application code) you must include an acknowledgement: |
91 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | |
0f113f3e | 92 | * |
d02b48c6 RE |
93 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
94 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
95 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
96 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
97 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
98 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
99 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
100 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
101 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
102 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
103 | * SUCH DAMAGE. | |
0f113f3e | 104 | * |
d02b48c6 RE |
105 | * The licence and distribution terms for any publically available version or |
106 | * derivative of this code cannot be changed. i.e. this code cannot simply be | |
107 | * copied and put under another distribution licence | |
108 | * [including the GNU Public Licence.] | |
109 | */ | |
e172d60d BM |
110 | /* ==================================================================== |
111 | * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. | |
0f113f3e | 112 | * ECDH support in OpenSSL originally developed by |
e172d60d BM |
113 | * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. |
114 | */ | |
d02b48c6 | 115 | |
b39fc560 | 116 | #include "internal/cryptlib.h" |
c7922304 | 117 | #include <openssl/safestack.h> |
d02b48c6 | 118 | |
0f113f3e MC |
119 | #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ |
120 | defined(__INTEL__) || \ | |
121 | defined(__x86_64) || defined(__x86_64__) || \ | |
122 | defined(_M_AMD64) || defined(_M_X64) | |
14e21f86 | 123 | |
0f113f3e MC |
124 | extern unsigned int OPENSSL_ia32cap_P[4]; |
125 | unsigned int *OPENSSL_ia32cap_loc(void) | |
126 | { | |
127 | return OPENSSL_ia32cap_P; | |
128 | } | |
14e21f86 | 129 | |
0f113f3e | 130 | # if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY) |
984d6c60 | 131 | #include <stdio.h> |
0f113f3e | 132 | # define OPENSSL_CPUID_SETUP |
1c7b2c0e | 133 | typedef uint64_t IA32CAP; |
2b247cf8 | 134 | void OPENSSL_cpuid_setup(void) |
0f113f3e MC |
135 | { |
136 | static int trigger = 0; | |
137 | IA32CAP OPENSSL_ia32_cpuid(unsigned int *); | |
138 | IA32CAP vec; | |
139 | char *env; | |
140 | ||
141 | if (trigger) | |
142 | return; | |
143 | ||
144 | trigger = 1; | |
145 | if ((env = getenv("OPENSSL_ia32cap"))) { | |
146 | int off = (env[0] == '~') ? 1 : 0; | |
147 | # if defined(_WIN32) | |
148 | if (!sscanf(env + off, "%I64i", &vec)) | |
149 | vec = strtoul(env + off, NULL, 0); | |
150 | # else | |
151 | if (!sscanf(env + off, "%lli", (long long *)&vec)) | |
152 | vec = strtoul(env + off, NULL, 0); | |
153 | # endif | |
154 | if (off) | |
155 | vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~vec; | |
156 | else if (env[0] == ':') | |
157 | vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); | |
158 | ||
159 | OPENSSL_ia32cap_P[2] = 0; | |
160 | if ((env = strchr(env, ':'))) { | |
161 | unsigned int vecx; | |
162 | env++; | |
163 | off = (env[0] == '~') ? 1 : 0; | |
164 | vecx = strtoul(env + off, NULL, 0); | |
165 | if (off) | |
166 | OPENSSL_ia32cap_P[2] &= ~vecx; | |
167 | else | |
168 | OPENSSL_ia32cap_P[2] = vecx; | |
169 | } | |
170 | } else | |
171 | vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); | |
e303f55f | 172 | |
14e21f86 AP |
173 | /* |
174 | * |(1<<10) sets a reserved bit to signal that variable | |
175 | * was initialized already... This is to avoid interference | |
176 | * with cpuid snippets in ELF .init segment. | |
177 | */ | |
0f113f3e MC |
178 | OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10); |
179 | OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32); | |
14e21f86 | 180 | } |
0f113f3e | 181 | # else |
c5cd28bd | 182 | unsigned int OPENSSL_ia32cap_P[4]; |
0f113f3e | 183 | # endif |
14e21f86 | 184 | |
630e4a6e | 185 | #else |
0f113f3e MC |
186 | unsigned int *OPENSSL_ia32cap_loc(void) |
187 | { | |
188 | return NULL; | |
189 | } | |
14e21f86 | 190 | #endif |
1875e6db | 191 | int OPENSSL_NONPIC_relocated = 0; |
a00e414f | 192 | #if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ) |
0f113f3e MC |
193 | void OPENSSL_cpuid_setup(void) |
194 | { | |
195 | } | |
14e21f86 AP |
196 | #endif |
197 | ||
e1d51de4 | 198 | #if (defined(_WIN32) || defined(__CYGWIN__)) && defined(_WINDLL) |
0f113f3e | 199 | # ifdef __CYGWIN__ |
c7709441 | 200 | /* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */ |
0f113f3e MC |
201 | # include <windows.h> |
202 | /* | |
203 | * this has side-effect of _WIN32 getting defined, which otherwise is | |
204 | * mutually exclusive with __CYGWIN__... | |
205 | */ | |
206 | # endif | |
d02b48c6 | 207 | |
0f113f3e MC |
208 | /* |
209 | * All we really need to do is remove the 'error' state when a thread | |
210 | * detaches | |
211 | */ | |
d02b48c6 | 212 | |
0f113f3e MC |
213 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) |
214 | { | |
215 | switch (fdwReason) { | |
216 | case DLL_PROCESS_ATTACH: | |
217 | OPENSSL_cpuid_setup(); | |
218 | # if defined(_WIN32_WINNT) | |
219 | { | |
220 | IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *) hinstDLL; | |
221 | IMAGE_NT_HEADERS *nt_headers; | |
222 | ||
223 | if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) { | |
224 | nt_headers = (IMAGE_NT_HEADERS *) ((char *)dos_header | |
225 | + dos_header->e_lfanew); | |
226 | if (nt_headers->Signature == IMAGE_NT_SIGNATURE && | |
227 | hinstDLL != | |
228 | (HINSTANCE) (nt_headers->OptionalHeader.ImageBase)) | |
229 | OPENSSL_NONPIC_relocated = 1; | |
230 | } | |
231 | } | |
232 | # endif | |
233 | break; | |
234 | case DLL_THREAD_ATTACH: | |
235 | break; | |
236 | case DLL_THREAD_DETACH: | |
237 | break; | |
238 | case DLL_PROCESS_DETACH: | |
239 | break; | |
240 | } | |
241 | return (TRUE); | |
242 | } | |
e322fa28 | 243 | #endif |
9f2027e5 | 244 | |
0f113f3e MC |
245 | #if defined(_WIN32) && !defined(__CYGWIN__) |
246 | # include <tchar.h> | |
247 | # include <signal.h> | |
248 | # ifdef __WATCOMC__ | |
249 | # if defined(_UNICODE) || defined(__UNICODE__) | |
250 | # define _vsntprintf _vsnwprintf | |
251 | # else | |
252 | # define _vsntprintf _vsnprintf | |
253 | # endif | |
254 | # endif | |
255 | # ifdef _MSC_VER | |
256 | # define alloca _alloca | |
257 | # endif | |
258 | ||
259 | # if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 | |
e476f942 | 260 | int OPENSSL_isservice(void) |
0f113f3e MC |
261 | { |
262 | HWINSTA h; | |
263 | DWORD len; | |
264 | WCHAR *name; | |
265 | static union { | |
266 | void *p; | |
156561b0 | 267 | FARPROC f; |
0f113f3e MC |
268 | } _OPENSSL_isservice = { |
269 | NULL | |
270 | }; | |
471d0eb3 AP |
271 | |
272 | if (_OPENSSL_isservice.p == NULL) { | |
156561b0 AP |
273 | HANDLE mod = GetModuleHandle(NULL); |
274 | if (mod != NULL) | |
275 | _OPENSSL_isservice.f = GetProcAddress(mod, "_OPENSSL_isservice"); | |
0f113f3e MC |
276 | if (_OPENSSL_isservice.p == NULL) |
277 | _OPENSSL_isservice.p = (void *)-1; | |
471d0eb3 AP |
278 | } |
279 | ||
280 | if (_OPENSSL_isservice.p != (void *)-1) | |
0f113f3e | 281 | return (*_OPENSSL_isservice.f) (); |
9f2027e5 | 282 | |
9f2027e5 | 283 | h = GetProcessWindowStation(); |
0f113f3e MC |
284 | if (h == NULL) |
285 | return -1; | |
286 | ||
287 | if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) || | |
288 | GetLastError() != ERROR_INSUFFICIENT_BUFFER) | |
289 | return -1; | |
290 | ||
291 | if (len > 512) | |
292 | return -1; /* paranoia */ | |
293 | len++, len &= ~1; /* paranoia */ | |
294 | name = (WCHAR *)alloca(len + sizeof(WCHAR)); | |
295 | if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len)) | |
296 | return -1; | |
297 | ||
298 | len++, len &= ~1; /* paranoia */ | |
299 | name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */ | |
300 | # if 1 | |
301 | /* | |
302 | * This doesn't cover "interactive" services [working with real | |
303 | * WinSta0's] nor programs started non-interactively by Task Scheduler | |
304 | * [those are working with SAWinSta]. | |
305 | */ | |
306 | if (wcsstr(name, L"Service-0x")) | |
307 | return 1; | |
308 | # else | |
9f2027e5 | 309 | /* This covers all non-interactive programs such as services. */ |
0f113f3e MC |
310 | if (!wcsstr(name, L"WinSta0")) |
311 | return 1; | |
312 | # endif | |
313 | else | |
314 | return 0; | |
9f2027e5 | 315 | } |
0f113f3e MC |
316 | # else |
317 | int OPENSSL_isservice(void) | |
318 | { | |
319 | return 0; | |
320 | } | |
321 | # endif | |
322 | ||
323 | void OPENSSL_showfatal(const char *fmta, ...) | |
324 | { | |
325 | va_list ap; | |
326 | TCHAR buf[256]; | |
327 | const TCHAR *fmt; | |
328 | # ifdef STD_ERROR_HANDLE /* what a dirty trick! */ | |
329 | HANDLE h; | |
330 | ||
331 | if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL && | |
332 | GetFileType(h) != FILE_TYPE_UNKNOWN) { | |
333 | /* must be console application */ | |
334 | int len; | |
335 | DWORD out; | |
336 | ||
337 | va_start(ap, fmta); | |
338 | len = _vsnprintf((char *)buf, sizeof(buf), fmta, ap); | |
339 | WriteFile(h, buf, len < 0 ? sizeof(buf) : (DWORD) len, &out, NULL); | |
340 | va_end(ap); | |
341 | return; | |
9f2027e5 | 342 | } |
0f113f3e | 343 | # endif |
9f2027e5 | 344 | |
0f113f3e MC |
345 | if (sizeof(TCHAR) == sizeof(char)) |
346 | fmt = (const TCHAR *)fmta; | |
9f2027e5 | 347 | else |
0f113f3e MC |
348 | do { |
349 | int keepgoing; | |
350 | size_t len_0 = strlen(fmta) + 1, i; | |
351 | WCHAR *fmtw; | |
352 | ||
353 | fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR)); | |
354 | if (fmtw == NULL) { | |
355 | fmt = (const TCHAR *)L"no stack?"; | |
356 | break; | |
357 | } | |
0f113f3e | 358 | if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0)) |
0f113f3e MC |
359 | for (i = 0; i < len_0; i++) |
360 | fmtw[i] = (WCHAR)fmta[i]; | |
0f113f3e MC |
361 | for (i = 0; i < len_0; i++) { |
362 | if (fmtw[i] == L'%') | |
363 | do { | |
364 | keepgoing = 0; | |
365 | switch (fmtw[i + 1]) { | |
366 | case L'0': | |
367 | case L'1': | |
368 | case L'2': | |
369 | case L'3': | |
370 | case L'4': | |
371 | case L'5': | |
372 | case L'6': | |
373 | case L'7': | |
374 | case L'8': | |
375 | case L'9': | |
376 | case L'.': | |
377 | case L'*': | |
378 | case L'-': | |
379 | i++; | |
380 | keepgoing = 1; | |
381 | break; | |
382 | case L's': | |
383 | fmtw[i + 1] = L'S'; | |
384 | break; | |
385 | case L'S': | |
386 | fmtw[i + 1] = L's'; | |
387 | break; | |
388 | case L'c': | |
389 | fmtw[i + 1] = L'C'; | |
390 | break; | |
391 | case L'C': | |
392 | fmtw[i + 1] = L'c'; | |
393 | break; | |
394 | } | |
395 | } while (keepgoing); | |
396 | } | |
397 | fmt = (const TCHAR *)fmtw; | |
398 | } while (0); | |
399 | ||
400 | va_start(ap, fmta); | |
bdcb1a2c DSH |
401 | _vsntprintf(buf, OSSL_NELEM(buf) - 1, fmt, ap); |
402 | buf[OSSL_NELEM(buf) - 1] = _T('\0'); | |
0f113f3e MC |
403 | va_end(ap); |
404 | ||
405 | # if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 | |
406 | /* this -------------v--- guards NT-specific calls */ | |
407 | if (check_winnt() && OPENSSL_isservice() > 0) { | |
4cd94416 GK |
408 | HANDLE hEventLog = RegisterEventSource(NULL, _T("OpenSSL")); |
409 | ||
410 | if (hEventLog != NULL) { | |
411 | const TCHAR *pmsg = buf; | |
412 | ||
413 | if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL, | |
414 | 1, 0, &pmsg, NULL)) { | |
415 | #if defined(DEBUG) | |
416 | /* | |
417 | * We are in a situation where we tried to report a critical | |
418 | * error and this failed for some reason. As a last resort, | |
419 | * in debug builds, send output to the debugger or any other | |
420 | * tool like DebugView which can monitor the output. | |
421 | */ | |
422 | OutputDebugString(pmsg); | |
423 | #endif | |
424 | } | |
425 | ||
426 | (void)DeregisterEventSource(hEventLog); | |
427 | } | |
0f113f3e MC |
428 | } else |
429 | # endif | |
4cd94416 | 430 | MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR); |
9f2027e5 AP |
431 | } |
432 | #else | |
0f113f3e MC |
433 | void OPENSSL_showfatal(const char *fmta, ...) |
434 | { | |
984d6c60 | 435 | #ifndef OPENSSL_NO_STDIO |
0f113f3e MC |
436 | va_list ap; |
437 | ||
438 | va_start(ap, fmta); | |
439 | vfprintf(stderr, fmta, ap); | |
440 | va_end(ap); | |
984d6c60 | 441 | #endif |
0f113f3e | 442 | } |
9f2027e5 | 443 | |
0f113f3e MC |
444 | int OPENSSL_isservice(void) |
445 | { | |
446 | return 0; | |
9f2027e5 AP |
447 | } |
448 | #endif | |
449 | ||
0f113f3e MC |
450 | void OpenSSLDie(const char *file, int line, const char *assertion) |
451 | { | |
452 | OPENSSL_showfatal | |
453 | ("%s(%d): OpenSSL internal error, assertion failed: %s\n", file, line, | |
454 | assertion); | |
6022fe81 | 455 | #if !defined(_WIN32) || defined(__CYGWIN__) |
0f113f3e | 456 | abort(); |
3b58c74c | 457 | #else |
0f113f3e MC |
458 | /* |
459 | * Win32 abort() customarily shows a dialog, but we just did that... | |
460 | */ | |
461 | # if !defined(_WIN32_WCE) | |
462 | raise(SIGABRT); | |
463 | # endif | |
464 | _exit(3); | |
3b58c74c | 465 | #endif |
0f113f3e | 466 | } |
9e88c827 | 467 | |
7c770d57 | 468 | int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) |
0f113f3e MC |
469 | { |
470 | size_t i; | |
471 | const unsigned char *a = in_a; | |
472 | const unsigned char *b = in_b; | |
473 | unsigned char x = 0; | |
7c770d57 | 474 | |
0f113f3e MC |
475 | for (i = 0; i < len; i++) |
476 | x |= a[i] ^ b[i]; | |
7c770d57 | 477 | |
0f113f3e MC |
478 | return x; |
479 | } |