mirror of
https://github.com/openssl/openssl.git
synced 2024-11-27 05:21:51 +08:00
2a3d0ee9d5
ChaCha20-Poly1305 is an AEAD cipher, and requires a unique nonce input for every encryption operation. RFC 7539 specifies that the nonce value (IV) should be 96 bits (12 bytes). OpenSSL allows a variable nonce length and front pads the nonce with 0 bytes if it is less than 12 bytes. However it also incorrectly allows a nonce to be set of up to 16 bytes. In this case only the last 12 bytes are significant and any additional leading bytes are ignored. It is a requirement of using this cipher that nonce values are unique. Messages encrypted using a reused nonce value are susceptible to serious confidentiality and integrity attacks. If an application changes the default nonce length to be longer than 12 bytes and then makes a change to the leading bytes of the nonce expecting the new value to be a new unique nonce then such an application could inadvertently encrypt messages with a reused nonce. Additionally the ignored bytes in a long nonce are not covered by the integrity guarantee of this cipher. Any application that relies on the integrity of these ignored leading bytes of a long nonce may be further affected. Any OpenSSL internal use of this cipher, including in SSL/TLS, is safe because no such use sets such a long nonce value. However user applications that use this cipher directly and set a non-default nonce length to be longer than 12 bytes may be vulnerable. CVE-2019-1543 Fixes #8345 Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/8406) |
||
---|---|---|
.. | ||
aes | ||
aria | ||
asn1 | ||
async | ||
bf | ||
bio | ||
blake2 | ||
bn | ||
buffer | ||
camellia | ||
cast | ||
chacha | ||
cmac | ||
cms | ||
comp | ||
conf | ||
ct | ||
des | ||
dh | ||
dsa | ||
dso | ||
ec | ||
engine | ||
err | ||
ess | ||
evp | ||
gmac | ||
hmac | ||
idea | ||
include/internal | ||
kdf | ||
kmac | ||
lhash | ||
md2 | ||
md4 | ||
md5 | ||
mdc2 | ||
modes | ||
objects | ||
ocsp | ||
pem | ||
perlasm | ||
pkcs7 | ||
pkcs12 | ||
poly1305 | ||
property | ||
rand | ||
rc2 | ||
rc4 | ||
rc5 | ||
ripemd | ||
rsa | ||
seed | ||
sha | ||
siphash | ||
sm2 | ||
sm3 | ||
sm4 | ||
srp | ||
stack | ||
store | ||
ts | ||
txt_db | ||
ui | ||
whrlpool | ||
x509 | ||
x509v3 | ||
alphacpuid.pl | ||
arm64cpuid.pl | ||
arm_arch.h | ||
armcap.c | ||
armv4cpuid.pl | ||
build.info | ||
c64xpluscpuid.pl | ||
context.c | ||
cpt_err.c | ||
cryptlib.c | ||
ctype.c | ||
cversion.c | ||
dllmain.c | ||
ebcdic.c | ||
ex_data.c | ||
getenv.c | ||
ia64cpuid.S | ||
init.c | ||
LPdir_nyi.c | ||
LPdir_unix.c | ||
LPdir_vms.c | ||
LPdir_win32.c | ||
LPdir_win.c | ||
LPdir_wince.c | ||
mem_clr.c | ||
mem_dbg.c | ||
mem_sec.c | ||
mem.c | ||
mips_arch.h | ||
o_dir.c | ||
o_fips.c | ||
o_fopen.c | ||
o_init.c | ||
o_str.c | ||
o_time.c | ||
pariscid.pl | ||
ppc_arch.h | ||
ppccap.c | ||
ppccpuid.pl | ||
README.sparse_array | ||
s390x_arch.h | ||
s390xcap.c | ||
s390xcpuid.pl | ||
sparc_arch.h | ||
sparccpuid.S | ||
sparcv9cap.c | ||
sparse_array.c | ||
threads_none.c | ||
threads_pthread.c | ||
threads_win.c | ||
trace.c | ||
uid.c | ||
vms_rms.h | ||
x86_64cpuid.pl | ||
x86cpuid.pl |
The sparse_array.c file contains an implementation of a sparse array that attempts to be both space and time efficient. The sparse array is represented using a tree structure. Each node in the tree contains a block of pointers to either the user supplied leaf values or to another node. There are a number of parameters used to define the block size: OPENSSL_SA_BLOCK_BITS Specifies the number of bits covered by each block SA_BLOCK_MAX Specifies the number of pointers in each block SA_BLOCK_MASK Specifies a bit mask to perform modulo block size SA_BLOCK_MAX_LEVELS Indicates the maximum possible height of the tree These constants are inter-related: SA_BLOCK_MAX = 2 ^ OPENSSL_SA_BLOCK_BITS SA_BLOCK_MASK = SA_BLOCK_MAX - 1 SA_BLOCK_MAX_LEVELS = number of bits in size_t divided by OPENSSL_SA_BLOCK_BITS rounded up to the next multiple of OPENSSL_SA_BLOCK_BITS OPENSSL_SA_BLOCK_BITS can be defined at compile time and this overrides the built in setting. As a space and performance optimisation, the height of the tree is usually less than the maximum possible height. Only sufficient height is allocated to accommodate the largest index added to the data structure. The largest index used to add a value to the array determines the tree height: +----------------------+---------------------+ | Largest Added Index | Height of Tree | +----------------------+---------------------+ | SA_BLOCK_MAX - 1 | 1 | | SA_BLOCK_MAX ^ 2 - 1 | 2 | | SA_BLOCK_MAX ^ 3 - 1 | 3 | | ... | ... | | size_t max | SA_BLOCK_MAX_LEVELS | +----------------------+---------------------+ The tree height is dynamically increased as needed based on additions. An empty tree is represented by a NULL root pointer. Inserting a value at index 0 results in the allocation of a top level node full of null pointers except for the single pointer to the user's data (N = SA_BLOCK_MAX for breviety): +----+ |Root| |Node| +-+--+ | | | v +-+-+---+---+---+---+ | 0 | 1 | 2 |...|N-1| | |nil|nil|...|nil| +-+-+---+---+---+---+ | | | v +-+--+ |User| |Data| +----+ Index 0 Inserting at element 2N+1 creates a new root node and pushes down the old root node. It then creates a second second level node to hold the pointer to the user's new data: +----+ |Root| |Node| +-+--+ | | | v +-+-+---+---+---+---+ | 0 | 1 | 2 |...|N-1| | |nil| |...|nil| +-+-+---+-+-+---+---+ | | | +------------------+ | | v v +-+-+---+---+---+---+ +-+-+---+---+---+---+ | 0 | 1 | 2 |...|N-1| | 0 | 1 | 2 |...|N-1| |nil| |nil|...|nil| |nil| |nil|...|nil| +-+-+---+---+---+---+ +---+-+-+---+---+---+ | | | | | | v v +-+--+ +-+--+ |User| |User| |Data| |Data| +----+ +----+ Index 0 Index 2N+1 The nodes themselves are allocated in a sparse manner. Only nodes which exist along a path from the root of the tree to an added leaf will be allocated. The complexity is hidden and nodes are allocated on an as needed basis. Because the data is expected to be sparse this doesn't result in a large waste of space. Values can be removed from the sparse array by setting their index position to NULL. The data structure does not attempt to reclaim nodes or reduce the height of the tree on removal. For example, now setting index 0 to NULL would result in: +----+ |Root| |Node| +-+--+ | | | v +-+-+---+---+---+---+ | 0 | 1 | 2 |...|N-1| | |nil| |...|nil| +-+-+---+-+-+---+---+ | | | +------------------+ | | v v +-+-+---+---+---+---+ +-+-+---+---+---+---+ | 0 | 1 | 2 |...|N-1| | 0 | 1 | 2 |...|N-1| |nil|nil|nil|...|nil| |nil| |nil|...|nil| +---+---+---+---+---+ +---+-+-+---+---+---+ | | | v +-+--+ |User| |Data| +----+ Index 2N+1 Accesses to elements in the sparse array take O(log n) time where n is the largest element. The base of the logarithm is SA_BLOCK_MAX, so for moderately small indices (e.g. NIDs), single level (constant time) access is achievable. Space usage is O(minimum(m, n log(n)) where m is the number of elements in the array. Note: sparse arrays only include pointers to types. Thus, SPARSE_ARRAY_OF(char) can be used to store a string.