2014-06-20 12:00:00 -07:00
|
|
|
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This package is an SSL implementation written
|
|
|
|
* by Eric Young (eay@cryptsoft.com).
|
|
|
|
* The implementation was written so as to conform with Netscapes SSL.
|
|
|
|
*
|
|
|
|
* This library is free for commercial and non-commercial use as long as
|
|
|
|
* the following conditions are aheared to. The following conditions
|
|
|
|
* apply to all code found in this distribution, be it the RC4, RSA,
|
|
|
|
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
|
|
|
* included with this distribution is covered by the same copyright terms
|
|
|
|
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
|
|
|
*
|
|
|
|
* Copyright remains Eric Young's, and as such any Copyright notices in
|
|
|
|
* the code are not to be removed.
|
|
|
|
* If this package is used in a product, Eric Young should be given attribution
|
|
|
|
* as the author of the parts of the library used.
|
|
|
|
* This can be in the form of a textual message at program startup or
|
|
|
|
* in documentation (online or textual) provided with the package.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* "This product includes cryptographic software written by
|
|
|
|
* Eric Young (eay@cryptsoft.com)"
|
|
|
|
* The word 'cryptographic' can be left out if the rouines from the library
|
|
|
|
* being used are not cryptographic related :-).
|
|
|
|
* 4. If you include any Windows specific code (or a derivative thereof) from
|
|
|
|
* the apps directory (application code) you must include an acknowledgement:
|
|
|
|
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* The licence and distribution terms for any publically available version or
|
|
|
|
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
|
|
|
* copied and put under another distribution licence
|
|
|
|
* [including the GNU Public Licence.]
|
|
|
|
*/
|
|
|
|
/* ====================================================================
|
|
|
|
* Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
*
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
*
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
*
|
|
|
|
* 3. All advertising materials mentioning features or use of this
|
|
|
|
* software must display the following acknowledgment:
|
|
|
|
* "This product includes software developed by the OpenSSL Project
|
|
|
|
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
|
|
|
*
|
|
|
|
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
|
|
|
* endorse or promote products derived from this software without
|
|
|
|
* prior written permission. For written permission, please contact
|
|
|
|
* openssl-core@openssl.org.
|
|
|
|
*
|
|
|
|
* 5. Products derived from this software may not be called "OpenSSL"
|
|
|
|
* nor may "OpenSSL" appear in their names without prior written
|
|
|
|
* permission of the OpenSSL Project.
|
|
|
|
*
|
|
|
|
* 6. Redistributions of any form whatsoever must retain the following
|
|
|
|
* acknowledgment:
|
|
|
|
* "This product includes software developed by the OpenSSL Project
|
|
|
|
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
|
|
|
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
|
|
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
|
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
* ====================================================================
|
|
|
|
*
|
|
|
|
* This product includes cryptographic software written by Eric Young
|
|
|
|
* (eay@cryptsoft.com). This product includes software written by Tim
|
|
|
|
* Hudson (tjh@cryptsoft.com). */
|
|
|
|
|
|
|
|
#ifndef OPENSSL_HEADER_CRYPTO_INTERNAL_H
|
|
|
|
#define OPENSSL_HEADER_CRYPTO_INTERNAL_H
|
|
|
|
|
2018-11-15 13:13:17 -10:00
|
|
|
#include <GFp/base.h> // Must be first.
|
|
|
|
|
|
|
|
#if defined(_MSC_VER)
|
|
|
|
#pragma warning(push, 3)
|
|
|
|
#endif
|
2018-11-15 13:02:41 -10:00
|
|
|
|
2016-01-21 14:57:17 -10:00
|
|
|
#include <assert.h>
|
|
|
|
|
2016-02-23 09:22:31 -10:00
|
|
|
#if defined(__clang__) || defined(_MSC_VER)
|
|
|
|
#include <string.h>
|
|
|
|
#endif
|
|
|
|
|
2018-11-15 13:13:17 -10:00
|
|
|
#if defined(_MSC_VER)
|
|
|
|
#pragma warning(pop)
|
|
|
|
#endif
|
|
|
|
|
Add start of infrastructure for checking constant-time properties.
Valgrind's checking of uninitialised memory behaves very much like a
check for constant-time code: branches and memory indexes based on
uninitialised memory trigger warnings. Therefore, if we can tell
Valgrind that some secret is “uninitialised”, it'll give us a warning if
we do something non-constant-time with it.
This was the idea behind https://github.com/agl/ctgrind. But tricks like
that are no longer needed because Valgrind now comes with support for
marking regions of memory as defined or not. Therefore we can use that
API to check constant-time code.
This CL defines |CONSTTIME_SECRET| and |CONSTTIME_DECLASSIFY|, which are
no-ops unless the code is built with
|BORINGSSL_CONSTANT_TIME_VALIDATION| defined, which it isn't by default.
So this CL is a no-op itself so far. But it does show that a couple of
bits of constant-time time are, in fact, constant-time—seemingly even
when compiled with optimisations, which is nice.
The annotations in the RSA code are a) probably not marking all the
secrets as secret, and b) triggers warnings that are a little
interesting:
The anti-glitch check calls |BN_mod_exp_mont| which checks that the
input is less than the modulus. Of course, it is because the input is
the RSA plaintext that we just decrypted, but the plaintext is supposed
to be secret and so branching based on its contents isn't allows by
Valgrind. The answer isn't totally clear, but I've run out of time on
this for now.
Change-Id: I1608ed0b22d201e97595fafe46127159e02d5b1b
Reviewed-on: https://boringssl-review.googlesource.com/c/33504
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2018-12-06 17:15:58 -08:00
|
|
|
#if defined(BORINGSSL_CONSTANT_TIME_VALIDATION)
|
|
|
|
#include <valgrind/memcheck.h>
|
|
|
|
#endif
|
|
|
|
|
2017-04-19 14:56:44 -10:00
|
|
|
#include <GFp/type_check.h>
|
2014-06-20 12:00:00 -07:00
|
|
|
|
2015-10-04 18:38:54 -10:00
|
|
|
#if defined(_MSC_VER)
|
2016-01-19 13:38:49 -10:00
|
|
|
#pragma warning(push, 3)
|
|
|
|
#include <intrin.h>
|
|
|
|
#pragma warning(pop)
|
2018-04-29 20:14:41 -10:00
|
|
|
#endif
|
2016-12-13 01:07:13 -05:00
|
|
|
|
2018-01-17 13:39:52 +01:00
|
|
|
#if defined(__GNUC__) && \
|
|
|
|
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
|
|
|
|
// |alignas| and |alignof| were added in C11. GCC added support in version 4.8.
|
|
|
|
// Testing for __STDC_VERSION__/__cplusplus doesn't work because 4.7 already
|
|
|
|
// reports support for C11.
|
|
|
|
#define alignas(x) __attribute__ ((aligned (x)))
|
|
|
|
#define alignof(x) __alignof__ (x)
|
2018-07-02 15:14:45 -04:00
|
|
|
#elif defined(_MSC_VER)
|
2016-01-17 20:12:57 -10:00
|
|
|
#define alignas(x) __declspec(align(x))
|
2018-05-01 10:57:27 -10:00
|
|
|
#define alignof(x) __alignof(x)
|
2015-10-04 18:38:54 -10:00
|
|
|
#else
|
|
|
|
#include <stdalign.h>
|
|
|
|
#endif
|
2014-06-20 12:00:00 -07:00
|
|
|
|
2015-01-09 15:44:37 -08:00
|
|
|
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || defined(OPENSSL_ARM) || \
|
2016-09-23 12:47:24 -07:00
|
|
|
defined(OPENSSL_AARCH64) || defined(OPENSSL_PPC64LE)
|
2018-04-29 10:59:44 -10:00
|
|
|
// GFp_cpuid_setup initializes the platform-specific feature cache.
|
2016-12-21 19:55:08 -10:00
|
|
|
void GFp_cpuid_setup(void);
|
2014-09-11 19:11:15 -04:00
|
|
|
#endif
|
2014-08-26 13:38:19 -07:00
|
|
|
|
2016-01-19 13:38:49 -10:00
|
|
|
#define OPENSSL_LITTLE_ENDIAN 1
|
|
|
|
#define OPENSSL_BIG_ENDIAN 2
|
|
|
|
|
|
|
|
#if defined(OPENSSL_X86_64) || defined(OPENSSL_X86) || \
|
|
|
|
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
|
|
|
|
__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
|
|
|
#define OPENSSL_ENDIAN OPENSSL_LITTLE_ENDIAN
|
|
|
|
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
|
|
|
|
__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
|
|
|
#define OPENSSL_ENDIAN OPENSSL_BIG_ENDIAN
|
|
|
|
#else
|
|
|
|
#error "Cannot determine endianness"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(__GNUC__)
|
|
|
|
#define bswap_u32(x) __builtin_bswap32(x)
|
|
|
|
#define bswap_u64(x) __builtin_bswap64(x)
|
|
|
|
#elif defined(_MSC_VER)
|
|
|
|
#pragma intrinsic(_byteswap_ulong, _byteswap_uint64)
|
|
|
|
#define bswap_u32(x) _byteswap_ulong(x)
|
|
|
|
#define bswap_u64(x) _byteswap_uint64(x)
|
|
|
|
#endif
|
|
|
|
|
2014-11-03 18:51:20 -08:00
|
|
|
|
2017-12-07 21:11:24 -05:00
|
|
|
#if (!defined(_MSC_VER) || defined(__clang__)) && defined(OPENSSL_64_BIT)
|
|
|
|
#define BORINGSSL_HAS_UINT128
|
2016-01-26 15:16:37 -10:00
|
|
|
typedef __int128_t int128_t;
|
|
|
|
typedef __uint128_t uint128_t;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2018-05-18 13:10:27 -10:00
|
|
|
// |aliasing_uint8| is like |uint8_t| except that it is guaranteed to be
|
|
|
|
// |unsigned char| so it can safely be used for aliasing casts. Assume POSIX
|
|
|
|
// compliance so that |CHAR_BIT| is guaranteed to be 8.
|
|
|
|
typedef unsigned char aliasing_uint8;
|
|
|
|
|
|
|
|
|
2017-08-18 14:06:02 -04:00
|
|
|
// Constant-time utility functions.
|
|
|
|
//
|
|
|
|
// The following methods return a bitmask of all ones (0xff...f) for true and 0
|
|
|
|
// for false. This is useful for choosing a value based on the result of a
|
|
|
|
// conditional in constant time. For example,
|
|
|
|
//
|
|
|
|
// if (a < b) {
|
|
|
|
// c = a;
|
|
|
|
// } else {
|
|
|
|
// c = b;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// can be written as
|
|
|
|
//
|
2018-05-18 12:45:27 -10:00
|
|
|
// crypto_word lt = constant_time_lt_w(a, b);
|
2017-08-18 14:06:02 -04:00
|
|
|
// c = constant_time_select_w(lt, a, b);
|
|
|
|
|
2018-05-18 12:45:27 -10:00
|
|
|
// crypto_word is the type that most constant-time functions use. Ideally we
|
2017-08-18 14:06:02 -04:00
|
|
|
// would like it to be |size_t|, but NaCl builds in 64-bit mode with 32-bit
|
2018-05-18 12:45:27 -10:00
|
|
|
// pointers, which means that |size_t| can be 32 bits when |crypto_word| is 64
|
2018-05-16 12:44:42 -10:00
|
|
|
// bits.
|
2017-04-20 13:51:11 -07:00
|
|
|
#if defined(OPENSSL_64_BIT)
|
2018-05-18 12:45:27 -10:00
|
|
|
typedef uint64_t crypto_word;
|
|
|
|
#define CRYPTO_WORD_BITS (64u)
|
2017-04-20 13:51:11 -07:00
|
|
|
#elif defined(OPENSSL_32_BIT)
|
2018-05-18 12:45:27 -10:00
|
|
|
typedef uint32_t crypto_word;
|
|
|
|
#define CRYPTO_WORD_BITS (32u)
|
2017-04-20 13:51:11 -07:00
|
|
|
#else
|
|
|
|
#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT"
|
|
|
|
#endif
|
|
|
|
|
2018-05-18 12:45:27 -10:00
|
|
|
#define CONSTTIME_TRUE_W ~((crypto_word)0)
|
|
|
|
#define CONSTTIME_FALSE_W ((crypto_word)0)
|
2017-03-16 11:38:18 -04:00
|
|
|
|
2017-08-18 14:06:02 -04:00
|
|
|
// constant_time_msb_w returns the given value with the MSB copied to all the
|
|
|
|
// other bits.
|
2018-05-18 12:45:27 -10:00
|
|
|
static inline crypto_word constant_time_msb_w(crypto_word a) {
|
2017-03-16 11:38:18 -04:00
|
|
|
return 0u - (a >> (sizeof(a) * 8 - 1));
|
2016-06-30 08:41:28 -10:00
|
|
|
}
|
|
|
|
|
2018-04-29 10:59:44 -10:00
|
|
|
// constant_time_is_zero_w returns 0xff..f if a == 0 and 0 otherwise.
|
2018-05-18 12:45:27 -10:00
|
|
|
static inline crypto_word constant_time_is_zero_w(crypto_word a) {
|
2017-08-18 14:06:02 -04:00
|
|
|
// Here is an SMT-LIB verification of this formula:
|
|
|
|
//
|
|
|
|
// (define-fun is_zero ((a (_ BitVec 32))) (_ BitVec 32)
|
|
|
|
// (bvand (bvnot a) (bvsub a #x00000001))
|
|
|
|
// )
|
|
|
|
//
|
|
|
|
// (declare-fun a () (_ BitVec 32))
|
|
|
|
//
|
|
|
|
// (assert (not (= (= #x00000001 (bvlshr (is_zero a) #x0000001f)) (= a #x00000000))))
|
|
|
|
// (check-sat)
|
|
|
|
// (get-model)
|
2017-04-20 13:51:11 -07:00
|
|
|
return constant_time_msb_w(~a & (a - 1));
|
2014-11-03 18:51:20 -08:00
|
|
|
}
|
|
|
|
|
2018-05-18 12:45:27 -10:00
|
|
|
static inline crypto_word constant_time_is_nonzero_w(crypto_word a) {
|
2018-04-26 16:49:26 -10:00
|
|
|
return ~constant_time_is_zero_w(a);
|
2016-07-07 10:34:14 -10:00
|
|
|
}
|
|
|
|
|
2017-08-18 14:06:02 -04:00
|
|
|
// constant_time_eq_w returns 0xff..f if a == b and 0 otherwise.
|
2018-05-18 12:45:27 -10:00
|
|
|
static inline crypto_word constant_time_eq_w(crypto_word a,
|
|
|
|
crypto_word b) {
|
2017-04-20 13:51:11 -07:00
|
|
|
return constant_time_is_zero_w(a ^ b);
|
2016-06-30 08:41:28 -10:00
|
|
|
}
|
|
|
|
|
2017-08-18 14:06:02 -04:00
|
|
|
// constant_time_select_w returns (mask & a) | (~mask & b). When |mask| is all
|
|
|
|
// 1s or all 0s (as returned by the methods above), the select methods return
|
|
|
|
// either |a| (if |mask| is nonzero) or |b| (if |mask| is zero).
|
2018-05-18 12:45:27 -10:00
|
|
|
static inline crypto_word constant_time_select_w(crypto_word mask,
|
|
|
|
crypto_word a,
|
|
|
|
crypto_word b) {
|
2016-06-30 08:41:28 -10:00
|
|
|
return (mask & a) | (~mask & b);
|
|
|
|
}
|
|
|
|
|
Add start of infrastructure for checking constant-time properties.
Valgrind's checking of uninitialised memory behaves very much like a
check for constant-time code: branches and memory indexes based on
uninitialised memory trigger warnings. Therefore, if we can tell
Valgrind that some secret is “uninitialised”, it'll give us a warning if
we do something non-constant-time with it.
This was the idea behind https://github.com/agl/ctgrind. But tricks like
that are no longer needed because Valgrind now comes with support for
marking regions of memory as defined or not. Therefore we can use that
API to check constant-time code.
This CL defines |CONSTTIME_SECRET| and |CONSTTIME_DECLASSIFY|, which are
no-ops unless the code is built with
|BORINGSSL_CONSTANT_TIME_VALIDATION| defined, which it isn't by default.
So this CL is a no-op itself so far. But it does show that a couple of
bits of constant-time time are, in fact, constant-time—seemingly even
when compiled with optimisations, which is nice.
The annotations in the RSA code are a) probably not marking all the
secrets as secret, and b) triggers warnings that are a little
interesting:
The anti-glitch check calls |BN_mod_exp_mont| which checks that the
input is less than the modulus. Of course, it is because the input is
the RSA plaintext that we just decrypted, but the plaintext is supposed
to be secret and so branching based on its contents isn't allows by
Valgrind. The answer isn't totally clear, but I've run out of time on
this for now.
Change-Id: I1608ed0b22d201e97595fafe46127159e02d5b1b
Reviewed-on: https://boringssl-review.googlesource.com/c/33504
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2018-12-06 17:15:58 -08:00
|
|
|
#if defined(BORINGSSL_CONSTANT_TIME_VALIDATION)
|
|
|
|
|
|
|
|
// CONSTTIME_SECRET takes a pointer and a number of bytes and marks that region
|
|
|
|
// of memory as secret. Secret data is tracked as it flows to registers and
|
|
|
|
// other parts of a memory. If secret data is used as a condition for a branch,
|
|
|
|
// or as a memory index, it will trigger warnings in valgrind.
|
|
|
|
#define CONSTTIME_SECRET(x, y) VALGRIND_MAKE_MEM_UNDEFINED(x, y)
|
|
|
|
|
|
|
|
// CONSTTIME_DECLASSIFY takes a pointer and a number of bytes and marks that
|
|
|
|
// region of memory as public. Public data is not subject to constant-time
|
|
|
|
// rules.
|
|
|
|
#define CONSTTIME_DECLASSIFY(x, y) VALGRIND_MAKE_MEM_DEFINED(x, y)
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#define CONSTTIME_SECRET(x, y)
|
|
|
|
#define CONSTTIME_DECLASSIFY(x, y)
|
|
|
|
|
|
|
|
#endif // BORINGSSL_CONSTANT_TIME_VALIDATION
|
|
|
|
|
2018-04-29 10:59:44 -10:00
|
|
|
// from_be_u32_ptr returns the 32-bit big-endian-encoded value at |data|.
|
2016-01-19 13:39:55 -10:00
|
|
|
static inline uint32_t from_be_u32_ptr(const uint8_t *data) {
|
2016-02-23 09:22:31 -10:00
|
|
|
#if defined(__clang__) || defined(_MSC_VER)
|
2018-04-29 10:59:44 -10:00
|
|
|
// XXX: Unlike GCC, Clang doesn't optimize compliant access to unaligned data
|
|
|
|
// well. See https://llvm.org/bugs/show_bug.cgi?id=20605,
|
|
|
|
// https://llvm.org/bugs/show_bug.cgi?id=17603,
|
|
|
|
// http://blog.regehr.org/archives/702, and
|
|
|
|
// http://blog.regehr.org/archives/1055. MSVC seems to have similar problems.
|
2016-02-23 09:22:31 -10:00
|
|
|
uint32_t value;
|
|
|
|
memcpy(&value, data, sizeof(value));
|
|
|
|
#if OPENSSL_ENDIAN != OPENSSL_BIG_ENDIAN
|
|
|
|
value = bswap_u32(value);
|
|
|
|
#endif
|
|
|
|
return value;
|
|
|
|
#else
|
2016-01-19 13:39:55 -10:00
|
|
|
return ((uint32_t)data[0] << 24) |
|
|
|
|
((uint32_t)data[1] << 16) |
|
|
|
|
((uint32_t)data[2] << 8) |
|
|
|
|
((uint32_t)data[3]);
|
2016-02-23 09:22:31 -10:00
|
|
|
#endif
|
2016-01-16 12:57:56 -05:00
|
|
|
}
|
|
|
|
|
2016-03-29 09:16:29 -04:00
|
|
|
|
2018-04-29 10:59:44 -10:00
|
|
|
// to_be_u32_ptr writes the value |x| to the location |out| in big-endian
|
|
|
|
// order.
|
2016-02-03 00:28:37 -10:00
|
|
|
static inline void to_be_u32_ptr(uint8_t *out, uint32_t value) {
|
2016-02-23 09:22:31 -10:00
|
|
|
#if defined(__clang__) || defined(_MSC_VER)
|
2018-04-29 10:59:44 -10:00
|
|
|
// XXX: Unlike GCC, Clang doesn't optimize compliant access to unaligned data
|
|
|
|
// well. See https://llvm.org/bugs/show_bug.cgi?id=20605,
|
|
|
|
// https://llvm.org/bugs/show_bug.cgi?id=17603,
|
|
|
|
// http://blog.regehr.org/archives/702, and
|
|
|
|
// http://blog.regehr.org/archives/1055. MSVC seems to have similar problems.
|
2016-02-23 09:22:31 -10:00
|
|
|
#if OPENSSL_ENDIAN != OPENSSL_BIG_ENDIAN
|
|
|
|
value = bswap_u32(value);
|
|
|
|
#endif
|
|
|
|
memcpy(out, &value, sizeof(value));
|
|
|
|
#else
|
2016-02-03 00:28:37 -10:00
|
|
|
out[0] = (uint8_t)(value >> 24);
|
|
|
|
out[1] = (uint8_t)(value >> 16);
|
|
|
|
out[2] = (uint8_t)(value >> 8);
|
|
|
|
out[3] = (uint8_t)value;
|
2016-03-14 17:21:56 -10:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-04-29 10:59:44 -10:00
|
|
|
// to_be_u64_ptr writes the value |value| to the location |out| in big-endian
|
|
|
|
// order.
|
2016-03-14 17:21:56 -10:00
|
|
|
static inline void to_be_u64_ptr(uint8_t *out, uint64_t value) {
|
|
|
|
#if defined(__clang__) || defined(_MSC_VER)
|
2018-04-29 10:59:44 -10:00
|
|
|
// XXX: Unlike GCC, Clang doesn't optimize compliant access to unaligned data
|
|
|
|
// well. See https://llvm.org/bugs/show_bug.cgi?id=20605,
|
|
|
|
// https://llvm.org/bugs/show_bug.cgi?id=17603,
|
|
|
|
// http://blog.regehr.org/archives/702, and
|
|
|
|
// http://blog.regehr.org/archives/1055. MSVC seems to have similar problems.
|
2016-03-14 17:21:56 -10:00
|
|
|
#if OPENSSL_ENDIAN != OPENSSL_BIG_ENDIAN
|
|
|
|
value = bswap_u64(value);
|
|
|
|
#endif
|
|
|
|
memcpy(out, &value, sizeof(value));
|
|
|
|
#else
|
|
|
|
out[0] = (uint8_t)(value >> 56);
|
|
|
|
out[1] = (uint8_t)(value >> 48);
|
|
|
|
out[2] = (uint8_t)(value >> 40);
|
|
|
|
out[3] = (uint8_t)(value >> 32);
|
|
|
|
out[4] = (uint8_t)(value >> 24);
|
|
|
|
out[5] = (uint8_t)(value >> 16);
|
|
|
|
out[6] = (uint8_t)(value >> 8);
|
|
|
|
out[7] = (uint8_t)value;
|
2016-02-23 09:22:31 -10:00
|
|
|
#endif
|
2016-01-21 22:43:28 -05:00
|
|
|
}
|
|
|
|
|
2017-08-18 14:06:02 -04:00
|
|
|
#endif // OPENSSL_HEADER_CRYPTO_INTERNAL_H
|