VirtualBox

source: vbox/trunk/src/libs/openssl-3.0.7/include/internal/constant_time.h@ 100966

最後變更 在這個檔案從100966是 97984,由 vboxsync 提交於 2 年 前

libs/openssl-3.0.7: Shut up pragma once warnings for internal headers. Added sed script for doing that. bugref:10317

檔案大小: 12.9 KB
 
1/*
2 * Copyright 2014-2021 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
145static ossl_inline unsigned int constant_time_ge(unsigned int a,
146 unsigned int b)
147{
148 return ~constant_time_lt(a, b);
149}
150
151static ossl_inline size_t constant_time_ge_s(size_t a, size_t b)
152{
153 return ~constant_time_lt_s(a, b);
154}
155
156static ossl_inline unsigned char constant_time_ge_8(unsigned int a,
157 unsigned int b)
158{
159 return (unsigned char)constant_time_ge(a, b);
160}
161
162static ossl_inline unsigned char constant_time_ge_8_s(size_t a, size_t b)
163{
164 return (unsigned char)constant_time_ge_s(a, b);
165}
166
167static ossl_inline unsigned int constant_time_is_zero(unsigned int a)
168{
169 return constant_time_msb(~a & (a - 1));
170}
171
172static ossl_inline size_t constant_time_is_zero_s(size_t a)
173{
174 return constant_time_msb_s(~a & (a - 1));
175}
176
177static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a)
178{
179 return (unsigned char)constant_time_is_zero(a);
180}
181
182static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a)
183{
184 return constant_time_msb_32(~a & (a - 1));
185}
186
187static ossl_inline uint64_t constant_time_is_zero_64(uint64_t a)
188{
189 return constant_time_msb_64(~a & (a - 1));
190}
191
192static ossl_inline unsigned int constant_time_eq(unsigned int a,
193 unsigned int b)
194{
195 return constant_time_is_zero(a ^ b);
196}
197
198static ossl_inline size_t constant_time_eq_s(size_t a, size_t b)
199{
200 return constant_time_is_zero_s(a ^ b);
201}
202
203static ossl_inline unsigned char constant_time_eq_8(unsigned int a,
204 unsigned int b)
205{
206 return (unsigned char)constant_time_eq(a, b);
207}
208
209static ossl_inline unsigned char constant_time_eq_8_s(size_t a, size_t b)
210{
211 return (unsigned char)constant_time_eq_s(a, b);
212}
213
214static ossl_inline unsigned int constant_time_eq_int(int a, int b)
215{
216 return constant_time_eq((unsigned)(a), (unsigned)(b));
217}
218
219static ossl_inline unsigned char constant_time_eq_int_8(int a, int b)
220{
221 return constant_time_eq_8((unsigned)(a), (unsigned)(b));
222}
223
224/*
225 * Returns the value unmodified, but avoids optimizations.
226 * The barriers prevent the compiler from narrowing down the
227 * possible value range of the mask and ~mask in the select
228 * statements, which avoids the recognition of the select
229 * and turning it into a conditional load or branch.
230 */
231static ossl_inline unsigned int value_barrier(unsigned int a)
232{
233#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
234 unsigned int r;
235 __asm__("" : "=r"(r) : "0"(a));
236#else
237 volatile unsigned int r = a;
238#endif
239 return r;
240}
241
242/* Convenience method for uint32_t. */
243static ossl_inline uint32_t value_barrier_32(uint32_t a)
244{
245#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
246 uint32_t r;
247 __asm__("" : "=r"(r) : "0"(a));
248#else
249 volatile uint32_t r = a;
250#endif
251 return r;
252}
253
254/* Convenience method for uint64_t. */
255static ossl_inline uint64_t value_barrier_64(uint64_t a)
256{
257#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
258 uint64_t r;
259 __asm__("" : "=r"(r) : "0"(a));
260#else
261 volatile uint64_t r = a;
262#endif
263 return r;
264}
265
266/* Convenience method for size_t. */
267static ossl_inline size_t value_barrier_s(size_t a)
268{
269#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
270 size_t r;
271 __asm__("" : "=r"(r) : "0"(a));
272#else
273 volatile size_t r = a;
274#endif
275 return r;
276}
277
278static ossl_inline unsigned int constant_time_select(unsigned int mask,
279 unsigned int a,
280 unsigned int b)
281{
282 return (value_barrier(mask) & a) | (value_barrier(~mask) & b);
283}
284
285static ossl_inline size_t constant_time_select_s(size_t mask,
286 size_t a,
287 size_t b)
288{
289 return (value_barrier_s(mask) & a) | (value_barrier_s(~mask) & b);
290}
291
292static ossl_inline unsigned char constant_time_select_8(unsigned char mask,
293 unsigned char a,
294 unsigned char b)
295{
296 return (unsigned char)constant_time_select(mask, a, b);
297}
298
299static ossl_inline int constant_time_select_int(unsigned int mask, int a,
300 int b)
301{
302 return (int)constant_time_select(mask, (unsigned)(a), (unsigned)(b));
303}
304
305static ossl_inline int constant_time_select_int_s(size_t mask, int a, int b)
306{
307 return (int)constant_time_select((unsigned)mask, (unsigned)(a),
308 (unsigned)(b));
309}
310
311static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a,
312 uint32_t b)
313{
314 return (value_barrier_32(mask) & a) | (value_barrier_32(~mask) & b);
315}
316
317static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a,
318 uint64_t b)
319{
320 return (value_barrier_64(mask) & a) | (value_barrier_64(~mask) & b);
321}
322
323/*
324 * mask must be 0xFFFFFFFF or 0x00000000.
325 *
326 * if (mask) {
327 * uint32_t tmp = *a;
328 *
329 * *a = *b;
330 * *b = tmp;
331 * }
332 */
333static ossl_inline void constant_time_cond_swap_32(uint32_t mask, uint32_t *a,
334 uint32_t *b)
335{
336 uint32_t xor = *a ^ *b;
337
338 xor &= mask;
339 *a ^= xor;
340 *b ^= xor;
341}
342
343/*
344 * mask must be 0xFFFFFFFF or 0x00000000.
345 *
346 * if (mask) {
347 * uint64_t tmp = *a;
348 *
349 * *a = *b;
350 * *b = tmp;
351 * }
352 */
353static ossl_inline void constant_time_cond_swap_64(uint64_t mask, uint64_t *a,
354 uint64_t *b)
355{
356 uint64_t xor = *a ^ *b;
357
358 xor &= mask;
359 *a ^= xor;
360 *b ^= xor;
361}
362
363/*
364 * mask must be 0xFF or 0x00.
365 * "constant time" is per len.
366 *
367 * if (mask) {
368 * unsigned char tmp[len];
369 *
370 * memcpy(tmp, a, len);
371 * memcpy(a, b);
372 * memcpy(b, tmp);
373 * }
374 */
375static ossl_inline void constant_time_cond_swap_buff(unsigned char mask,
376 unsigned char *a,
377 unsigned char *b,
378 size_t len)
379{
380 size_t i;
381 unsigned char tmp;
382
383 for (i = 0; i < len; i++) {
384 tmp = a[i] ^ b[i];
385 tmp &= mask;
386 a[i] ^= tmp;
387 b[i] ^= tmp;
388 }
389}
390
391/*
392 * table is a two dimensional array of bytes. Each row has rowsize elements.
393 * Copies row number idx into out. rowsize and numrows are not considered
394 * private.
395 */
396static ossl_inline void constant_time_lookup(void *out,
397 const void *table,
398 size_t rowsize,
399 size_t numrows,
400 size_t idx)
401{
402 size_t i, j;
403 const unsigned char *tablec = (const unsigned char *)table;
404 unsigned char *outc = (unsigned char *)out;
405 unsigned char mask;
406
407 memset(out, 0, rowsize);
408
409 /* Note idx may underflow - but that is well defined */
410 for (i = 0; i < numrows; i++, idx--) {
411 mask = (unsigned char)constant_time_is_zero_s(idx);
412 for (j = 0; j < rowsize; j++)
413 *(outc + j) |= constant_time_select_8(mask, *(tablec++), 0);
414 }
415}
416
417/*
418 * Expected usage pattern is to unconditionally set error and then
419 * wipe it if there was no actual error. |clear| is 1 or 0.
420 */
421void err_clear_last_constant_time(int clear);
422
423#endif /* OSSL_INTERNAL_CONSTANT_TIME_H */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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