VirtualBox

source: vbox/trunk/src/libs/openssl-3.3.2/include/internal/constant_time.h@ 108358

最後變更 在這個檔案從108358是 108206,由 vboxsync 提交於 5 週 前

openssl-3.3.2: Exported all files to OSE and removed .scm-settings ​bugref:10757

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 13.5 KB
 
1/*
2 * Copyright 2014-2024 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (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#ifndef OSSL_INTERNAL_CONSTANT_TIME_H
11# define OSSL_INTERNAL_CONSTANT_TIME_H
12# ifndef RT_WITHOUT_PRAGMA_ONCE /* VBOX */
13# pragma once
14# endif /* VBOX */
15
16# include <stdlib.h>
17# include <string.h>
18# include <openssl/e_os2.h> /* For 'ossl_inline' */
19
20/*-
21 * The boolean methods return a bitmask of all ones (0xff...f) for true
22 * and 0 for false. This is useful for choosing a value based on the result
23 * of a conditional in constant time. For example,
24 * if (a < b) {
25 * c = a;
26 * } else {
27 * c = b;
28 * }
29 * can be written as
30 * unsigned int lt = constant_time_lt(a, b);
31 * c = constant_time_select(lt, a, b);
32 */
33
34/* Returns the given value with the MSB copied to all the other bits. */
35static ossl_inline unsigned int constant_time_msb(unsigned int a);
36/* Convenience method for uint32_t. */
37static ossl_inline uint32_t constant_time_msb_32(uint32_t a);
38/* Convenience method for uint64_t. */
39static ossl_inline uint64_t constant_time_msb_64(uint64_t a);
40
41/* Returns 0xff..f if a < b and 0 otherwise. */
42static ossl_inline unsigned int constant_time_lt(unsigned int a,
43 unsigned int b);
44/* Convenience method for getting an 8-bit mask. */
45static ossl_inline unsigned char constant_time_lt_8(unsigned int a,
46 unsigned int b);
47/* Convenience method for uint64_t. */
48static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b);
49
50/* Returns 0xff..f if a >= b and 0 otherwise. */
51static ossl_inline unsigned int constant_time_ge(unsigned int a,
52 unsigned int b);
53/* Convenience method for getting an 8-bit mask. */
54static ossl_inline unsigned char constant_time_ge_8(unsigned int a,
55 unsigned int b);
56
57/* Returns 0xff..f if a == 0 and 0 otherwise. */
58static ossl_inline unsigned int constant_time_is_zero(unsigned int a);
59/* Convenience method for getting an 8-bit mask. */
60static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a);
61/* Convenience method for getting a 32-bit mask. */
62static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a);
63
64/* Returns 0xff..f if a == b and 0 otherwise. */
65static ossl_inline unsigned int constant_time_eq(unsigned int a,
66 unsigned int b);
67/* Convenience method for getting an 8-bit mask. */
68static ossl_inline unsigned char constant_time_eq_8(unsigned int a,
69 unsigned int b);
70/* Signed integers. */
71static ossl_inline unsigned int constant_time_eq_int(int a, int b);
72/* Convenience method for getting an 8-bit mask. */
73static ossl_inline unsigned char constant_time_eq_int_8(int a, int b);
74
75/*-
76 * Returns (mask & a) | (~mask & b).
77 *
78 * When |mask| is all 1s or all 0s (as returned by the methods above),
79 * the select methods return either |a| (if |mask| is nonzero) or |b|
80 * (if |mask| is zero).
81 */
82static ossl_inline unsigned int constant_time_select(unsigned int mask,
83 unsigned int a,
84 unsigned int b);
85/* Convenience method for unsigned chars. */
86static ossl_inline unsigned char constant_time_select_8(unsigned char mask,
87 unsigned char a,
88 unsigned char b);
89
90/* Convenience method for uint32_t. */
91static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a,
92 uint32_t b);
93
94/* Convenience method for uint64_t. */
95static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a,
96 uint64_t b);
97/* Convenience method for signed integers. */
98static ossl_inline int constant_time_select_int(unsigned int mask, int a,
99 int b);
100
101
102static ossl_inline unsigned int constant_time_msb(unsigned int a)
103{
104 return 0 - (a >> (sizeof(a) * 8 - 1));
105}
106
107
108static ossl_inline uint32_t constant_time_msb_32(uint32_t a)
109{
110 return 0 - (a >> 31);
111}
112
113static ossl_inline uint64_t constant_time_msb_64(uint64_t a)
114{
115 return 0 - (a >> 63);
116}
117
118static ossl_inline size_t constant_time_msb_s(size_t a)
119{
120 return 0 - (a >> (sizeof(a) * 8 - 1));
121}
122
123static ossl_inline unsigned int constant_time_lt(unsigned int a,
124 unsigned int b)
125{
126 return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b)));
127}
128
129static ossl_inline size_t constant_time_lt_s(size_t a, size_t b)
130{
131 return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b)));
132}
133
134static ossl_inline unsigned char constant_time_lt_8(unsigned int a,
135 unsigned int b)
136{
137 return (unsigned char)constant_time_lt(a, b);
138}
139
140static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b)
141{
142 return constant_time_msb_64(a ^ ((a ^ b) | ((a - b) ^ b)));
143}
144
145#ifdef BN_ULONG
146static ossl_inline BN_ULONG constant_time_msb_bn(BN_ULONG a)
147{
148 return 0 - (a >> (sizeof(a) * 8 - 1));
149}
150
151static ossl_inline BN_ULONG constant_time_lt_bn(BN_ULONG a, BN_ULONG b)
152{
153 return constant_time_msb_bn(a ^ ((a ^ b) | ((a - b) ^ b)));
154}
155
156static ossl_inline BN_ULONG constant_time_is_zero_bn(BN_ULONG a)
157{
158 return constant_time_msb_bn(~a & (a - 1));
159}
160
161static ossl_inline BN_ULONG constant_time_eq_bn(BN_ULONG a,
162 BN_ULONG b)
163{
164 return constant_time_is_zero_bn(a ^ b);
165}
166#endif
167
168static ossl_inline unsigned int constant_time_ge(unsigned int a,
169 unsigned int b)
170{
171 return ~constant_time_lt(a, b);
172}
173
174static ossl_inline size_t constant_time_ge_s(size_t a, size_t b)
175{
176 return ~constant_time_lt_s(a, b);
177}
178
179static ossl_inline unsigned char constant_time_ge_8(unsigned int a,
180 unsigned int b)
181{
182 return (unsigned char)constant_time_ge(a, b);
183}
184
185static ossl_inline unsigned char constant_time_ge_8_s(size_t a, size_t b)
186{
187 return (unsigned char)constant_time_ge_s(a, b);
188}
189
190static ossl_inline unsigned int constant_time_is_zero(unsigned int a)
191{
192 return constant_time_msb(~a & (a - 1));
193}
194
195static ossl_inline size_t constant_time_is_zero_s(size_t a)
196{
197 return constant_time_msb_s(~a & (a - 1));
198}
199
200static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a)
201{
202 return (unsigned char)constant_time_is_zero(a);
203}
204
205static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a)
206{
207 return constant_time_msb_32(~a & (a - 1));
208}
209
210static ossl_inline uint64_t constant_time_is_zero_64(uint64_t a)
211{
212 return constant_time_msb_64(~a & (a - 1));
213}
214
215static ossl_inline unsigned int constant_time_eq(unsigned int a,
216 unsigned int b)
217{
218 return constant_time_is_zero(a ^ b);
219}
220
221static ossl_inline size_t constant_time_eq_s(size_t a, size_t b)
222{
223 return constant_time_is_zero_s(a ^ b);
224}
225
226static ossl_inline unsigned char constant_time_eq_8(unsigned int a,
227 unsigned int b)
228{
229 return (unsigned char)constant_time_eq(a, b);
230}
231
232static ossl_inline unsigned char constant_time_eq_8_s(size_t a, size_t b)
233{
234 return (unsigned char)constant_time_eq_s(a, b);
235}
236
237static ossl_inline unsigned int constant_time_eq_int(int a, int b)
238{
239 return constant_time_eq((unsigned)(a), (unsigned)(b));
240}
241
242static ossl_inline unsigned char constant_time_eq_int_8(int a, int b)
243{
244 return constant_time_eq_8((unsigned)(a), (unsigned)(b));
245}
246
247/*
248 * Returns the value unmodified, but avoids optimizations.
249 * The barriers prevent the compiler from narrowing down the
250 * possible value range of the mask and ~mask in the select
251 * statements, which avoids the recognition of the select
252 * and turning it into a conditional load or branch.
253 */
254static ossl_inline unsigned int value_barrier(unsigned int a)
255{
256#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
257 unsigned int r;
258 __asm__("" : "=r"(r) : "0"(a));
259#else
260 volatile unsigned int r = a;
261#endif
262 return r;
263}
264
265/* Convenience method for uint32_t. */
266static ossl_inline uint32_t value_barrier_32(uint32_t a)
267{
268#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
269 uint32_t r;
270 __asm__("" : "=r"(r) : "0"(a));
271#else
272 volatile uint32_t r = a;
273#endif
274 return r;
275}
276
277/* Convenience method for uint64_t. */
278static ossl_inline uint64_t value_barrier_64(uint64_t a)
279{
280#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
281 uint64_t r;
282 __asm__("" : "=r"(r) : "0"(a));
283#else
284 volatile uint64_t r = a;
285#endif
286 return r;
287}
288
289/* Convenience method for size_t. */
290static ossl_inline size_t value_barrier_s(size_t a)
291{
292#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
293 size_t r;
294 __asm__("" : "=r"(r) : "0"(a));
295#else
296 volatile size_t r = a;
297#endif
298 return r;
299}
300
301static ossl_inline unsigned int constant_time_select(unsigned int mask,
302 unsigned int a,
303 unsigned int b)
304{
305 return (value_barrier(mask) & a) | (value_barrier(~mask) & b);
306}
307
308static ossl_inline size_t constant_time_select_s(size_t mask,
309 size_t a,
310 size_t b)
311{
312 return (value_barrier_s(mask) & a) | (value_barrier_s(~mask) & b);
313}
314
315static ossl_inline unsigned char constant_time_select_8(unsigned char mask,
316 unsigned char a,
317 unsigned char b)
318{
319 return (unsigned char)constant_time_select(mask, a, b);
320}
321
322static ossl_inline int constant_time_select_int(unsigned int mask, int a,
323 int b)
324{
325 return (int)constant_time_select(mask, (unsigned)(a), (unsigned)(b));
326}
327
328static ossl_inline int constant_time_select_int_s(size_t mask, int a, int b)
329{
330 return (int)constant_time_select((unsigned)mask, (unsigned)(a),
331 (unsigned)(b));
332}
333
334static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a,
335 uint32_t b)
336{
337 return (value_barrier_32(mask) & a) | (value_barrier_32(~mask) & b);
338}
339
340static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a,
341 uint64_t b)
342{
343 return (value_barrier_64(mask) & a) | (value_barrier_64(~mask) & b);
344}
345
346/*
347 * mask must be 0xFFFFFFFF or 0x00000000.
348 *
349 * if (mask) {
350 * uint32_t tmp = *a;
351 *
352 * *a = *b;
353 * *b = tmp;
354 * }
355 */
356static ossl_inline void constant_time_cond_swap_32(uint32_t mask, uint32_t *a,
357 uint32_t *b)
358{
359 uint32_t xor = *a ^ *b;
360
361 xor &= mask;
362 *a ^= xor;
363 *b ^= xor;
364}
365
366/*
367 * mask must be 0xFFFFFFFF or 0x00000000.
368 *
369 * if (mask) {
370 * uint64_t tmp = *a;
371 *
372 * *a = *b;
373 * *b = tmp;
374 * }
375 */
376static ossl_inline void constant_time_cond_swap_64(uint64_t mask, uint64_t *a,
377 uint64_t *b)
378{
379 uint64_t xor = *a ^ *b;
380
381 xor &= mask;
382 *a ^= xor;
383 *b ^= xor;
384}
385
386/*
387 * mask must be 0xFF or 0x00.
388 * "constant time" is per len.
389 *
390 * if (mask) {
391 * unsigned char tmp[len];
392 *
393 * memcpy(tmp, a, len);
394 * memcpy(a, b);
395 * memcpy(b, tmp);
396 * }
397 */
398static ossl_inline void constant_time_cond_swap_buff(unsigned char mask,
399 unsigned char *a,
400 unsigned char *b,
401 size_t len)
402{
403 size_t i;
404 unsigned char tmp;
405
406 for (i = 0; i < len; i++) {
407 tmp = a[i] ^ b[i];
408 tmp &= mask;
409 a[i] ^= tmp;
410 b[i] ^= tmp;
411 }
412}
413
414/*
415 * table is a two dimensional array of bytes. Each row has rowsize elements.
416 * Copies row number idx into out. rowsize and numrows are not considered
417 * private.
418 */
419static ossl_inline void constant_time_lookup(void *out,
420 const void *table,
421 size_t rowsize,
422 size_t numrows,
423 size_t idx)
424{
425 size_t i, j;
426 const unsigned char *tablec = (const unsigned char *)table;
427 unsigned char *outc = (unsigned char *)out;
428 unsigned char mask;
429
430 memset(out, 0, rowsize);
431
432 /* Note idx may underflow - but that is well defined */
433 for (i = 0; i < numrows; i++, idx--) {
434 mask = (unsigned char)constant_time_is_zero_s(idx);
435 for (j = 0; j < rowsize; j++)
436 *(outc + j) |= constant_time_select_8(mask, *(tablec++), 0);
437 }
438}
439
440/*
441 * Expected usage pattern is to unconditionally set error and then
442 * wipe it if there was no actual error. |clear| is 1 or 0.
443 */
444void err_clear_last_constant_time(int clear);
445
446#endif /* OSSL_INTERNAL_CONSTANT_TIME_H */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette