diff options
author | Emma Miler <emma.pi@protonmail.com> | 2022-12-02 23:00:33 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-02 23:00:33 +0100 |
commit | 2d59006262d6e45f41ee325af78433475884dca4 (patch) | |
tree | 939c84779bf6a455102c74937f238a0ec05698eb /include/internal | |
parent | be78dbacc5dcc95e7d9be503d61ceb5de640c661 (diff) | |
download | NorthstarLauncher-2d59006262d6e45f41ee325af78433475884dca4.tar.gz NorthstarLauncher-2d59006262d6e45f41ee325af78433475884dca4.zip |
Move include directory (#337)v1.11.0-rc1
* Move include directory to shared folder
This commit moves the `include` directory from the NorthstarDLL project folder to the solution folder. This allows both the DLL and Launcher project to target it properly.
* Fix filters
* Update memalloc.h
* Fix filters
* Update NorthstarLauncher.vcxproj
* Remove stuff from other PR
* Update NorthstarLauncher.vcxproj
* Update NorthstarLauncher.vcxproj
* Update NorthstarDLL.vcxproj
Diffstat (limited to 'include/internal')
39 files changed, 4462 insertions, 0 deletions
diff --git a/include/internal/__DECC_INCLUDE_EPILOGUE.H b/include/internal/__DECC_INCLUDE_EPILOGUE.H new file mode 100644 index 00000000..e57c0eab --- /dev/null +++ b/include/internal/__DECC_INCLUDE_EPILOGUE.H @@ -0,0 +1,16 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is only used by HP C on VMS, and is included automatically + * after each header file from this directory + */ + +/* restore state. Must correspond to the save in __decc_include_prologue.h */ +#pragma names restore diff --git a/include/internal/__DECC_INCLUDE_PROLOGUE.H b/include/internal/__DECC_INCLUDE_PROLOGUE.H new file mode 100644 index 00000000..a0139575 --- /dev/null +++ b/include/internal/__DECC_INCLUDE_PROLOGUE.H @@ -0,0 +1,20 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is only used by HP C on VMS, and is included automatically + * after each header file from this directory + */ + +/* save state */ +#pragma names save +/* have the compiler shorten symbols larger than 31 chars to 23 chars + * followed by a 8 hex char CRC + */ +#pragma names as_is,shortened diff --git a/include/internal/asn1.h b/include/internal/asn1.h new file mode 100644 index 00000000..3143e340 --- /dev/null +++ b/include/internal/asn1.h @@ -0,0 +1,16 @@ +/* + * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_ASN1_H +# define OSSL_INTERNAL_ASN1_H +# pragma once + +int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb); + +#endif diff --git a/include/internal/bio.h b/include/internal/bio.h new file mode 100644 index 00000000..2d36a7b9 --- /dev/null +++ b/include/internal/bio.h @@ -0,0 +1,91 @@ +/* + * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_BIO_H +# define OSSL_INTERNAL_BIO_H +# pragma once + +# include <openssl/core.h> +# include <openssl/bio.h> + +struct bio_method_st { + int type; + char *name; + int (*bwrite) (BIO *, const char *, size_t, size_t *); + int (*bwrite_old) (BIO *, const char *, int); + int (*bread) (BIO *, char *, size_t, size_t *); + int (*bread_old) (BIO *, char *, int); + int (*bputs) (BIO *, const char *); + int (*bgets) (BIO *, char *, int); + long (*ctrl) (BIO *, int, long, void *); + int (*create) (BIO *); + int (*destroy) (BIO *); + long (*callback_ctrl) (BIO *, int, BIO_info_cb *); +}; + +void bio_free_ex_data(BIO *bio); +void bio_cleanup(void); + + +/* Old style to new style BIO_METHOD conversion functions */ +int bwrite_conv(BIO *bio, const char *data, size_t datal, size_t *written); +int bread_conv(BIO *bio, char *data, size_t datal, size_t *read); + +/* Changes to these internal BIOs must also update include/openssl/bio.h */ +# define BIO_CTRL_SET_KTLS 72 +# define BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG 74 +# define BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG 75 + +/* + * This is used with socket BIOs: + * BIO_FLAGS_KTLS_TX means we are using ktls with this BIO for sending. + * BIO_FLAGS_KTLS_TX_CTRL_MSG means we are about to send a ctrl message next. + * BIO_FLAGS_KTLS_RX means we are using ktls with this BIO for receiving. + */ +# define BIO_FLAGS_KTLS_TX 0x800 +# define BIO_FLAGS_KTLS_TX_CTRL_MSG 0x1000 +# define BIO_FLAGS_KTLS_RX 0x2000 + +/* KTLS related controls and flags */ +# define BIO_set_ktls_flag(b, is_tx) \ + BIO_set_flags(b, (is_tx) ? BIO_FLAGS_KTLS_TX : BIO_FLAGS_KTLS_RX) +# define BIO_should_ktls_flag(b, is_tx) \ + BIO_test_flags(b, (is_tx) ? BIO_FLAGS_KTLS_TX : BIO_FLAGS_KTLS_RX) +# define BIO_set_ktls_ctrl_msg_flag(b) \ + BIO_set_flags(b, BIO_FLAGS_KTLS_TX_CTRL_MSG) +# define BIO_should_ktls_ctrl_msg_flag(b) \ + BIO_test_flags(b, BIO_FLAGS_KTLS_TX_CTRL_MSG) +# define BIO_clear_ktls_ctrl_msg_flag(b) \ + BIO_clear_flags(b, BIO_FLAGS_KTLS_TX_CTRL_MSG) + +# define BIO_set_ktls(b, keyblob, is_tx) \ + BIO_ctrl(b, BIO_CTRL_SET_KTLS, is_tx, keyblob) +# define BIO_set_ktls_ctrl_msg(b, record_type) \ + BIO_ctrl(b, BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG, record_type, NULL) +# define BIO_clear_ktls_ctrl_msg(b) \ + BIO_ctrl(b, BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG, 0, NULL) + +/* Functions to allow the core to offer the CORE_BIO type to providers */ +OSSL_CORE_BIO *ossl_core_bio_new_from_bio(BIO *bio); +OSSL_CORE_BIO *ossl_core_bio_new_file(const char *filename, const char *mode); +OSSL_CORE_BIO *ossl_core_bio_new_mem_buf(const void *buf, int len); +int ossl_core_bio_read_ex(OSSL_CORE_BIO *cb, void *data, size_t dlen, + size_t *readbytes); +int ossl_core_bio_write_ex(OSSL_CORE_BIO *cb, const void *data, size_t dlen, + size_t *written); +int ossl_core_bio_gets(OSSL_CORE_BIO *cb, char *buf, int size); +int ossl_core_bio_puts(OSSL_CORE_BIO *cb, const char *buf); +long ossl_core_bio_ctrl(OSSL_CORE_BIO *cb, int cmd, long larg, void *parg); +int ossl_core_bio_up_ref(OSSL_CORE_BIO *cb); +int ossl_core_bio_free(OSSL_CORE_BIO *cb); +int ossl_core_bio_vprintf(OSSL_CORE_BIO *cb, const char *format, va_list args); + +int ossl_bio_init_core(OSSL_LIB_CTX *libctx, const OSSL_DISPATCH *fns); + +#endif diff --git a/include/internal/comp.h b/include/internal/comp.h new file mode 100644 index 00000000..3ad86fc7 --- /dev/null +++ b/include/internal/comp.h @@ -0,0 +1,12 @@ +/* + * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/comp.h> + +void ossl_comp_zlib_cleanup(void); diff --git a/include/internal/conf.h b/include/internal/conf.h new file mode 100644 index 00000000..8c6c29cd --- /dev/null +++ b/include/internal/conf.h @@ -0,0 +1,31 @@ +/* + * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_CONF_H +# define OSSL_INTERNAL_CONF_H +# pragma once + +# include <openssl/conf.h> + +# define DEFAULT_CONF_MFLAGS \ + (CONF_MFLAGS_DEFAULT_SECTION | \ + CONF_MFLAGS_IGNORE_MISSING_FILE | \ + CONF_MFLAGS_IGNORE_RETURN_CODES) + +struct ossl_init_settings_st { + char *filename; + char *appname; + unsigned long flags; +}; + +int ossl_config_int(const OPENSSL_INIT_SETTINGS *); +void ossl_no_config_int(void); +void ossl_config_modules_free(void); + +#endif diff --git a/include/internal/constant_time.h b/include/internal/constant_time.h new file mode 100644 index 00000000..0ed6f823 --- /dev/null +++ b/include/internal/constant_time.h @@ -0,0 +1,421 @@ +/* + * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_CONSTANT_TIME_H +# define OSSL_INTERNAL_CONSTANT_TIME_H +# pragma once + +# include <stdlib.h> +# include <string.h> +# include <openssl/e_os2.h> /* For 'ossl_inline' */ + +/*- + * The boolean 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 + * unsigned int lt = constant_time_lt(a, b); + * c = constant_time_select(lt, a, b); + */ + +/* Returns the given value with the MSB copied to all the other bits. */ +static ossl_inline unsigned int constant_time_msb(unsigned int a); +/* Convenience method for uint32_t. */ +static ossl_inline uint32_t constant_time_msb_32(uint32_t a); +/* Convenience method for uint64_t. */ +static ossl_inline uint64_t constant_time_msb_64(uint64_t a); + +/* Returns 0xff..f if a < b and 0 otherwise. */ +static ossl_inline unsigned int constant_time_lt(unsigned int a, + unsigned int b); +/* Convenience method for getting an 8-bit mask. */ +static ossl_inline unsigned char constant_time_lt_8(unsigned int a, + unsigned int b); +/* Convenience method for uint64_t. */ +static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b); + +/* Returns 0xff..f if a >= b and 0 otherwise. */ +static ossl_inline unsigned int constant_time_ge(unsigned int a, + unsigned int b); +/* Convenience method for getting an 8-bit mask. */ +static ossl_inline unsigned char constant_time_ge_8(unsigned int a, + unsigned int b); + +/* Returns 0xff..f if a == 0 and 0 otherwise. */ +static ossl_inline unsigned int constant_time_is_zero(unsigned int a); +/* Convenience method for getting an 8-bit mask. */ +static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a); +/* Convenience method for getting a 32-bit mask. */ +static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a); + +/* Returns 0xff..f if a == b and 0 otherwise. */ +static ossl_inline unsigned int constant_time_eq(unsigned int a, + unsigned int b); +/* Convenience method for getting an 8-bit mask. */ +static ossl_inline unsigned char constant_time_eq_8(unsigned int a, + unsigned int b); +/* Signed integers. */ +static ossl_inline unsigned int constant_time_eq_int(int a, int b); +/* Convenience method for getting an 8-bit mask. */ +static ossl_inline unsigned char constant_time_eq_int_8(int a, int b); + +/*- + * 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). + */ +static ossl_inline unsigned int constant_time_select(unsigned int mask, + unsigned int a, + unsigned int b); +/* Convenience method for unsigned chars. */ +static ossl_inline unsigned char constant_time_select_8(unsigned char mask, + unsigned char a, + unsigned char b); + +/* Convenience method for uint32_t. */ +static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a, + uint32_t b); + +/* Convenience method for uint64_t. */ +static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a, + uint64_t b); +/* Convenience method for signed integers. */ +static ossl_inline int constant_time_select_int(unsigned int mask, int a, + int b); + + +static ossl_inline unsigned int constant_time_msb(unsigned int a) +{ + return 0 - (a >> (sizeof(a) * 8 - 1)); +} + + +static ossl_inline uint32_t constant_time_msb_32(uint32_t a) +{ + return 0 - (a >> 31); +} + +static ossl_inline uint64_t constant_time_msb_64(uint64_t a) +{ + return 0 - (a >> 63); +} + +static ossl_inline size_t constant_time_msb_s(size_t a) +{ + return 0 - (a >> (sizeof(a) * 8 - 1)); +} + +static ossl_inline unsigned int constant_time_lt(unsigned int a, + unsigned int b) +{ + return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b))); +} + +static ossl_inline size_t constant_time_lt_s(size_t a, size_t b) +{ + return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b))); +} + +static ossl_inline unsigned char constant_time_lt_8(unsigned int a, + unsigned int b) +{ + return (unsigned char)constant_time_lt(a, b); +} + +static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b) +{ + return constant_time_msb_64(a ^ ((a ^ b) | ((a - b) ^ b))); +} + +static ossl_inline unsigned int constant_time_ge(unsigned int a, + unsigned int b) +{ + return ~constant_time_lt(a, b); +} + +static ossl_inline size_t constant_time_ge_s(size_t a, size_t b) +{ + return ~constant_time_lt_s(a, b); +} + +static ossl_inline unsigned char constant_time_ge_8(unsigned int a, + unsigned int b) +{ + return (unsigned char)constant_time_ge(a, b); +} + +static ossl_inline unsigned char constant_time_ge_8_s(size_t a, size_t b) +{ + return (unsigned char)constant_time_ge_s(a, b); +} + +static ossl_inline unsigned int constant_time_is_zero(unsigned int a) +{ + return constant_time_msb(~a & (a - 1)); +} + +static ossl_inline size_t constant_time_is_zero_s(size_t a) +{ + return constant_time_msb_s(~a & (a - 1)); +} + +static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a) +{ + return (unsigned char)constant_time_is_zero(a); +} + +static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a) +{ + return constant_time_msb_32(~a & (a - 1)); +} + +static ossl_inline uint64_t constant_time_is_zero_64(uint64_t a) +{ + return constant_time_msb_64(~a & (a - 1)); +} + +static ossl_inline unsigned int constant_time_eq(unsigned int a, + unsigned int b) +{ + return constant_time_is_zero(a ^ b); +} + +static ossl_inline size_t constant_time_eq_s(size_t a, size_t b) +{ + return constant_time_is_zero_s(a ^ b); +} + +static ossl_inline unsigned char constant_time_eq_8(unsigned int a, + unsigned int b) +{ + return (unsigned char)constant_time_eq(a, b); +} + +static ossl_inline unsigned char constant_time_eq_8_s(size_t a, size_t b) +{ + return (unsigned char)constant_time_eq_s(a, b); +} + +static ossl_inline unsigned int constant_time_eq_int(int a, int b) +{ + return constant_time_eq((unsigned)(a), (unsigned)(b)); +} + +static ossl_inline unsigned char constant_time_eq_int_8(int a, int b) +{ + return constant_time_eq_8((unsigned)(a), (unsigned)(b)); +} + +/* + * Returns the value unmodified, but avoids optimizations. + * The barriers prevent the compiler from narrowing down the + * possible value range of the mask and ~mask in the select + * statements, which avoids the recognition of the select + * and turning it into a conditional load or branch. + */ +static ossl_inline unsigned int value_barrier(unsigned int a) +{ +#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) + unsigned int r; + __asm__("" : "=r"(r) : "0"(a)); +#else + volatile unsigned int r = a; +#endif + return r; +} + +/* Convenience method for uint32_t. */ +static ossl_inline uint32_t value_barrier_32(uint32_t a) +{ +#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) + uint32_t r; + __asm__("" : "=r"(r) : "0"(a)); +#else + volatile uint32_t r = a; +#endif + return r; +} + +/* Convenience method for uint64_t. */ +static ossl_inline uint64_t value_barrier_64(uint64_t a) +{ +#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) + uint64_t r; + __asm__("" : "=r"(r) : "0"(a)); +#else + volatile uint64_t r = a; +#endif + return r; +} + +/* Convenience method for size_t. */ +static ossl_inline size_t value_barrier_s(size_t a) +{ +#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) + size_t r; + __asm__("" : "=r"(r) : "0"(a)); +#else + volatile size_t r = a; +#endif + return r; +} + +static ossl_inline unsigned int constant_time_select(unsigned int mask, + unsigned int a, + unsigned int b) +{ + return (value_barrier(mask) & a) | (value_barrier(~mask) & b); +} + +static ossl_inline size_t constant_time_select_s(size_t mask, + size_t a, + size_t b) +{ + return (value_barrier_s(mask) & a) | (value_barrier_s(~mask) & b); +} + +static ossl_inline unsigned char constant_time_select_8(unsigned char mask, + unsigned char a, + unsigned char b) +{ + return (unsigned char)constant_time_select(mask, a, b); +} + +static ossl_inline int constant_time_select_int(unsigned int mask, int a, + int b) +{ + return (int)constant_time_select(mask, (unsigned)(a), (unsigned)(b)); +} + +static ossl_inline int constant_time_select_int_s(size_t mask, int a, int b) +{ + return (int)constant_time_select((unsigned)mask, (unsigned)(a), + (unsigned)(b)); +} + +static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a, + uint32_t b) +{ + return (value_barrier_32(mask) & a) | (value_barrier_32(~mask) & b); +} + +static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a, + uint64_t b) +{ + return (value_barrier_64(mask) & a) | (value_barrier_64(~mask) & b); +} + +/* + * mask must be 0xFFFFFFFF or 0x00000000. + * + * if (mask) { + * uint32_t tmp = *a; + * + * *a = *b; + * *b = tmp; + * } + */ +static ossl_inline void constant_time_cond_swap_32(uint32_t mask, uint32_t *a, + uint32_t *b) +{ + uint32_t xor = *a ^ *b; + + xor &= mask; + *a ^= xor; + *b ^= xor; +} + +/* + * mask must be 0xFFFFFFFF or 0x00000000. + * + * if (mask) { + * uint64_t tmp = *a; + * + * *a = *b; + * *b = tmp; + * } + */ +static ossl_inline void constant_time_cond_swap_64(uint64_t mask, uint64_t *a, + uint64_t *b) +{ + uint64_t xor = *a ^ *b; + + xor &= mask; + *a ^= xor; + *b ^= xor; +} + +/* + * mask must be 0xFF or 0x00. + * "constant time" is per len. + * + * if (mask) { + * unsigned char tmp[len]; + * + * memcpy(tmp, a, len); + * memcpy(a, b); + * memcpy(b, tmp); + * } + */ +static ossl_inline void constant_time_cond_swap_buff(unsigned char mask, + unsigned char *a, + unsigned char *b, + size_t len) +{ + size_t i; + unsigned char tmp; + + for (i = 0; i < len; i++) { + tmp = a[i] ^ b[i]; + tmp &= mask; + a[i] ^= tmp; + b[i] ^= tmp; + } +} + +/* + * table is a two dimensional array of bytes. Each row has rowsize elements. + * Copies row number idx into out. rowsize and numrows are not considered + * private. + */ +static ossl_inline void constant_time_lookup(void *out, + const void *table, + size_t rowsize, + size_t numrows, + size_t idx) +{ + size_t i, j; + const unsigned char *tablec = (const unsigned char *)table; + unsigned char *outc = (unsigned char *)out; + unsigned char mask; + + memset(out, 0, rowsize); + + /* Note idx may underflow - but that is well defined */ + for (i = 0; i < numrows; i++, idx--) { + mask = (unsigned char)constant_time_is_zero_s(idx); + for (j = 0; j < rowsize; j++) + *(outc + j) |= constant_time_select_8(mask, *(tablec++), 0); + } +} + +/* + * Expected usage pattern is to unconditionally set error and then + * wipe it if there was no actual error. |clear| is 1 or 0. + */ +void err_clear_last_constant_time(int clear); + +#endif /* OSSL_INTERNAL_CONSTANT_TIME_H */ diff --git a/include/internal/core.h b/include/internal/core.h new file mode 100644 index 00000000..d9dc4241 --- /dev/null +++ b/include/internal/core.h @@ -0,0 +1,66 @@ +/* + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_CORE_H +# define OSSL_INTERNAL_CORE_H +# pragma once + +/* + * namespaces: + * + * ossl_method_ Core Method API + */ + +/* + * construct an arbitrary method from a dispatch table found by looking + * up a match for the < operation_id, name, property > combination. + * constructor and destructor are the constructor and destructor for that + * arbitrary object. + * + * These objects are normally cached, unless the provider says not to cache. + * However, force_cache can be used to force caching whatever the provider + * says (for example, because the application knows better). + */ +typedef struct ossl_method_construct_method_st { + /* Get a temporary store */ + void *(*get_tmp_store)(void *data); + /* Get an already existing method from a store */ + void *(*get)(void *store, const OSSL_PROVIDER **prov, void *data); + /* Store a method in a store */ + int (*put)(void *store, void *method, const OSSL_PROVIDER *prov, + const char *name, const char *propdef, void *data); + /* Construct a new method */ + void *(*construct)(const OSSL_ALGORITHM *algodef, OSSL_PROVIDER *prov, + void *data); + /* Destruct a method */ + void (*destruct)(void *method, void *data); +} OSSL_METHOD_CONSTRUCT_METHOD; + +void *ossl_method_construct(OSSL_LIB_CTX *ctx, int operation_id, + OSSL_PROVIDER **provider_rw, int force_cache, + OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data); + +void ossl_algorithm_do_all(OSSL_LIB_CTX *libctx, int operation_id, + OSSL_PROVIDER *provider, + int (*pre)(OSSL_PROVIDER *, int operation_id, + void *data, int *result), + void (*fn)(OSSL_PROVIDER *provider, + const OSSL_ALGORITHM *algo, + int no_store, void *data), + int (*post)(OSSL_PROVIDER *, int operation_id, + int no_store, void *data, int *result), + void *data); +char *ossl_algorithm_get1_first_name(const OSSL_ALGORITHM *algo); + +__owur int ossl_lib_ctx_write_lock(OSSL_LIB_CTX *ctx); +__owur int ossl_lib_ctx_read_lock(OSSL_LIB_CTX *ctx); +int ossl_lib_ctx_unlock(OSSL_LIB_CTX *ctx); +int ossl_lib_ctx_is_child(OSSL_LIB_CTX *ctx); + +#endif diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h new file mode 100644 index 00000000..1291299b --- /dev/null +++ b/include/internal/cryptlib.h @@ -0,0 +1,261 @@ +/* + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_CRYPTLIB_H +# define OSSL_INTERNAL_CRYPTLIB_H +# pragma once + +# include <stdlib.h> +# include <string.h> + +# ifdef OPENSSL_USE_APPLINK +# define BIO_FLAGS_UPLINK_INTERNAL 0x8000 +# include "ms/uplink.h" +# else +# define BIO_FLAGS_UPLINK_INTERNAL 0 +# endif + +# include <openssl/crypto.h> +# include <openssl/buffer.h> +# include <openssl/bio.h> +# include <openssl/asn1.h> +# include <openssl/err.h> +# include "internal/nelem.h" + +#ifdef NDEBUG +# define ossl_assert(x) ((x) != 0) +#else +__owur static ossl_inline int ossl_assert_int(int expr, const char *exprstr, + const char *file, int line) +{ + if (!expr) + OPENSSL_die(exprstr, file, line); + + return expr; +} + +# define ossl_assert(x) ossl_assert_int((x) != 0, "Assertion failed: "#x, \ + __FILE__, __LINE__) + +#endif + +/* + * Use this inside a union with the field that needs to be aligned to a + * reasonable boundary for the platform. The most pessimistic alignment + * of the listed types will be used by the compiler. + */ +# define OSSL_UNION_ALIGN \ + double align; \ + ossl_uintmax_t align_int; \ + void *align_ptr + +typedef struct ex_callback_st EX_CALLBACK; +DEFINE_STACK_OF(EX_CALLBACK) + +typedef struct mem_st MEM; +DEFINE_LHASH_OF(MEM); + +# define OPENSSL_CONF "openssl.cnf" + +# ifndef OPENSSL_SYS_VMS +# define X509_CERT_AREA OPENSSLDIR +# define X509_CERT_DIR OPENSSLDIR "/certs" +# define X509_CERT_FILE OPENSSLDIR "/cert.pem" +# define X509_PRIVATE_DIR OPENSSLDIR "/private" +# define CTLOG_FILE OPENSSLDIR "/ct_log_list.cnf" +# else +# define X509_CERT_AREA "OSSL$DATAROOT:[000000]" +# define X509_CERT_DIR "OSSL$DATAROOT:[CERTS]" +# define X509_CERT_FILE "OSSL$DATAROOT:[000000]cert.pem" +# define X509_PRIVATE_DIR "OSSL$DATAROOT:[PRIVATE]" +# define CTLOG_FILE "OSSL$DATAROOT:[000000]ct_log_list.cnf" +# endif + +# define X509_CERT_DIR_EVP "SSL_CERT_DIR" +# define X509_CERT_FILE_EVP "SSL_CERT_FILE" +# define CTLOG_FILE_EVP "CTLOG_FILE" + +/* size of string representations */ +# define DECIMAL_SIZE(type) ((sizeof(type)*8+2)/3+1) +# define HEX_SIZE(type) (sizeof(type)*2) + +void OPENSSL_cpuid_setup(void); +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64) +extern unsigned int OPENSSL_ia32cap_P[]; +#endif +void OPENSSL_showfatal(const char *fmta, ...); +int ossl_do_ex_data_init(OSSL_LIB_CTX *ctx); +void ossl_crypto_cleanup_all_ex_data_int(OSSL_LIB_CTX *ctx); +int openssl_init_fork_handlers(void); +int openssl_get_fork_id(void); + +char *ossl_safe_getenv(const char *name); + +extern CRYPTO_RWLOCK *memdbg_lock; +int openssl_strerror_r(int errnum, char *buf, size_t buflen); +# if !defined(OPENSSL_NO_STDIO) +FILE *openssl_fopen(const char *filename, const char *mode); +# else +void *openssl_fopen(const char *filename, const char *mode); +# endif + +uint32_t OPENSSL_rdtsc(void); +size_t OPENSSL_instrument_bus(unsigned int *, size_t); +size_t OPENSSL_instrument_bus2(unsigned int *, size_t, size_t); + +/* ex_data structures */ + +/* + * Each structure type (sometimes called a class), that supports + * exdata has a stack of callbacks for each instance. + */ +struct ex_callback_st { + long argl; /* Arbitrary long */ + void *argp; /* Arbitrary void * */ + int priority; /* Priority ordering for freeing */ + CRYPTO_EX_new *new_func; + CRYPTO_EX_free *free_func; + CRYPTO_EX_dup *dup_func; +}; + +/* + * The state for each class. This could just be a typedef, but + * a structure allows future changes. + */ +typedef struct ex_callbacks_st { + STACK_OF(EX_CALLBACK) *meth; +} EX_CALLBACKS; + +typedef struct ossl_ex_data_global_st { + CRYPTO_RWLOCK *ex_data_lock; + EX_CALLBACKS ex_data[CRYPTO_EX_INDEX__COUNT]; +} OSSL_EX_DATA_GLOBAL; + + +/* OSSL_LIB_CTX */ + +# define OSSL_LIB_CTX_PROVIDER_STORE_RUN_ONCE_INDEX 0 +# define OSSL_LIB_CTX_DEFAULT_METHOD_STORE_RUN_ONCE_INDEX 1 +# define OSSL_LIB_CTX_METHOD_STORE_RUN_ONCE_INDEX 2 +# define OSSL_LIB_CTX_MAX_RUN_ONCE 3 + +# define OSSL_LIB_CTX_EVP_METHOD_STORE_INDEX 0 +# define OSSL_LIB_CTX_PROVIDER_STORE_INDEX 1 +# define OSSL_LIB_CTX_PROPERTY_DEFN_INDEX 2 +# define OSSL_LIB_CTX_PROPERTY_STRING_INDEX 3 +# define OSSL_LIB_CTX_NAMEMAP_INDEX 4 +# define OSSL_LIB_CTX_DRBG_INDEX 5 +# define OSSL_LIB_CTX_DRBG_NONCE_INDEX 6 +# define OSSL_LIB_CTX_RAND_CRNGT_INDEX 7 +# ifdef FIPS_MODULE +# define OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX 8 +# endif +# define OSSL_LIB_CTX_FIPS_PROV_INDEX 9 +# define OSSL_LIB_CTX_ENCODER_STORE_INDEX 10 +# define OSSL_LIB_CTX_DECODER_STORE_INDEX 11 +# define OSSL_LIB_CTX_SELF_TEST_CB_INDEX 12 +# define OSSL_LIB_CTX_BIO_PROV_INDEX 13 +# define OSSL_LIB_CTX_GLOBAL_PROPERTIES 14 +# define OSSL_LIB_CTX_STORE_LOADER_STORE_INDEX 15 +# define OSSL_LIB_CTX_PROVIDER_CONF_INDEX 16 +# define OSSL_LIB_CTX_BIO_CORE_INDEX 17 +# define OSSL_LIB_CTX_CHILD_PROVIDER_INDEX 18 +# define OSSL_LIB_CTX_MAX_INDEXES 19 + +# define OSSL_LIB_CTX_METHOD_LOW_PRIORITY -1 +# define OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY 0 +# define OSSL_LIB_CTX_METHOD_PRIORITY_1 1 +# define OSSL_LIB_CTX_METHOD_PRIORITY_2 2 + +typedef struct ossl_lib_ctx_method { + int priority; + void *(*new_func)(OSSL_LIB_CTX *ctx); + void (*free_func)(void *); +} OSSL_LIB_CTX_METHOD; + +OSSL_LIB_CTX *ossl_lib_ctx_get_concrete(OSSL_LIB_CTX *ctx); +int ossl_lib_ctx_is_default(OSSL_LIB_CTX *ctx); +int ossl_lib_ctx_is_global_default(OSSL_LIB_CTX *ctx); + +/* Functions to retrieve pointers to data by index */ +void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *, int /* index */, + const OSSL_LIB_CTX_METHOD * ctx); + +void ossl_lib_ctx_default_deinit(void); +OSSL_EX_DATA_GLOBAL *ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX *ctx); +typedef int (ossl_lib_ctx_run_once_fn)(OSSL_LIB_CTX *ctx); +typedef void (ossl_lib_ctx_onfree_fn)(OSSL_LIB_CTX *ctx); + +int ossl_lib_ctx_run_once(OSSL_LIB_CTX *ctx, unsigned int idx, + ossl_lib_ctx_run_once_fn run_once_fn); +int ossl_lib_ctx_onfree(OSSL_LIB_CTX *ctx, ossl_lib_ctx_onfree_fn onfreefn); +const char *ossl_lib_ctx_get_descriptor(OSSL_LIB_CTX *libctx); + +OSSL_LIB_CTX *ossl_crypto_ex_data_get_ossl_lib_ctx(const CRYPTO_EX_DATA *ad); +int ossl_crypto_new_ex_data_ex(OSSL_LIB_CTX *ctx, int class_index, void *obj, + CRYPTO_EX_DATA *ad); +int ossl_crypto_get_ex_new_index_ex(OSSL_LIB_CTX *ctx, int class_index, + long argl, void *argp, + CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func, + int priority); +int ossl_crypto_free_ex_index_ex(OSSL_LIB_CTX *ctx, int class_index, int idx); + +/* Function for simple binary search */ + +/* Flags */ +# define OSSL_BSEARCH_VALUE_ON_NOMATCH 0x01 +# define OSSL_BSEARCH_FIRST_VALUE_ON_MATCH 0x02 + +const void *ossl_bsearch(const void *key, const void *base, int num, + int size, int (*cmp) (const void *, const void *), + int flags); + +char *ossl_sk_ASN1_UTF8STRING2text(STACK_OF(ASN1_UTF8STRING) *text, + const char *sep, size_t max_len); +char *ossl_ipaddr_to_asc(unsigned char *p, int len); + +char *ossl_buf2hexstr_sep(const unsigned char *buf, long buflen, char sep); +unsigned char *ossl_hexstr2buf_sep(const char *str, long *buflen, + const char sep); + +static ossl_inline int ossl_ends_with_dirsep(const char *path) +{ + if (*path != '\0') + path += strlen(path) - 1; +# if defined __VMS + if (*path == ']' || *path == '>' || *path == ':') + return 1; +# elif defined _WIN32 + if (*path == '\\') + return 1; +# endif + return *path == '/'; +} + +static ossl_inline int ossl_is_absolute_path(const char *path) +{ +# if defined __VMS + if (strchr(path, ':') != NULL + || ((path[0] == '[' || path[0] == '<') + && path[1] != '.' && path[1] != '-' + && path[1] != ']' && path[1] != '>')) + return 1; +# elif defined _WIN32 + if (path[0] == '\\' + || (path[0] != '\0' && path[1] == ':')) + return 1; +# endif + return path[0] == '/'; +} + +#endif diff --git a/include/internal/dane.h b/include/internal/dane.h new file mode 100644 index 00000000..a3d78a7f --- /dev/null +++ b/include/internal/dane.h @@ -0,0 +1,104 @@ +/* + * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_DANE_H +#define OSSL_INTERNAL_DANE_H +# pragma once + +# include <openssl/safestack.h> + +/*- + * Certificate usages: + * https://tools.ietf.org/html/rfc6698#section-2.1.1 + */ +#define DANETLS_USAGE_PKIX_TA 0 +#define DANETLS_USAGE_PKIX_EE 1 +#define DANETLS_USAGE_DANE_TA 2 +#define DANETLS_USAGE_DANE_EE 3 +#define DANETLS_USAGE_LAST DANETLS_USAGE_DANE_EE + +/*- + * Selectors: + * https://tools.ietf.org/html/rfc6698#section-2.1.2 + */ +#define DANETLS_SELECTOR_CERT 0 +#define DANETLS_SELECTOR_SPKI 1 +#define DANETLS_SELECTOR_LAST DANETLS_SELECTOR_SPKI + +/*- + * Matching types: + * https://tools.ietf.org/html/rfc6698#section-2.1.3 + */ +#define DANETLS_MATCHING_FULL 0 +#define DANETLS_MATCHING_2256 1 +#define DANETLS_MATCHING_2512 2 +#define DANETLS_MATCHING_LAST DANETLS_MATCHING_2512 + +typedef struct danetls_record_st { + uint8_t usage; + uint8_t selector; + uint8_t mtype; + unsigned char *data; + size_t dlen; + EVP_PKEY *spki; +} danetls_record; + +DEFINE_STACK_OF(danetls_record) + +/* + * Shared DANE context + */ +struct dane_ctx_st { + const EVP_MD **mdevp; /* mtype -> digest */ + uint8_t *mdord; /* mtype -> preference */ + uint8_t mdmax; /* highest supported mtype */ + unsigned long flags; /* feature bitmask */ +}; + +/* + * Per connection DANE state + */ +struct ssl_dane_st { + struct dane_ctx_st *dctx; + STACK_OF(danetls_record) *trecs; + STACK_OF(X509) *certs; /* DANE-TA(2) Cert(0) Full(0) certs */ + danetls_record *mtlsa; /* Matching TLSA record */ + X509 *mcert; /* DANE matched cert */ + uint32_t umask; /* Usages present */ + int mdpth; /* Depth of matched cert */ + int pdpth; /* Depth of PKIX trust */ + unsigned long flags; /* feature bitmask */ +}; + +#define DANETLS_ENABLED(dane) \ + ((dane) != NULL && sk_danetls_record_num((dane)->trecs) > 0) + +#define DANETLS_USAGE_BIT(u) (((uint32_t)1) << u) + +#define DANETLS_PKIX_TA_MASK (DANETLS_USAGE_BIT(DANETLS_USAGE_PKIX_TA)) +#define DANETLS_PKIX_EE_MASK (DANETLS_USAGE_BIT(DANETLS_USAGE_PKIX_EE)) +#define DANETLS_DANE_TA_MASK (DANETLS_USAGE_BIT(DANETLS_USAGE_DANE_TA)) +#define DANETLS_DANE_EE_MASK (DANETLS_USAGE_BIT(DANETLS_USAGE_DANE_EE)) + +#define DANETLS_PKIX_MASK (DANETLS_PKIX_TA_MASK | DANETLS_PKIX_EE_MASK) +#define DANETLS_DANE_MASK (DANETLS_DANE_TA_MASK | DANETLS_DANE_EE_MASK) +#define DANETLS_TA_MASK (DANETLS_PKIX_TA_MASK | DANETLS_DANE_TA_MASK) +#define DANETLS_EE_MASK (DANETLS_PKIX_EE_MASK | DANETLS_DANE_EE_MASK) + +#define DANETLS_HAS_PKIX(dane) ((dane) && ((dane)->umask & DANETLS_PKIX_MASK)) +#define DANETLS_HAS_DANE(dane) ((dane) && ((dane)->umask & DANETLS_DANE_MASK)) +#define DANETLS_HAS_TA(dane) ((dane) && ((dane)->umask & DANETLS_TA_MASK)) +#define DANETLS_HAS_EE(dane) ((dane) && ((dane)->umask & DANETLS_EE_MASK)) + +#define DANETLS_HAS_PKIX_TA(dane) ((dane)&&((dane)->umask & DANETLS_PKIX_TA_MASK)) +#define DANETLS_HAS_PKIX_EE(dane) ((dane)&&((dane)->umask & DANETLS_PKIX_EE_MASK)) +#define DANETLS_HAS_DANE_TA(dane) ((dane)&&((dane)->umask & DANETLS_DANE_TA_MASK)) +#define DANETLS_HAS_DANE_EE(dane) ((dane)&&((dane)->umask & DANETLS_DANE_EE_MASK)) + +#endif /* OSSL_INTERNAL_DANE_H */ diff --git a/include/internal/deprecated.h b/include/internal/deprecated.h new file mode 100644 index 00000000..a313a015 --- /dev/null +++ b/include/internal/deprecated.h @@ -0,0 +1,30 @@ +/* + * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This header file should be included by internal code that needs to use APIs + * that have been deprecated for public use, but where those symbols will still + * be available internally. For example the EVP and provider code needs to use + * low level APIs that are otherwise deprecated. + * + * This header *must* be the first OpenSSL header included by a source file. + */ + +#ifndef OSSL_INTERNAL_DEPRECATED_H +# define OSSL_INTERNAL_DEPRECATED_H +# pragma once + +# include <openssl/configuration.h> + +# undef OPENSSL_NO_DEPRECATED +# define OPENSSL_SUPPRESS_DEPRECATED + +# include <openssl/macros.h> + +#endif diff --git a/include/internal/der.h b/include/internal/der.h new file mode 100644 index 00000000..a3e56d0d --- /dev/null +++ b/include/internal/der.h @@ -0,0 +1,88 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/bn.h> +#include "internal/packet.h" + +/* + * NOTE: X.690 numbers the identifier octet bits 1 to 8. + * We use the same numbering in comments here. + */ + +/* Well known primitive tags */ + +/* + * DER UNIVERSAL tags, occupying bits 1-5 in the DER identifier byte + * These are only valid for the UNIVERSAL class. With the other classes, + * these bits have a different meaning. + */ +#define DER_P_EOC 0 /* BER End Of Contents tag */ +#define DER_P_BOOLEAN 1 +#define DER_P_INTEGER 2 +#define DER_P_BIT_STRING 3 +#define DER_P_OCTET_STRING 4 +#define DER_P_NULL 5 +#define DER_P_OBJECT 6 +#define DER_P_OBJECT_DESCRIPTOR 7 +#define DER_P_EXTERNAL 8 +#define DER_P_REAL 9 +#define DER_P_ENUMERATED 10 +#define DER_P_UTF8STRING 12 +#define DER_P_SEQUENCE 16 +#define DER_P_SET 17 +#define DER_P_NUMERICSTRING 18 +#define DER_P_PRINTABLESTRING 19 +#define DER_P_T61STRING 20 +#define DER_P_VIDEOTEXSTRING 21 +#define DER_P_IA5STRING 22 +#define DER_P_UTCTIME 23 +#define DER_P_GENERALIZEDTIME 24 +#define DER_P_GRAPHICSTRING 25 +#define DER_P_ISO64STRING 26 +#define DER_P_GENERALSTRING 27 +#define DER_P_UNIVERSALSTRING 28 +#define DER_P_BMPSTRING 30 + +/* DER Flags, occupying bit 6 in the DER identifier byte */ +#define DER_F_PRIMITIVE 0x00 +#define DER_F_CONSTRUCTED 0x20 + +/* DER classes tags, occupying bits 7-8 in the DER identifier byte */ +#define DER_C_UNIVERSAL 0x00 +#define DER_C_APPLICATION 0x40 +#define DER_C_CONTEXT 0x80 +#define DER_C_PRIVATE 0xC0 + +/* + * Run-time constructors. + * + * They all construct DER backwards, so care should be taken to use them + * that way. + */ + +/* This can be used for all items that don't have a context */ +#define DER_NO_CONTEXT -1 + +int ossl_DER_w_precompiled(WPACKET *pkt, int tag, + const unsigned char *precompiled, + size_t precompiled_n); + +int ossl_DER_w_boolean(WPACKET *pkt, int tag, int b); +int ossl_DER_w_ulong(WPACKET *pkt, int tag, unsigned long v); +int ossl_DER_w_bn(WPACKET *pkt, int tag, const BIGNUM *v); +int ossl_DER_w_null(WPACKET *pkt, int tag); +int ossl_DER_w_octet_string(WPACKET *pkt, int tag, + const unsigned char *data, size_t data_n); +int ossl_DER_w_octet_string_uint32(WPACKET *pkt, int tag, uint32_t value); + +/* + * All constructors for constructed elements have a begin and a end function + */ +int ossl_DER_w_begin_sequence(WPACKET *pkt, int tag); +int ossl_DER_w_end_sequence(WPACKET *pkt, int tag); diff --git a/include/internal/dso.h b/include/internal/dso.h new file mode 100644 index 00000000..160ddb98 --- /dev/null +++ b/include/internal/dso.h @@ -0,0 +1,164 @@ +/* + * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_DSO_H +# define OSSL_INTERNAL_DSO_H +# pragma once + +# include <openssl/crypto.h> +# include "internal/dsoerr.h" + +/* These values are used as commands to DSO_ctrl() */ +# define DSO_CTRL_GET_FLAGS 1 +# define DSO_CTRL_SET_FLAGS 2 +# define DSO_CTRL_OR_FLAGS 3 + +/* + * By default, DSO_load() will translate the provided filename into a form + * typical for the platform using the dso_name_converter function of the + * method. Eg. win32 will transform "blah" into "blah.dll", and dlfcn will + * transform it into "libblah.so". This callback could even utilise the + * DSO_METHOD's converter too if it only wants to override behaviour for + * one or two possible DSO methods. However, the following flag can be + * set in a DSO to prevent *any* native name-translation at all - eg. if + * the caller has prompted the user for a path to a driver library so the + * filename should be interpreted as-is. + */ +# define DSO_FLAG_NO_NAME_TRANSLATION 0x01 +/* + * An extra flag to give if only the extension should be added as + * translation. This is obviously only of importance on Unix and other + * operating systems where the translation also may prefix the name with + * something, like 'lib', and ignored everywhere else. This flag is also + * ignored if DSO_FLAG_NO_NAME_TRANSLATION is used at the same time. + */ +# define DSO_FLAG_NAME_TRANSLATION_EXT_ONLY 0x02 + +/* + * Don't unload the DSO when we call DSO_free() + */ +# define DSO_FLAG_NO_UNLOAD_ON_FREE 0x04 + +/* + * This flag loads the library with public symbols. Meaning: The exported + * symbols of this library are public to all libraries loaded after this + * library. At the moment only implemented in unix. + */ +# define DSO_FLAG_GLOBAL_SYMBOLS 0x20 + +typedef void (*DSO_FUNC_TYPE) (void); + +typedef struct dso_st DSO; +typedef struct dso_meth_st DSO_METHOD; + +/* + * The function prototype used for method functions (or caller-provided + * callbacks) that transform filenames. They are passed a DSO structure + * pointer (or NULL if they are to be used independently of a DSO object) and + * a filename to transform. They should either return NULL (if there is an + * error condition) or a newly allocated string containing the transformed + * form that the caller will need to free with OPENSSL_free() when done. + */ +typedef char *(*DSO_NAME_CONVERTER_FUNC)(DSO *, const char *); +/* + * The function prototype used for method functions (or caller-provided + * callbacks) that merge two file specifications. They are passed a DSO + * structure pointer (or NULL if they are to be used independently of a DSO + * object) and two file specifications to merge. They should either return + * NULL (if there is an error condition) or a newly allocated string + * containing the result of merging that the caller will need to free with + * OPENSSL_free() when done. Here, merging means that bits and pieces are + * taken from each of the file specifications and added together in whatever + * fashion that is sensible for the DSO method in question. The only rule + * that really applies is that if the two specification contain pieces of the + * same type, the copy from the first string takes priority. One could see + * it as the first specification is the one given by the user and the second + * being a bunch of defaults to add on if they're missing in the first. + */ +typedef char *(*DSO_MERGER_FUNC)(DSO *, const char *, const char *); + +DSO *DSO_new(void); +int DSO_free(DSO *dso); +int DSO_flags(DSO *dso); +int DSO_up_ref(DSO *dso); +long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg); + +/* + * These functions can be used to get/set the platform-independent filename + * used for a DSO. NB: set will fail if the DSO is already loaded. + */ +const char *DSO_get_filename(DSO *dso); +int DSO_set_filename(DSO *dso, const char *filename); +/* + * This function will invoke the DSO's name_converter callback to translate a + * filename, or if the callback isn't set it will instead use the DSO_METHOD's + * converter. If "filename" is NULL, the "filename" in the DSO itself will be + * used. If the DSO_FLAG_NO_NAME_TRANSLATION flag is set, then the filename is + * simply duplicated. NB: This function is usually called from within a + * DSO_METHOD during the processing of a DSO_load() call, and is exposed so + * that caller-created DSO_METHODs can do the same thing. A non-NULL return + * value will need to be OPENSSL_free()'d. + */ +char *DSO_convert_filename(DSO *dso, const char *filename); +/* + * This function will invoke the DSO's merger callback to merge two file + * specifications, or if the callback isn't set it will instead use the + * DSO_METHOD's merger. A non-NULL return value will need to be + * OPENSSL_free()'d. + */ +char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2); + +/* + * The all-singing all-dancing load function, you normally pass NULL for the + * first and third parameters. Use DSO_up_ref and DSO_free for subsequent + * reference count handling. Any flags passed in will be set in the + * constructed DSO after its init() function but before the load operation. + * If 'dso' is non-NULL, 'flags' is ignored. + */ +DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags); + +/* This function binds to a function inside a shared library. */ +DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname); + +/* + * This method is the default, but will beg, borrow, or steal whatever method + * should be the default on any particular platform (including + * DSO_METH_null() if necessary). + */ +DSO_METHOD *DSO_METHOD_openssl(void); + +/* + * This function writes null-terminated pathname of DSO module containing + * 'addr' into 'sz' large caller-provided 'path' and returns the number of + * characters [including trailing zero] written to it. If 'sz' is 0 or + * negative, 'path' is ignored and required amount of characters [including + * trailing zero] to accommodate pathname is returned. If 'addr' is NULL, then + * pathname of cryptolib itself is returned. Negative or zero return value + * denotes error. + */ +int DSO_pathbyaddr(void *addr, char *path, int sz); + +/* + * Like DSO_pathbyaddr() but instead returns a handle to the DSO for the symbol + * or NULL on error. + */ +DSO *DSO_dsobyaddr(void *addr, int flags); + +/* + * This function should be used with caution! It looks up symbols in *all* + * loaded modules and if module gets unloaded by somebody else attempt to + * dereference the pointer is doomed to have fatal consequences. Primary + * usage for this function is to probe *core* system functionality, e.g. + * check if getnameinfo(3) is available at run-time without bothering about + * OS-specific details such as libc.so.versioning or where does it actually + * reside: in libc itself or libsocket. + */ +void *DSO_global_lookup(const char *name); + +#endif diff --git a/include/internal/dsoerr.h b/include/internal/dsoerr.h new file mode 100644 index 00000000..b1719e83 --- /dev/null +++ b/include/internal/dsoerr.h @@ -0,0 +1,48 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_DSOERR_H +# define OSSL_INTERNAL_DSOERR_H +# pragma once + +# include <openssl/opensslconf.h> +# include <openssl/symhacks.h> + +# ifdef __cplusplus +extern "C" { +# endif + +int ossl_err_load_DSO_strings(void); + +/* + * DSO reason codes. + */ +# define DSO_R_CTRL_FAILED 100 +# define DSO_R_DSO_ALREADY_LOADED 110 +# define DSO_R_EMPTY_FILE_STRUCTURE 113 +# define DSO_R_FAILURE 114 +# define DSO_R_FILENAME_TOO_BIG 101 +# define DSO_R_FINISH_FAILED 102 +# define DSO_R_INCORRECT_FILE_SYNTAX 115 +# define DSO_R_LOAD_FAILED 103 +# define DSO_R_NAME_TRANSLATION_FAILED 109 +# define DSO_R_NO_FILENAME 111 +# define DSO_R_NULL_HANDLE 104 +# define DSO_R_SET_FILENAME_FAILED 112 +# define DSO_R_STACK_ERROR 105 +# define DSO_R_SYM_FAILURE 106 +# define DSO_R_UNLOAD_FAILED 107 +# define DSO_R_UNSUPPORTED 108 + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/include/internal/endian.h b/include/internal/endian.h new file mode 100644 index 00000000..8b34e03e --- /dev/null +++ b/include/internal/endian.h @@ -0,0 +1,51 @@ +/* + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_ENDIAN_H +# define OSSL_INTERNAL_ENDIAN_H +# pragma once + +/* + * IS_LITTLE_ENDIAN and IS_BIG_ENDIAN can be used to detect the endiannes + * at compile time. To use it, DECLARE_IS_ENDIAN must be used to declare + * a variable. + * + * L_ENDIAN and B_ENDIAN can be used at preprocessor time. They can be set + * in the configarion using the lib_cppflags variable. If neither is + * set, it will fall back to code works with either endianness. + */ + +# if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) +# define DECLARE_IS_ENDIAN const int ossl_is_little_endian = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define IS_LITTLE_ENDIAN (ossl_is_little_endian) +# define IS_BIG_ENDIAN (!ossl_is_little_endian) +# if defined(L_ENDIAN) && (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__) +# error "L_ENDIAN defined on a big endian machine" +# endif +# if defined(B_ENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +# error "B_ENDIAN defined on a little endian machine" +# endif +# if !defined(L_ENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +# define L_ENDIAN +# endif +# if !defined(B_ENDIAN) && (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__) +# define B_ENDIAN +# endif +# else +# define DECLARE_IS_ENDIAN \ + const union { \ + long one; \ + char little; \ + } ossl_is_endian = { 1 } + +# define IS_LITTLE_ENDIAN (ossl_is_endian.little != 0) +# define IS_BIG_ENDIAN (ossl_is_endian.little == 0) +# endif + +#endif diff --git a/include/internal/err.h b/include/internal/err.h new file mode 100644 index 00000000..d8a308f0 --- /dev/null +++ b/include/internal/err.h @@ -0,0 +1,16 @@ +/* + * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_ERR_H +# define OSSL_INTERNAL_ERR_H +# pragma once + +void err_free_strings_int(void); + +#endif diff --git a/include/internal/ffc.h b/include/internal/ffc.h new file mode 100644 index 00000000..79cb06ab --- /dev/null +++ b/include/internal/ffc.h @@ -0,0 +1,212 @@ +/* + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_FFC_H +# define OSSL_INTERNAL_FFC_H +# pragma once + +# include <openssl/core.h> +# include <openssl/bn.h> +# include <openssl/evp.h> +# include <openssl/dh.h> /* Uses Error codes from DH */ +# include <openssl/params.h> +# include <openssl/param_build.h> +# include "internal/sizes.h" + +/* Default value for gindex when canonical generation of g is not used */ +# define FFC_UNVERIFIABLE_GINDEX -1 + +/* The different types of FFC keys */ +# define FFC_PARAM_TYPE_DSA 0 +# define FFC_PARAM_TYPE_DH 1 + +/* + * The mode used by functions that share code for both generation and + * verification. See ossl_ffc_params_FIPS186_4_gen_verify(). + */ +#define FFC_PARAM_MODE_VERIFY 0 +#define FFC_PARAM_MODE_GENERATE 1 + +/* Return codes for generation and validation of FFC parameters */ +#define FFC_PARAM_RET_STATUS_FAILED 0 +#define FFC_PARAM_RET_STATUS_SUCCESS 1 +/* Returned if validating and g is only partially verifiable */ +#define FFC_PARAM_RET_STATUS_UNVERIFIABLE_G 2 + +/* Validation flags */ +# define FFC_PARAM_FLAG_VALIDATE_PQ 0x01 +# define FFC_PARAM_FLAG_VALIDATE_G 0x02 +# define FFC_PARAM_FLAG_VALIDATE_PQG \ + (FFC_PARAM_FLAG_VALIDATE_PQ | FFC_PARAM_FLAG_VALIDATE_G) +#define FFC_PARAM_FLAG_VALIDATE_LEGACY 0x04 + +/* + * NB: These values must align with the equivalently named macros in + * openssl/dh.h. We cannot use those macros here in case DH has been disabled. + */ +# define FFC_CHECK_P_NOT_PRIME 0x00001 +# define FFC_CHECK_P_NOT_SAFE_PRIME 0x00002 +# define FFC_CHECK_UNKNOWN_GENERATOR 0x00004 +# define FFC_CHECK_NOT_SUITABLE_GENERATOR 0x00008 +# define FFC_CHECK_Q_NOT_PRIME 0x00010 +# define FFC_CHECK_INVALID_Q_VALUE 0x00020 +# define FFC_CHECK_INVALID_J_VALUE 0x00040 + +# define FFC_CHECK_BAD_LN_PAIR 0x00080 +# define FFC_CHECK_INVALID_SEED_SIZE 0x00100 +# define FFC_CHECK_MISSING_SEED_OR_COUNTER 0x00200 +# define FFC_CHECK_INVALID_G 0x00400 +# define FFC_CHECK_INVALID_PQ 0x00800 +# define FFC_CHECK_INVALID_COUNTER 0x01000 +# define FFC_CHECK_P_MISMATCH 0x02000 +# define FFC_CHECK_Q_MISMATCH 0x04000 +# define FFC_CHECK_G_MISMATCH 0x08000 +# define FFC_CHECK_COUNTER_MISMATCH 0x10000 + +/* Validation Return codes */ +# define FFC_ERROR_PUBKEY_TOO_SMALL 0x01 +# define FFC_ERROR_PUBKEY_TOO_LARGE 0x02 +# define FFC_ERROR_PUBKEY_INVALID 0x04 +# define FFC_ERROR_NOT_SUITABLE_GENERATOR 0x08 +# define FFC_ERROR_PRIVKEY_TOO_SMALL 0x10 +# define FFC_ERROR_PRIVKEY_TOO_LARGE 0x20 + +/* + * Finite field cryptography (FFC) domain parameters are used by DH and DSA. + * Refer to FIPS186_4 Appendix A & B. + */ +typedef struct ffc_params_st { + /* Primes */ + BIGNUM *p; + BIGNUM *q; + /* Generator */ + BIGNUM *g; + /* DH X9.42 Optional Subgroup factor j >= 2 where p = j * q + 1 */ + BIGNUM *j; + + /* Required for FIPS186_4 validation of p, q and optionally canonical g */ + unsigned char *seed; + /* If this value is zero the hash size is used as the seed length */ + size_t seedlen; + /* Required for FIPS186_4 validation of p and q */ + int pcounter; + int nid; /* The identity of a named group */ + + /* + * Required for FIPS186_4 generation & validation of canonical g. + * It uses unverifiable g if this value is -1. + */ + int gindex; + int h; /* loop counter for unverifiable g */ + + unsigned int flags; + /* + * The digest to use for generation or validation. If this value is NULL, + * then the digest is chosen using the value of N. + */ + const char *mdname; + const char *mdprops; +} FFC_PARAMS; + +void ossl_ffc_params_init(FFC_PARAMS *params); +void ossl_ffc_params_cleanup(FFC_PARAMS *params); +void ossl_ffc_params_set0_pqg(FFC_PARAMS *params, BIGNUM *p, BIGNUM *q, + BIGNUM *g); +void ossl_ffc_params_get0_pqg(const FFC_PARAMS *params, const BIGNUM **p, + const BIGNUM **q, const BIGNUM **g); +void ossl_ffc_params_set0_j(FFC_PARAMS *d, BIGNUM *j); +int ossl_ffc_params_set_seed(FFC_PARAMS *params, + const unsigned char *seed, size_t seedlen); +void ossl_ffc_params_set_gindex(FFC_PARAMS *params, int index); +void ossl_ffc_params_set_pcounter(FFC_PARAMS *params, int index); +void ossl_ffc_params_set_h(FFC_PARAMS *params, int index); +void ossl_ffc_params_set_flags(FFC_PARAMS *params, unsigned int flags); +void ossl_ffc_params_enable_flags(FFC_PARAMS *params, unsigned int flags, + int enable); +int ossl_ffc_set_digest(FFC_PARAMS *params, const char *alg, const char *props); + +int ossl_ffc_params_set_validate_params(FFC_PARAMS *params, + const unsigned char *seed, + size_t seedlen, int counter); +void ossl_ffc_params_get_validate_params(const FFC_PARAMS *params, + unsigned char **seed, size_t *seedlen, + int *pcounter); + +int ossl_ffc_params_copy(FFC_PARAMS *dst, const FFC_PARAMS *src); +int ossl_ffc_params_cmp(const FFC_PARAMS *a, const FFC_PARAMS *b, int ignore_q); + +#ifndef FIPS_MODULE +int ossl_ffc_params_print(BIO *bp, const FFC_PARAMS *ffc, int indent); +#endif /* FIPS_MODULE */ + + +int ossl_ffc_params_FIPS186_4_generate(OSSL_LIB_CTX *libctx, FFC_PARAMS *params, + int type, size_t L, size_t N, + int *res, BN_GENCB *cb); +int ossl_ffc_params_FIPS186_2_generate(OSSL_LIB_CTX *libctx, FFC_PARAMS *params, + int type, size_t L, size_t N, + int *res, BN_GENCB *cb); + +int ossl_ffc_params_FIPS186_4_gen_verify(OSSL_LIB_CTX *libctx, + FFC_PARAMS *params, int mode, int type, + size_t L, size_t N, int *res, + BN_GENCB *cb); +int ossl_ffc_params_FIPS186_2_gen_verify(OSSL_LIB_CTX *libctx, + FFC_PARAMS *params, int mode, int type, + size_t L, size_t N, int *res, + BN_GENCB *cb); + +int ossl_ffc_params_simple_validate(OSSL_LIB_CTX *libctx, + const FFC_PARAMS *params, + int paramstype, int *res); +int ossl_ffc_params_full_validate(OSSL_LIB_CTX *libctx, + const FFC_PARAMS *params, + int paramstype, int *res); +int ossl_ffc_params_FIPS186_4_validate(OSSL_LIB_CTX *libctx, + const FFC_PARAMS *params, + int type, int *res, BN_GENCB *cb); +int ossl_ffc_params_FIPS186_2_validate(OSSL_LIB_CTX *libctx, + const FFC_PARAMS *params, + int type, int *res, BN_GENCB *cb); + +int ossl_ffc_generate_private_key(BN_CTX *ctx, const FFC_PARAMS *params, + int N, int s, BIGNUM *priv); + +int ossl_ffc_params_validate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont, + const BIGNUM *p, const BIGNUM *q, + const BIGNUM *g, BIGNUM *tmp, + int *ret); + +int ossl_ffc_validate_public_key(const FFC_PARAMS *params, + const BIGNUM *pub_key, int *ret); +int ossl_ffc_validate_public_key_partial(const FFC_PARAMS *params, + const BIGNUM *pub_key, int *ret); +int ossl_ffc_validate_private_key(const BIGNUM *upper, const BIGNUM *priv_key, + int *ret); + +int ossl_ffc_params_todata(const FFC_PARAMS *ffc, OSSL_PARAM_BLD *tmpl, + OSSL_PARAM params[]); +int ossl_ffc_params_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[]); + +typedef struct dh_named_group_st DH_NAMED_GROUP; +const DH_NAMED_GROUP *ossl_ffc_name_to_dh_named_group(const char *name); +const DH_NAMED_GROUP *ossl_ffc_uid_to_dh_named_group(int uid); +#ifndef OPENSSL_NO_DH +const DH_NAMED_GROUP *ossl_ffc_numbers_to_dh_named_group(const BIGNUM *p, + const BIGNUM *q, + const BIGNUM *g); +#endif +int ossl_ffc_named_group_get_uid(const DH_NAMED_GROUP *group); +const char *ossl_ffc_named_group_get_name(const DH_NAMED_GROUP *); +#ifndef OPENSSL_NO_DH +const BIGNUM *ossl_ffc_named_group_get_q(const DH_NAMED_GROUP *group); +int ossl_ffc_named_group_set_pqg(FFC_PARAMS *ffc, const DH_NAMED_GROUP *group); +#endif + +#endif /* OSSL_INTERNAL_FFC_H */ diff --git a/include/internal/ktls.h b/include/internal/ktls.h new file mode 100644 index 00000000..95492fd0 --- /dev/null +++ b/include/internal/ktls.h @@ -0,0 +1,404 @@ +/* + * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#if defined(OPENSSL_SYS_LINUX) +# ifndef OPENSSL_NO_KTLS +# include <linux/version.h> +# if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) +# define OPENSSL_NO_KTLS +# ifndef PEDANTIC +# warning "KTLS requires Kernel Headers >= 4.13.0" +# warning "Skipping Compilation of KTLS" +# endif +# endif +# endif +#endif + +#ifndef HEADER_INTERNAL_KTLS +# define HEADER_INTERNAL_KTLS +# pragma once + +# ifndef OPENSSL_NO_KTLS + +# if defined(__FreeBSD__) +# include <sys/types.h> +# include <sys/socket.h> +# include <sys/ktls.h> +# include <netinet/in.h> +# include <netinet/tcp.h> +# include <openssl/ssl3.h> + +# ifndef TCP_RXTLS_ENABLE +# define OPENSSL_NO_KTLS_RX +# endif +# define OPENSSL_KTLS_AES_GCM_128 +# define OPENSSL_KTLS_AES_GCM_256 +# define OPENSSL_KTLS_TLS13 + +typedef struct tls_enable ktls_crypto_info_t; + +/* + * FreeBSD does not require any additional steps to enable KTLS before + * setting keys. + */ +static ossl_inline int ktls_enable(int fd) +{ + return 1; +} + +/* + * The TCP_TXTLS_ENABLE socket option marks the outgoing socket buffer + * as using TLS. If successful, then data sent using this socket will + * be encrypted and encapsulated in TLS records using the tls_en + * provided here. + * + * The TCP_RXTLS_ENABLE socket option marks the incoming socket buffer + * as using TLS. If successful, then data received for this socket will + * be authenticated and decrypted using the tls_en provided here. + */ +static ossl_inline int ktls_start(int fd, ktls_crypto_info_t *tls_en, int is_tx) +{ + if (is_tx) + return setsockopt(fd, IPPROTO_TCP, TCP_TXTLS_ENABLE, + tls_en, sizeof(*tls_en)) ? 0 : 1; +# ifndef OPENSSL_NO_KTLS_RX + return setsockopt(fd, IPPROTO_TCP, TCP_RXTLS_ENABLE, tls_en, + sizeof(*tls_en)) ? 0 : 1; +# else + return 0; +# endif +} + +/* + * Send a TLS record using the tls_en provided in ktls_start and use + * record_type instead of the default SSL3_RT_APPLICATION_DATA. + * When the socket is non-blocking, then this call either returns EAGAIN or + * the entire record is pushed to TCP. It is impossible to send a partial + * record using this control message. + */ +static ossl_inline int ktls_send_ctrl_message(int fd, unsigned char record_type, + const void *data, size_t length) +{ + struct msghdr msg = { 0 }; + int cmsg_len = sizeof(record_type); + struct cmsghdr *cmsg; + char buf[CMSG_SPACE(cmsg_len)]; + struct iovec msg_iov; /* Vector of data to send/receive into */ + + msg.msg_control = buf; + msg.msg_controllen = sizeof(buf); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = IPPROTO_TCP; + cmsg->cmsg_type = TLS_SET_RECORD_TYPE; + cmsg->cmsg_len = CMSG_LEN(cmsg_len); + *((unsigned char *)CMSG_DATA(cmsg)) = record_type; + msg.msg_controllen = cmsg->cmsg_len; + + msg_iov.iov_base = (void *)data; + msg_iov.iov_len = length; + msg.msg_iov = &msg_iov; + msg.msg_iovlen = 1; + + return sendmsg(fd, &msg, 0); +} + +# ifdef OPENSSL_NO_KTLS_RX + +static ossl_inline int ktls_read_record(int fd, void *data, size_t length) +{ + return -1; +} + +# else /* !defined(OPENSSL_NO_KTLS_RX) */ + +/* + * Receive a TLS record using the tls_en provided in ktls_start. The + * kernel strips any explicit IV and authentication tag, but provides + * the TLS record header via a control message. If there is an error + * with the TLS record such as an invalid header, invalid padding, or + * authentication failure recvmsg() will fail with an error. + */ +static ossl_inline int ktls_read_record(int fd, void *data, size_t length) +{ + struct msghdr msg = { 0 }; + int cmsg_len = sizeof(struct tls_get_record); + struct tls_get_record *tgr; + struct cmsghdr *cmsg; + char buf[CMSG_SPACE(cmsg_len)]; + struct iovec msg_iov; /* Vector of data to send/receive into */ + int ret; + unsigned char *p = data; + const size_t prepend_length = SSL3_RT_HEADER_LENGTH; + + if (length <= prepend_length) { + errno = EINVAL; + return -1; + } + + msg.msg_control = buf; + msg.msg_controllen = sizeof(buf); + + msg_iov.iov_base = p + prepend_length; + msg_iov.iov_len = length - prepend_length; + msg.msg_iov = &msg_iov; + msg.msg_iovlen = 1; + + ret = recvmsg(fd, &msg, 0); + if (ret <= 0) + return ret; + + if ((msg.msg_flags & (MSG_EOR | MSG_CTRUNC)) != MSG_EOR) { + errno = EMSGSIZE; + return -1; + } + + if (msg.msg_controllen == 0) { + errno = EBADMSG; + return -1; + } + + cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg->cmsg_level != IPPROTO_TCP || cmsg->cmsg_type != TLS_GET_RECORD + || cmsg->cmsg_len != CMSG_LEN(cmsg_len)) { + errno = EBADMSG; + return -1; + } + + tgr = (struct tls_get_record *)CMSG_DATA(cmsg); + p[0] = tgr->tls_type; + p[1] = tgr->tls_vmajor; + p[2] = tgr->tls_vminor; + *(uint16_t *)(p + 3) = htons(ret); + + return ret + prepend_length; +} + +# endif /* OPENSSL_NO_KTLS_RX */ + +/* + * KTLS enables the sendfile system call to send data from a file over + * TLS. + */ +static ossl_inline ossl_ssize_t ktls_sendfile(int s, int fd, off_t off, + size_t size, int flags) +{ + off_t sbytes = 0; + int ret; + + ret = sendfile(fd, s, off, size, NULL, &sbytes, flags); + if (ret == -1 && sbytes == 0) + return -1; + return sbytes; +} + +# endif /* __FreeBSD__ */ + +# if defined(OPENSSL_SYS_LINUX) + +# include <linux/tls.h> +# if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0) +# define OPENSSL_NO_KTLS_RX +# ifndef PEDANTIC +# warning "KTLS requires Kernel Headers >= 4.17.0 for receiving" +# warning "Skipping Compilation of KTLS receive data path" +# endif +# endif +# define OPENSSL_KTLS_AES_GCM_128 +# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) +# define OPENSSL_KTLS_AES_GCM_256 +# define OPENSSL_KTLS_TLS13 +# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) +# define OPENSSL_KTLS_AES_CCM_128 +# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) +# ifndef OPENSSL_NO_CHACHA +# define OPENSSL_KTLS_CHACHA20_POLY1305 +# endif +# endif +# endif +# endif + +# include <sys/sendfile.h> +# include <netinet/tcp.h> +# include <linux/socket.h> +# include <openssl/ssl3.h> +# include <openssl/tls1.h> +# include <openssl/evp.h> + +# ifndef SOL_TLS +# define SOL_TLS 282 +# endif + +# ifndef TCP_ULP +# define TCP_ULP 31 +# endif + +# ifndef TLS_RX +# define TLS_RX 2 +# endif + +struct tls_crypto_info_all { + union { +# ifdef OPENSSL_KTLS_AES_GCM_128 + struct tls12_crypto_info_aes_gcm_128 gcm128; +# endif +# ifdef OPENSSL_KTLS_AES_GCM_256 + struct tls12_crypto_info_aes_gcm_256 gcm256; +# endif +# ifdef OPENSSL_KTLS_AES_CCM_128 + struct tls12_crypto_info_aes_ccm_128 ccm128; +# endif +# ifdef OPENSSL_KTLS_CHACHA20_POLY1305 + struct tls12_crypto_info_chacha20_poly1305 chacha20poly1305; +# endif + }; + size_t tls_crypto_info_len; +}; + +typedef struct tls_crypto_info_all ktls_crypto_info_t; + +/* + * When successful, this socket option doesn't change the behaviour of the + * TCP socket, except changing the TCP setsockopt handler to enable the + * processing of SOL_TLS socket options. All other functionality remains the + * same. + */ +static ossl_inline int ktls_enable(int fd) +{ + return setsockopt(fd, SOL_TCP, TCP_ULP, "tls", sizeof("tls")) ? 0 : 1; +} + +/* + * The TLS_TX socket option changes the send/sendmsg handlers of the TCP socket. + * If successful, then data sent using this socket will be encrypted and + * encapsulated in TLS records using the crypto_info provided here. + * The TLS_RX socket option changes the recv/recvmsg handlers of the TCP socket. + * If successful, then data received using this socket will be decrypted, + * authenticated and decapsulated using the crypto_info provided here. + */ +static ossl_inline int ktls_start(int fd, ktls_crypto_info_t *crypto_info, + int is_tx) +{ + return setsockopt(fd, SOL_TLS, is_tx ? TLS_TX : TLS_RX, + crypto_info, crypto_info->tls_crypto_info_len) ? 0 : 1; +} + +/* + * Send a TLS record using the crypto_info provided in ktls_start and use + * record_type instead of the default SSL3_RT_APPLICATION_DATA. + * When the socket is non-blocking, then this call either returns EAGAIN or + * the entire record is pushed to TCP. It is impossible to send a partial + * record using this control message. + */ +static ossl_inline int ktls_send_ctrl_message(int fd, unsigned char record_type, + const void *data, size_t length) +{ + struct msghdr msg; + int cmsg_len = sizeof(record_type); + struct cmsghdr *cmsg; + union { + struct cmsghdr hdr; + char buf[CMSG_SPACE(sizeof(unsigned char))]; + } cmsgbuf; + struct iovec msg_iov; /* Vector of data to send/receive into */ + + memset(&msg, 0, sizeof(msg)); + msg.msg_control = cmsgbuf.buf; + msg.msg_controllen = sizeof(cmsgbuf.buf); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_TLS; + cmsg->cmsg_type = TLS_SET_RECORD_TYPE; + cmsg->cmsg_len = CMSG_LEN(cmsg_len); + *((unsigned char *)CMSG_DATA(cmsg)) = record_type; + msg.msg_controllen = cmsg->cmsg_len; + + msg_iov.iov_base = (void *)data; + msg_iov.iov_len = length; + msg.msg_iov = &msg_iov; + msg.msg_iovlen = 1; + + return sendmsg(fd, &msg, 0); +} + +/* + * KTLS enables the sendfile system call to send data from a file over TLS. + * @flags are ignored on Linux. (placeholder for FreeBSD sendfile) + * */ +static ossl_inline ossl_ssize_t ktls_sendfile(int s, int fd, off_t off, size_t size, int flags) +{ + return sendfile(s, fd, &off, size); +} + +# ifdef OPENSSL_NO_KTLS_RX + + +static ossl_inline int ktls_read_record(int fd, void *data, size_t length) +{ + return -1; +} + +# else /* !defined(OPENSSL_NO_KTLS_RX) */ + +/* + * Receive a TLS record using the crypto_info provided in ktls_start. + * The kernel strips the TLS record header, IV and authentication tag, + * returning only the plaintext data or an error on failure. + * We add the TLS record header here to satisfy routines in rec_layer_s3.c + */ +static ossl_inline int ktls_read_record(int fd, void *data, size_t length) +{ + struct msghdr msg; + struct cmsghdr *cmsg; + union { + struct cmsghdr hdr; + char buf[CMSG_SPACE(sizeof(unsigned char))]; + } cmsgbuf; + struct iovec msg_iov; + int ret; + unsigned char *p = data; + const size_t prepend_length = SSL3_RT_HEADER_LENGTH; + + if (length < prepend_length + EVP_GCM_TLS_TAG_LEN) { + errno = EINVAL; + return -1; + } + + memset(&msg, 0, sizeof(msg)); + msg.msg_control = cmsgbuf.buf; + msg.msg_controllen = sizeof(cmsgbuf.buf); + + msg_iov.iov_base = p + prepend_length; + msg_iov.iov_len = length - prepend_length - EVP_GCM_TLS_TAG_LEN; + msg.msg_iov = &msg_iov; + msg.msg_iovlen = 1; + + ret = recvmsg(fd, &msg, 0); + if (ret < 0) + return ret; + + if (msg.msg_controllen > 0) { + cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg->cmsg_type == TLS_GET_RECORD_TYPE) { + p[0] = *((unsigned char *)CMSG_DATA(cmsg)); + p[1] = TLS1_2_VERSION_MAJOR; + p[2] = TLS1_2_VERSION_MINOR; + /* returned length is limited to msg_iov.iov_len above */ + p[3] = (ret >> 8) & 0xff; + p[4] = ret & 0xff; + ret += prepend_length; + } + } + + return ret; +} + +# endif /* OPENSSL_NO_KTLS_RX */ + +# endif /* OPENSSL_SYS_LINUX */ +# endif /* OPENSSL_NO_KTLS */ +#endif /* HEADER_INTERNAL_KTLS */ diff --git a/include/internal/namemap.h b/include/internal/namemap.h new file mode 100644 index 00000000..a4c60ae6 --- /dev/null +++ b/include/internal/namemap.h @@ -0,0 +1,43 @@ +/* + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" + +typedef struct ossl_namemap_st OSSL_NAMEMAP; + +OSSL_NAMEMAP *ossl_namemap_stored(OSSL_LIB_CTX *libctx); + +OSSL_NAMEMAP *ossl_namemap_new(void); +void ossl_namemap_free(OSSL_NAMEMAP *namemap); +int ossl_namemap_empty(OSSL_NAMEMAP *namemap); + +int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name); +int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number, + const char *name, size_t name_len); + +/* + * The number<->name relationship is 1<->many + * Therefore, the name->number mapping is a simple function, while the + * number->name mapping is an iterator. + */ +int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name); +int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap, + const char *name, size_t name_len); +const char *ossl_namemap_num2name(const OSSL_NAMEMAP *namemap, int number, + size_t idx); +int ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number, + void (*fn)(const char *name, void *data), + void *data); + +/* + * A utility that handles several names in a string, divided by a given + * separator. + */ +int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number, + const char *names, const char separator); diff --git a/include/internal/nelem.h b/include/internal/nelem.h new file mode 100644 index 00000000..b758513b --- /dev/null +++ b/include/internal/nelem.h @@ -0,0 +1,15 @@ +/* + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_NELEM_H +# define OSSL_INTERNAL_NELEM_H +# pragma once + +# define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0])) +#endif diff --git a/include/internal/numbers.h b/include/internal/numbers.h new file mode 100644 index 00000000..4f4d3306 --- /dev/null +++ b/include/internal/numbers.h @@ -0,0 +1,85 @@ +/* + * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_NUMBERS_H +# define OSSL_INTERNAL_NUMBERS_H +# pragma once + +# include <limits.h> + +# if (-1 & 3) == 0x03 /* Two's complement */ + +# define __MAXUINT__(T) ((T) -1) +# define __MAXINT__(T) ((T) ((((T) 1) << ((sizeof(T) * CHAR_BIT) - 1)) ^ __MAXUINT__(T))) +# define __MININT__(T) (-__MAXINT__(T) - 1) + +# elif (-1 & 3) == 0x02 /* One's complement */ + +# define __MAXUINT__(T) (((T) -1) + 1) +# define __MAXINT__(T) ((T) ((((T) 1) << ((sizeof(T) * CHAR_BIT) - 1)) ^ __MAXUINT__(T))) +# define __MININT__(T) (-__MAXINT__(T)) + +# elif (-1 & 3) == 0x01 /* Sign/magnitude */ + +# define __MAXINT__(T) ((T) (((((T) 1) << ((sizeof(T) * CHAR_BIT) - 2)) - 1) | (((T) 1) << ((sizeof(T) * CHAR_BIT) - 2)))) +# define __MAXUINT__(T) ((T) (__MAXINT__(T) | (((T) 1) << ((sizeof(T) * CHAR_BIT) - 1)))) +# define __MININT__(T) (-__MAXINT__(T)) + +# else + +# error "do not know the integer encoding on this architecture" + +# endif + +# ifndef INT8_MAX +# define INT8_MIN __MININT__(int8_t) +# define INT8_MAX __MAXINT__(int8_t) +# define UINT8_MAX __MAXUINT__(uint8_t) +# endif + +# ifndef INT16_MAX +# define INT16_MIN __MININT__(int16_t) +# define INT16_MAX __MAXINT__(int16_t) +# define UINT16_MAX __MAXUINT__(uint16_t) +# endif + +# ifndef INT32_MAX +# define INT32_MIN __MININT__(int32_t) +# define INT32_MAX __MAXINT__(int32_t) +# define UINT32_MAX __MAXUINT__(uint32_t) +# endif + +# ifndef INT64_MAX +# define INT64_MIN __MININT__(int64_t) +# define INT64_MAX __MAXINT__(int64_t) +# define UINT64_MAX __MAXUINT__(uint64_t) +# endif + +# ifndef INT128_MAX +# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16 +typedef __int128_t int128_t; +typedef __uint128_t uint128_t; +# define INT128_MIN __MININT__(int128_t) +# define INT128_MAX __MAXINT__(int128_t) +# define UINT128_MAX __MAXUINT__(uint128_t) +# endif +# endif + +# ifndef SIZE_MAX +# define SIZE_MAX __MAXUINT__(size_t) +# endif + +# ifndef OSSL_INTMAX_MAX +# define OSSL_INTMAX_MIN __MININT__(ossl_intmax_t) +# define OSSL_INTMAX_MAX __MAXINT__(ossl_intmax_t) +# define OSSL_UINTMAX_MAX __MAXUINT__(ossl_uintmax_t) +# endif + +#endif + diff --git a/include/internal/o_dir.h b/include/internal/o_dir.h new file mode 100644 index 00000000..add34d14 --- /dev/null +++ b/include/internal/o_dir.h @@ -0,0 +1,53 @@ +/* + * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is dual-licensed and is also available under the following + * terms: + * + * Copyright (c) 2004, Richard Levitte <richard@levitte.org> + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS 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. + */ + +#ifndef OSSL_INTERNAL_O_DIR_H +# define OSSL_INTERNAL_O_DIR_H +# pragma once + +typedef struct OPENSSL_dir_context_st OPENSSL_DIR_CTX; + +/* + * returns NULL on error or end-of-directory. If it is end-of-directory, + * errno will be zero + */ +const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx, const char *directory); +/* returns 1 on success, 0 on error */ +int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx); + +#endif /* LPDIR_H */ diff --git a/include/internal/packet.h b/include/internal/packet.h new file mode 100644 index 00000000..170997db --- /dev/null +++ b/include/internal/packet.h @@ -0,0 +1,902 @@ +/* + * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_PACKET_H +# define OSSL_INTERNAL_PACKET_H +# pragma once + +# include <string.h> +# include <openssl/bn.h> +# include <openssl/buffer.h> +# include <openssl/crypto.h> +# include <openssl/e_os2.h> + +# include "internal/numbers.h" + +typedef struct { + /* Pointer to where we are currently reading from */ + const unsigned char *curr; + /* Number of bytes remaining */ + size_t remaining; +} PACKET; + +/* Internal unchecked shorthand; don't use outside this file. */ +static ossl_inline void packet_forward(PACKET *pkt, size_t len) +{ + pkt->curr += len; + pkt->remaining -= len; +} + +/* + * Returns the number of bytes remaining to be read in the PACKET + */ +static ossl_inline size_t PACKET_remaining(const PACKET *pkt) +{ + return pkt->remaining; +} + +/* + * Returns a pointer to the first byte after the packet data. + * Useful for integrating with non-PACKET parsing code. + * Specifically, we use PACKET_end() to verify that a d2i_... call + * has consumed the entire packet contents. + */ +static ossl_inline const unsigned char *PACKET_end(const PACKET *pkt) +{ + return pkt->curr + pkt->remaining; +} + +/* + * Returns a pointer to the PACKET's current position. + * For use in non-PACKETized APIs. + */ +static ossl_inline const unsigned char *PACKET_data(const PACKET *pkt) +{ + return pkt->curr; +} + +/* + * Initialise a PACKET with |len| bytes held in |buf|. This does not make a + * copy of the data so |buf| must be present for the whole time that the PACKET + * is being used. + */ +__owur static ossl_inline int PACKET_buf_init(PACKET *pkt, + const unsigned char *buf, + size_t len) +{ + /* Sanity check for negative values. */ + if (len > (size_t)(SIZE_MAX / 2)) + return 0; + + pkt->curr = buf; + pkt->remaining = len; + return 1; +} + +/* Initialize a PACKET to hold zero bytes. */ +static ossl_inline void PACKET_null_init(PACKET *pkt) +{ + pkt->curr = NULL; + pkt->remaining = 0; +} + +/* + * Returns 1 if the packet has length |num| and its contents equal the |num| + * bytes read from |ptr|. Returns 0 otherwise (lengths or contents not equal). + * If lengths are equal, performs the comparison in constant time. + */ +__owur static ossl_inline int PACKET_equal(const PACKET *pkt, const void *ptr, + size_t num) +{ + if (PACKET_remaining(pkt) != num) + return 0; + return CRYPTO_memcmp(pkt->curr, ptr, num) == 0; +} + +/* + * Peek ahead and initialize |subpkt| with the next |len| bytes read from |pkt|. + * Data is not copied: the |subpkt| packet will share its underlying buffer with + * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + */ +__owur static ossl_inline int PACKET_peek_sub_packet(const PACKET *pkt, + PACKET *subpkt, size_t len) +{ + if (PACKET_remaining(pkt) < len) + return 0; + + return PACKET_buf_init(subpkt, pkt->curr, len); +} + +/* + * Initialize |subpkt| with the next |len| bytes read from |pkt|. Data is not + * copied: the |subpkt| packet will share its underlying buffer with the + * original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + */ +__owur static ossl_inline int PACKET_get_sub_packet(PACKET *pkt, + PACKET *subpkt, size_t len) +{ + if (!PACKET_peek_sub_packet(pkt, subpkt, len)) + return 0; + + packet_forward(pkt, len); + + return 1; +} + +/* + * Peek ahead at 2 bytes in network order from |pkt| and store the value in + * |*data| + */ +__owur static ossl_inline int PACKET_peek_net_2(const PACKET *pkt, + unsigned int *data) +{ + if (PACKET_remaining(pkt) < 2) + return 0; + + *data = ((unsigned int)(*pkt->curr)) << 8; + *data |= *(pkt->curr + 1); + + return 1; +} + +/* Equivalent of n2s */ +/* Get 2 bytes in network order from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_get_net_2(PACKET *pkt, unsigned int *data) +{ + if (!PACKET_peek_net_2(pkt, data)) + return 0; + + packet_forward(pkt, 2); + + return 1; +} + +/* Same as PACKET_get_net_2() but for a size_t */ +__owur static ossl_inline int PACKET_get_net_2_len(PACKET *pkt, size_t *data) +{ + unsigned int i; + int ret = PACKET_get_net_2(pkt, &i); + + if (ret) + *data = (size_t)i; + + return ret; +} + +/* + * Peek ahead at 3 bytes in network order from |pkt| and store the value in + * |*data| + */ +__owur static ossl_inline int PACKET_peek_net_3(const PACKET *pkt, + unsigned long *data) +{ + if (PACKET_remaining(pkt) < 3) + return 0; + + *data = ((unsigned long)(*pkt->curr)) << 16; + *data |= ((unsigned long)(*(pkt->curr + 1))) << 8; + *data |= *(pkt->curr + 2); + + return 1; +} + +/* Equivalent of n2l3 */ +/* Get 3 bytes in network order from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_get_net_3(PACKET *pkt, unsigned long *data) +{ + if (!PACKET_peek_net_3(pkt, data)) + return 0; + + packet_forward(pkt, 3); + + return 1; +} + +/* Same as PACKET_get_net_3() but for a size_t */ +__owur static ossl_inline int PACKET_get_net_3_len(PACKET *pkt, size_t *data) +{ + unsigned long i; + int ret = PACKET_get_net_3(pkt, &i); + + if (ret) + *data = (size_t)i; + + return ret; +} + +/* + * Peek ahead at 4 bytes in network order from |pkt| and store the value in + * |*data| + */ +__owur static ossl_inline int PACKET_peek_net_4(const PACKET *pkt, + unsigned long *data) +{ + if (PACKET_remaining(pkt) < 4) + return 0; + + *data = ((unsigned long)(*pkt->curr)) << 24; + *data |= ((unsigned long)(*(pkt->curr + 1))) << 16; + *data |= ((unsigned long)(*(pkt->curr + 2))) << 8; + *data |= *(pkt->curr + 3); + + return 1; +} + +/* Equivalent of n2l */ +/* Get 4 bytes in network order from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_get_net_4(PACKET *pkt, unsigned long *data) +{ + if (!PACKET_peek_net_4(pkt, data)) + return 0; + + packet_forward(pkt, 4); + + return 1; +} + +/* Same as PACKET_get_net_4() but for a size_t */ +__owur static ossl_inline int PACKET_get_net_4_len(PACKET *pkt, size_t *data) +{ + unsigned long i; + int ret = PACKET_get_net_4(pkt, &i); + + if (ret) + *data = (size_t)i; + + return ret; +} + +/* Peek ahead at 1 byte from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_peek_1(const PACKET *pkt, + unsigned int *data) +{ + if (!PACKET_remaining(pkt)) + return 0; + + *data = *pkt->curr; + + return 1; +} + +/* Get 1 byte from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_get_1(PACKET *pkt, unsigned int *data) +{ + if (!PACKET_peek_1(pkt, data)) + return 0; + + packet_forward(pkt, 1); + + return 1; +} + +/* Same as PACKET_get_1() but for a size_t */ +__owur static ossl_inline int PACKET_get_1_len(PACKET *pkt, size_t *data) +{ + unsigned int i; + int ret = PACKET_get_1(pkt, &i); + + if (ret) + *data = (size_t)i; + + return ret; +} + +/* + * Peek ahead at 4 bytes in reverse network order from |pkt| and store the value + * in |*data| + */ +__owur static ossl_inline int PACKET_peek_4(const PACKET *pkt, + unsigned long *data) +{ + if (PACKET_remaining(pkt) < 4) + return 0; + + *data = *pkt->curr; + *data |= ((unsigned long)(*(pkt->curr + 1))) << 8; + *data |= ((unsigned long)(*(pkt->curr + 2))) << 16; + *data |= ((unsigned long)(*(pkt->curr + 3))) << 24; + + return 1; +} + +/* Equivalent of c2l */ +/* + * Get 4 bytes in reverse network order from |pkt| and store the value in + * |*data| + */ +__owur static ossl_inline int PACKET_get_4(PACKET *pkt, unsigned long *data) +{ + if (!PACKET_peek_4(pkt, data)) + return 0; + + packet_forward(pkt, 4); + + return 1; +} + +/* + * Peek ahead at |len| bytes from the |pkt| and store a pointer to them in + * |*data|. This just points at the underlying buffer that |pkt| is using. The + * caller should not free this data directly (it will be freed when the + * underlying buffer gets freed + */ +__owur static ossl_inline int PACKET_peek_bytes(const PACKET *pkt, + const unsigned char **data, + size_t len) +{ + if (PACKET_remaining(pkt) < len) + return 0; + + *data = pkt->curr; + + return 1; +} + +/* + * Read |len| bytes from the |pkt| and store a pointer to them in |*data|. This + * just points at the underlying buffer that |pkt| is using. The caller should + * not free this data directly (it will be freed when the underlying buffer gets + * freed + */ +__owur static ossl_inline int PACKET_get_bytes(PACKET *pkt, + const unsigned char **data, + size_t len) +{ + if (!PACKET_peek_bytes(pkt, data, len)) + return 0; + + packet_forward(pkt, len); + + return 1; +} + +/* Peek ahead at |len| bytes from |pkt| and copy them to |data| */ +__owur static ossl_inline int PACKET_peek_copy_bytes(const PACKET *pkt, + unsigned char *data, + size_t len) +{ + if (PACKET_remaining(pkt) < len) + return 0; + + memcpy(data, pkt->curr, len); + + return 1; +} + +/* + * Read |len| bytes from |pkt| and copy them to |data|. + * The caller is responsible for ensuring that |data| can hold |len| bytes. + */ +__owur static ossl_inline int PACKET_copy_bytes(PACKET *pkt, + unsigned char *data, size_t len) +{ + if (!PACKET_peek_copy_bytes(pkt, data, len)) + return 0; + + packet_forward(pkt, len); + + return 1; +} + +/* + * Copy packet data to |dest|, and set |len| to the number of copied bytes. + * If the packet has more than |dest_len| bytes, nothing is copied. + * Returns 1 if the packet data fits in |dest_len| bytes, 0 otherwise. + * Does not forward PACKET position (because it is typically the last thing + * done with a given PACKET). + */ +__owur static ossl_inline int PACKET_copy_all(const PACKET *pkt, + unsigned char *dest, + size_t dest_len, size_t *len) +{ + if (PACKET_remaining(pkt) > dest_len) { + *len = 0; + return 0; + } + *len = pkt->remaining; + memcpy(dest, pkt->curr, pkt->remaining); + return 1; +} + +/* + * Copy |pkt| bytes to a newly allocated buffer and store a pointer to the + * result in |*data|, and the length in |len|. + * If |*data| is not NULL, the old data is OPENSSL_free'd. + * If the packet is empty, or malloc fails, |*data| will be set to NULL. + * Returns 1 if the malloc succeeds and 0 otherwise. + * Does not forward PACKET position (because it is typically the last thing + * done with a given PACKET). + */ +__owur static ossl_inline int PACKET_memdup(const PACKET *pkt, + unsigned char **data, size_t *len) +{ + size_t length; + + OPENSSL_free(*data); + *data = NULL; + *len = 0; + + length = PACKET_remaining(pkt); + + if (length == 0) + return 1; + + *data = OPENSSL_memdup(pkt->curr, length); + if (*data == NULL) + return 0; + + *len = length; + return 1; +} + +/* + * Read a C string from |pkt| and copy to a newly allocated, NUL-terminated + * buffer. Store a pointer to the result in |*data|. + * If |*data| is not NULL, the old data is OPENSSL_free'd. + * If the data in |pkt| does not contain a NUL-byte, the entire data is + * copied and NUL-terminated. + * Returns 1 if the malloc succeeds and 0 otherwise. + * Does not forward PACKET position (because it is typically the last thing done + * with a given PACKET). + */ +__owur static ossl_inline int PACKET_strndup(const PACKET *pkt, char **data) +{ + OPENSSL_free(*data); + + /* This will succeed on an empty packet, unless pkt->curr == NULL. */ + *data = OPENSSL_strndup((const char *)pkt->curr, PACKET_remaining(pkt)); + return (*data != NULL); +} + +/* Returns 1 if |pkt| contains at least one 0-byte, 0 otherwise. */ +static ossl_inline int PACKET_contains_zero_byte(const PACKET *pkt) +{ + return memchr(pkt->curr, 0, pkt->remaining) != NULL; +} + +/* Move the current reading position forward |len| bytes */ +__owur static ossl_inline int PACKET_forward(PACKET *pkt, size_t len) +{ + if (PACKET_remaining(pkt) < len) + return 0; + + packet_forward(pkt, len); + + return 1; +} + +/* + * Reads a variable-length vector prefixed with a one-byte length, and stores + * the contents in |subpkt|. |pkt| can equal |subpkt|. + * Data is not copied: the |subpkt| packet will share its underlying buffer with + * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + * Upon failure, the original |pkt| and |subpkt| are not modified. + */ +__owur static ossl_inline int PACKET_get_length_prefixed_1(PACKET *pkt, + PACKET *subpkt) +{ + unsigned int length; + const unsigned char *data; + PACKET tmp = *pkt; + if (!PACKET_get_1(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length)) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* + * Like PACKET_get_length_prefixed_1, but additionally, fails when there are + * leftover bytes in |pkt|. + */ +__owur static ossl_inline int PACKET_as_length_prefixed_1(PACKET *pkt, + PACKET *subpkt) +{ + unsigned int length; + const unsigned char *data; + PACKET tmp = *pkt; + if (!PACKET_get_1(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length) || + PACKET_remaining(&tmp) != 0) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* + * Reads a variable-length vector prefixed with a two-byte length, and stores + * the contents in |subpkt|. |pkt| can equal |subpkt|. + * Data is not copied: the |subpkt| packet will share its underlying buffer with + * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + * Upon failure, the original |pkt| and |subpkt| are not modified. + */ +__owur static ossl_inline int PACKET_get_length_prefixed_2(PACKET *pkt, + PACKET *subpkt) +{ + unsigned int length; + const unsigned char *data; + PACKET tmp = *pkt; + + if (!PACKET_get_net_2(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length)) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* + * Like PACKET_get_length_prefixed_2, but additionally, fails when there are + * leftover bytes in |pkt|. + */ +__owur static ossl_inline int PACKET_as_length_prefixed_2(PACKET *pkt, + PACKET *subpkt) +{ + unsigned int length; + const unsigned char *data; + PACKET tmp = *pkt; + + if (!PACKET_get_net_2(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length) || + PACKET_remaining(&tmp) != 0) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* + * Reads a variable-length vector prefixed with a three-byte length, and stores + * the contents in |subpkt|. |pkt| can equal |subpkt|. + * Data is not copied: the |subpkt| packet will share its underlying buffer with + * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + * Upon failure, the original |pkt| and |subpkt| are not modified. + */ +__owur static ossl_inline int PACKET_get_length_prefixed_3(PACKET *pkt, + PACKET *subpkt) +{ + unsigned long length; + const unsigned char *data; + PACKET tmp = *pkt; + if (!PACKET_get_net_3(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length)) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* Writeable packets */ + +typedef struct wpacket_sub WPACKET_SUB; +struct wpacket_sub { + /* The parent WPACKET_SUB if we have one or NULL otherwise */ + WPACKET_SUB *parent; + + /* + * Offset into the buffer where the length of this WPACKET goes. We use an + * offset in case the buffer grows and gets reallocated. + */ + size_t packet_len; + + /* Number of bytes in the packet_len or 0 if we don't write the length */ + size_t lenbytes; + + /* Number of bytes written to the buf prior to this packet starting */ + size_t pwritten; + + /* Flags for this sub-packet */ + unsigned int flags; +}; + +typedef struct wpacket_st WPACKET; +struct wpacket_st { + /* The buffer where we store the output data */ + BUF_MEM *buf; + + /* Fixed sized buffer which can be used as an alternative to buf */ + unsigned char *staticbuf; + + /* + * Offset into the buffer where we are currently writing. We use an offset + * in case the buffer grows and gets reallocated. + */ + size_t curr; + + /* Number of bytes written so far */ + size_t written; + + /* Maximum number of bytes we will allow to be written to this WPACKET */ + size_t maxsize; + + /* Our sub-packets (always at least one if not finished) */ + WPACKET_SUB *subs; + + /* Writing from the end first? */ + unsigned int endfirst : 1; +}; + +/* Flags */ + +/* Default */ +#define WPACKET_FLAGS_NONE 0 + +/* Error on WPACKET_close() if no data written to the WPACKET */ +#define WPACKET_FLAGS_NON_ZERO_LENGTH 1 + +/* + * Abandon all changes on WPACKET_close() if no data written to the WPACKET, + * i.e. this does not write out a zero packet length + */ +#define WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH 2 + + +/* + * Initialise a WPACKET with the buffer in |buf|. The buffer must exist + * for the whole time that the WPACKET is being used. Additionally |lenbytes| of + * data is preallocated at the start of the buffer to store the length of the + * WPACKET once we know it. + */ +int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes); + +/* + * Same as WPACKET_init_len except there is no preallocation of the WPACKET + * length. + */ +int WPACKET_init(WPACKET *pkt, BUF_MEM *buf); + +/* + * Same as WPACKET_init_len except there is no underlying buffer. No data is + * ever actually written. We just keep track of how much data would have been + * written if a buffer was there. + */ +int WPACKET_init_null(WPACKET *pkt, size_t lenbytes); + +/* + * Same as WPACKET_init_null except we set the WPACKET to assume DER length + * encoding for sub-packets. + */ +int WPACKET_init_null_der(WPACKET *pkt); + +/* + * Same as WPACKET_init_len except we do not use a growable BUF_MEM structure. + * A fixed buffer of memory |buf| of size |len| is used instead. A failure will + * occur if you attempt to write beyond the end of the buffer + */ +int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len, + size_t lenbytes); + +/* + * Same as WPACKET_init_static_len except lenbytes is always 0, and we set the + * WPACKET to write to the end of the buffer moving towards the start and use + * DER length encoding for sub-packets. + */ +int WPACKET_init_der(WPACKET *pkt, unsigned char *buf, size_t len); + +/* + * Set the flags to be applied to the current sub-packet + */ +int WPACKET_set_flags(WPACKET *pkt, unsigned int flags); + +/* + * Closes the most recent sub-packet. It also writes out the length of the + * packet to the required location (normally the start of the WPACKET) if + * appropriate. The top level WPACKET should be closed using WPACKET_finish() + * instead of this function. + */ +int WPACKET_close(WPACKET *pkt); + +/* + * The same as WPACKET_close() but only for the top most WPACKET. Additionally + * frees memory resources for this WPACKET. + */ +int WPACKET_finish(WPACKET *pkt); + +/* + * Iterate through all the sub-packets and write out their lengths as if they + * were being closed. The lengths will be overwritten with the final lengths + * when the sub-packets are eventually closed (which may be different if more + * data is added to the WPACKET). This function fails if a sub-packet is of 0 + * length and WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH is set. + */ +int WPACKET_fill_lengths(WPACKET *pkt); + +/* + * Initialise a new sub-packet. Additionally |lenbytes| of data is preallocated + * at the start of the sub-packet to store its length once we know it. Don't + * call this directly. Use the convenience macros below instead. + */ +int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes); + +/* + * Convenience macros for calling WPACKET_start_sub_packet_len with different + * lengths + */ +#define WPACKET_start_sub_packet_u8(pkt) \ + WPACKET_start_sub_packet_len__((pkt), 1) +#define WPACKET_start_sub_packet_u16(pkt) \ + WPACKET_start_sub_packet_len__((pkt), 2) +#define WPACKET_start_sub_packet_u24(pkt) \ + WPACKET_start_sub_packet_len__((pkt), 3) +#define WPACKET_start_sub_packet_u32(pkt) \ + WPACKET_start_sub_packet_len__((pkt), 4) + +/* + * Same as WPACKET_start_sub_packet_len__() except no bytes are pre-allocated + * for the sub-packet length. + */ +int WPACKET_start_sub_packet(WPACKET *pkt); + +/* + * Allocate bytes in the WPACKET for the output. This reserves the bytes + * and counts them as "written", but doesn't actually do the writing. A pointer + * to the allocated bytes is stored in |*allocbytes|. |allocbytes| may be NULL. + * WARNING: the allocated bytes must be filled in immediately, without further + * WPACKET_* calls. If not then the underlying buffer may be realloc'd and + * change its location. + */ +int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, + unsigned char **allocbytes); + +/* + * The same as WPACKET_allocate_bytes() except additionally a new sub-packet is + * started for the allocated bytes, and then closed immediately afterwards. The + * number of length bytes for the sub-packet is in |lenbytes|. Don't call this + * directly. Use the convenience macros below instead. + */ +int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len, + unsigned char **allocbytes, size_t lenbytes); + +/* + * Convenience macros for calling WPACKET_sub_allocate_bytes with different + * lengths + */ +#define WPACKET_sub_allocate_bytes_u8(pkt, len, bytes) \ + WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 1) +#define WPACKET_sub_allocate_bytes_u16(pkt, len, bytes) \ + WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 2) +#define WPACKET_sub_allocate_bytes_u24(pkt, len, bytes) \ + WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 3) +#define WPACKET_sub_allocate_bytes_u32(pkt, len, bytes) \ + WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 4) + +/* + * The same as WPACKET_allocate_bytes() except the reserved bytes are not + * actually counted as written. Typically this will be for when we don't know + * how big arbitrary data is going to be up front, but we do know what the + * maximum size will be. If this function is used, then it should be immediately + * followed by a WPACKET_allocate_bytes() call before any other WPACKET + * functions are called (unless the write to the allocated bytes is abandoned). + * + * For example: If we are generating a signature, then the size of that + * signature may not be known in advance. We can use WPACKET_reserve_bytes() to + * handle this: + * + * if (!WPACKET_sub_reserve_bytes_u16(&pkt, EVP_PKEY_get_size(pkey), &sigbytes1) + * || EVP_SignFinal(md_ctx, sigbytes1, &siglen, pkey) <= 0 + * || !WPACKET_sub_allocate_bytes_u16(&pkt, siglen, &sigbytes2) + * || sigbytes1 != sigbytes2) + * goto err; + */ +int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes); + +/* + * The "reserve_bytes" equivalent of WPACKET_sub_allocate_bytes__() + */ +int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len, + unsigned char **allocbytes, size_t lenbytes); + +/* + * Convenience macros for WPACKET_sub_reserve_bytes with different lengths + */ +#define WPACKET_sub_reserve_bytes_u8(pkt, len, bytes) \ + WPACKET_reserve_bytes__((pkt), (len), (bytes), 1) +#define WPACKET_sub_reserve_bytes_u16(pkt, len, bytes) \ + WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 2) +#define WPACKET_sub_reserve_bytes_u24(pkt, len, bytes) \ + WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 3) +#define WPACKET_sub_reserve_bytes_u32(pkt, len, bytes) \ + WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 4) + +/* + * Write the value stored in |val| into the WPACKET. The value will consume + * |bytes| amount of storage. An error will occur if |val| cannot be + * accommodated in |bytes| storage, e.g. attempting to write the value 256 into + * 1 byte will fail. Don't call this directly. Use the convenience macros below + * instead. + */ +int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t bytes); + +/* + * Convenience macros for calling WPACKET_put_bytes with different + * lengths + */ +#define WPACKET_put_bytes_u8(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 1) +#define WPACKET_put_bytes_u16(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 2) +#define WPACKET_put_bytes_u24(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 3) +#define WPACKET_put_bytes_u32(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 4) + +/* Set a maximum size that we will not allow the WPACKET to grow beyond */ +int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize); + +/* Copy |len| bytes of data from |*src| into the WPACKET. */ +int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len); + +/* Set |len| bytes of data to |ch| into the WPACKET. */ +int WPACKET_memset(WPACKET *pkt, int ch, size_t len); + +/* + * Copy |len| bytes of data from |*src| into the WPACKET and prefix with its + * length (consuming |lenbytes| of data for the length). Don't call this + * directly. Use the convenience macros below instead. + */ +int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len, + size_t lenbytes); + +/* Convenience macros for calling WPACKET_sub_memcpy with different lengths */ +#define WPACKET_sub_memcpy_u8(pkt, src, len) \ + WPACKET_sub_memcpy__((pkt), (src), (len), 1) +#define WPACKET_sub_memcpy_u16(pkt, src, len) \ + WPACKET_sub_memcpy__((pkt), (src), (len), 2) +#define WPACKET_sub_memcpy_u24(pkt, src, len) \ + WPACKET_sub_memcpy__((pkt), (src), (len), 3) +#define WPACKET_sub_memcpy_u32(pkt, src, len) \ + WPACKET_sub_memcpy__((pkt), (src), (len), 4) + +/* + * Return the total number of bytes written so far to the underlying buffer + * including any storage allocated for length bytes + */ +int WPACKET_get_total_written(WPACKET *pkt, size_t *written); + +/* + * Returns the length of the current sub-packet. This excludes any bytes + * allocated for the length itself. + */ +int WPACKET_get_length(WPACKET *pkt, size_t *len); + +/* + * Returns a pointer to the current write location, but does not allocate any + * bytes. + */ +unsigned char *WPACKET_get_curr(WPACKET *pkt); + +/* Returns true if the underlying buffer is actually NULL */ +int WPACKET_is_null_buf(WPACKET *pkt); + +/* Release resources in a WPACKET if a failure has occurred. */ +void WPACKET_cleanup(WPACKET *pkt); + +#endif /* OSSL_INTERNAL_PACKET_H */ diff --git a/include/internal/param_build_set.h b/include/internal/param_build_set.h new file mode 100644 index 00000000..126211b7 --- /dev/null +++ b/include/internal/param_build_set.h @@ -0,0 +1,46 @@ +/* + * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_PARAM_BUILD_SET_H +# define OSSL_INTERNAL_PARAM_BUILD_SET_H +# pragma once + +# include <openssl/safestack.h> +# include <openssl/param_build.h> +# include "internal/cryptlib.h" + +typedef union { + OSSL_UNION_ALIGN; +} OSSL_PARAM_ALIGNED_BLOCK; + +# define OSSL_PARAM_ALIGN_SIZE sizeof(OSSL_PARAM_ALIGNED_BLOCK) + +size_t ossl_param_bytes_to_blocks(size_t bytes); +void ossl_param_set_secure_block(OSSL_PARAM *last, void *secure_buffer, + size_t secure_buffer_sz); + +int ossl_param_build_set_int(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, + const char *key, int num); +int ossl_param_build_set_long(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, + const char *key, long num); +int ossl_param_build_set_utf8_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, + const char *key, const char *buf); +int ossl_param_build_set_octet_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, + const char *key, + const unsigned char *data, + size_t data_len); +int ossl_param_build_set_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, + const char *key, const BIGNUM *bn); +int ossl_param_build_set_bn_pad(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, + const char *key, const BIGNUM *bn, size_t sz); +int ossl_param_build_set_multi_key_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, + const char *names[], + STACK_OF(BIGNUM_const) *stk); + +#endif /* OSSL_INTERNAL_PARAM_BUILD_SET_H */ diff --git a/include/internal/passphrase.h b/include/internal/passphrase.h new file mode 100644 index 00000000..54d997b0 --- /dev/null +++ b/include/internal/passphrase.h @@ -0,0 +1,122 @@ +/* + * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_PASSPHRASE_H +# define OSSL_INTERNAL_PASSPHRASE_H +# pragma once + +/* + * This is a passphrase reader bridge with bells and whistles. + * + * On one hand, an API may wish to offer all sorts of passphrase callback + * possibilities to users, or may have to do so for historical reasons. + * On the other hand, that same API may have demands from other interfaces, + * notably from the libcrypto <-> provider interface, which uses + * OSSL_PASSPHRASE_CALLBACK consistently. + * + * The structure and functions below are the fundaments for bridging one + * passphrase callback form to another. + * + * In addition, extra features are included (this may be a growing list): + * + * - password caching. This is to be used by APIs where it's likely + * that the same passphrase may be asked for more than once, but the + * user shouldn't get prompted more than once. For example, this is + * useful for OSSL_DECODER, which may have to use a passphrase while + * trying to find out what input it has. + */ + +/* + * Structure to hold whatever the calling user may specify. This structure + * is intended to be integrated into API specific structures or to be used + * as a local on-stack variable type. Therefore, no functions to allocate + * or freed it on the heap is offered. + */ +struct ossl_passphrase_data_st { + enum { + is_expl_passphrase = 1, /* Explicit passphrase given by user */ + is_pem_password, /* pem_password_cb given by user */ + is_ossl_passphrase, /* OSSL_PASSPHRASE_CALLBACK given by user */ + is_ui_method /* UI_METHOD given by user */ + } type; + union { + struct { + char *passphrase_copy; + size_t passphrase_len; + } expl_passphrase; + + struct { + pem_password_cb *password_cb; + void *password_cbarg; + } pem_password; + + struct { + OSSL_PASSPHRASE_CALLBACK *passphrase_cb; + void *passphrase_cbarg; + } ossl_passphrase; + + struct { + const UI_METHOD *ui_method; + void *ui_method_data; + } ui_method; + } _; + + /*- + * Flags section + */ + + /* Set to indicate that caching should be done */ + unsigned int flag_cache_passphrase:1; + + /*- + * Misc section: caches and other + */ + + char *cached_passphrase; + size_t cached_passphrase_len; +}; + +/* Structure manipulation */ + +void ossl_pw_clear_passphrase_data(struct ossl_passphrase_data_st *data); +void ossl_pw_clear_passphrase_cache(struct ossl_passphrase_data_st *data); + +int ossl_pw_set_passphrase(struct ossl_passphrase_data_st *data, + const unsigned char *passphrase, + size_t passphrase_len); +int ossl_pw_set_pem_password_cb(struct ossl_passphrase_data_st *data, + pem_password_cb *cb, void *cbarg); +int ossl_pw_set_ossl_passphrase_cb(struct ossl_passphrase_data_st *data, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg); +int ossl_pw_set_ui_method(struct ossl_passphrase_data_st *data, + const UI_METHOD *ui_method, void *ui_data); + +int ossl_pw_enable_passphrase_caching(struct ossl_passphrase_data_st *data); +int ossl_pw_disable_passphrase_caching(struct ossl_passphrase_data_st *data); + +/* Central function for direct calls */ + +int ossl_pw_get_passphrase(char *pass, size_t pass_size, size_t *pass_len, + const OSSL_PARAM params[], int verify, + struct ossl_passphrase_data_st *data); + +/* Callback functions */ + +/* + * All of these callback expect that the callback argument is a + * struct ossl_passphrase_data_st + */ + +pem_password_cb ossl_pw_pem_password; +pem_password_cb ossl_pw_pvk_password; +/* One callback for encoding (verification prompt) and one for decoding */ +OSSL_PASSPHRASE_CALLBACK ossl_pw_passphrase_callback_enc; +OSSL_PASSPHRASE_CALLBACK ossl_pw_passphrase_callback_dec; + +#endif diff --git a/include/internal/property.h b/include/internal/property.h new file mode 100644 index 00000000..82119745 --- /dev/null +++ b/include/internal/property.h @@ -0,0 +1,93 @@ +/* + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_PROPERTY_H +# define OSSL_INTERNAL_PROPERTY_H +# pragma once + +# include "internal/cryptlib.h" + +typedef struct ossl_method_store_st OSSL_METHOD_STORE; +typedef struct ossl_property_list_st OSSL_PROPERTY_LIST; + +typedef enum { + OSSL_PROPERTY_TYPE_STRING, OSSL_PROPERTY_TYPE_NUMBER, + OSSL_PROPERTY_TYPE_VALUE_UNDEFINED +} OSSL_PROPERTY_TYPE; +typedef struct ossl_property_definition_st OSSL_PROPERTY_DEFINITION; + +/* Initialisation */ +int ossl_property_parse_init(OSSL_LIB_CTX *ctx); + +/* Property definition parser */ +OSSL_PROPERTY_LIST *ossl_parse_property(OSSL_LIB_CTX *ctx, const char *defn); +/* Property query parser */ +OSSL_PROPERTY_LIST *ossl_parse_query(OSSL_LIB_CTX *ctx, const char *s, + int create_values); +/* Property checker of query vs definition */ +int ossl_property_match_count(const OSSL_PROPERTY_LIST *query, + const OSSL_PROPERTY_LIST *defn); +int ossl_property_is_enabled(OSSL_LIB_CTX *ctx, const char *property_name, + const OSSL_PROPERTY_LIST *prop_list); +/* Free a parsed property list */ +void ossl_property_free(OSSL_PROPERTY_LIST *p); + +/* Get a property from a property list */ +const OSSL_PROPERTY_DEFINITION * +ossl_property_find_property(const OSSL_PROPERTY_LIST *list, + OSSL_LIB_CTX *libctx, const char *name); +OSSL_PROPERTY_TYPE ossl_property_get_type(const OSSL_PROPERTY_DEFINITION *prop); +const char *ossl_property_get_string_value(OSSL_LIB_CTX *libctx, + const OSSL_PROPERTY_DEFINITION *prop); +int64_t ossl_property_get_number_value(const OSSL_PROPERTY_DEFINITION *prop); + + +/* Implementation store functions */ +OSSL_METHOD_STORE *ossl_method_store_new(OSSL_LIB_CTX *ctx); +void ossl_method_store_free(OSSL_METHOD_STORE *store); +int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov, + int nid, const char *properties, void *method, + int (*method_up_ref)(void *), + void (*method_destruct)(void *)); +int ossl_method_store_remove(OSSL_METHOD_STORE *store, int nid, + const void *method); +void ossl_method_store_do_all(OSSL_METHOD_STORE *store, + void (*fn)(int id, void *method, void *fnarg), + void *fnarg); +int ossl_method_store_fetch(OSSL_METHOD_STORE *store, + int nid, const char *prop_query, + const OSSL_PROVIDER **prov, void **method); + +/* Get the global properties associate with the specified library context */ +OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *ctx, + int loadconfig); + +/* property query cache functions */ +int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov, + int nid, const char *prop_query, void **result); +int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov, + int nid, const char *prop_query, void *result, + int (*method_up_ref)(void *), + void (*method_destruct)(void *)); + +__owur int ossl_method_store_flush_cache(OSSL_METHOD_STORE *store, int all); + +/* Merge two property queries together */ +OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a, + const OSSL_PROPERTY_LIST *b); + +size_t ossl_property_list_to_string(OSSL_LIB_CTX *ctx, + const OSSL_PROPERTY_LIST *list, char *buf, + size_t bufsize); + +int ossl_global_properties_no_mirrored(OSSL_LIB_CTX *libctx); +void ossl_global_properties_stop_mirroring(OSSL_LIB_CTX *libctx); + +#endif diff --git a/include/internal/propertyerr.h b/include/internal/propertyerr.h new file mode 100644 index 00000000..fbee53f1 --- /dev/null +++ b/include/internal/propertyerr.h @@ -0,0 +1,43 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_PROPERTYERR_H +# define OSSL_INTERNAL_PROPERTYERR_H +# pragma once + +# include <openssl/opensslconf.h> +# include <openssl/symhacks.h> + +# ifdef __cplusplus +extern "C" { +# endif + +int ossl_err_load_PROP_strings(void); + +/* + * PROP reason codes. + */ +# define PROP_R_NAME_TOO_LONG 100 +# define PROP_R_NOT_AN_ASCII_CHARACTER 101 +# define PROP_R_NOT_AN_HEXADECIMAL_DIGIT 102 +# define PROP_R_NOT_AN_IDENTIFIER 103 +# define PROP_R_NOT_AN_OCTAL_DIGIT 104 +# define PROP_R_NOT_A_DECIMAL_DIGIT 105 +# define PROP_R_NO_MATCHING_STRING_DELIMITER 106 +# define PROP_R_NO_VALUE 107 +# define PROP_R_PARSE_FAILED 108 +# define PROP_R_STRING_TOO_LONG 109 +# define PROP_R_TRAILING_CHARACTERS 110 + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/include/internal/provider.h b/include/internal/provider.h new file mode 100644 index 00000000..d09829d0 --- /dev/null +++ b/include/internal/provider.h @@ -0,0 +1,117 @@ +/* + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_PROVIDER_H +# define OSSL_INTERNAL_PROVIDER_H +# pragma once + +# include <openssl/core.h> +# include <openssl/core_dispatch.h> +# include "internal/dso.h" +# include "internal/symhacks.h" + +# ifdef __cplusplus +extern "C" { +# endif + +/* + * namespaces: + * + * ossl_provider_ Provider Object internal API + * OSSL_PROVIDER Provider Object + */ + +/* Provider Object finder, constructor and destructor */ +OSSL_PROVIDER *ossl_provider_find(OSSL_LIB_CTX *libctx, const char *name, + int noconfig); +OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name, + OSSL_provider_init_fn *init_function, + int noconfig); +int ossl_provider_up_ref(OSSL_PROVIDER *prov); +void ossl_provider_free(OSSL_PROVIDER *prov); + +/* Setters */ +int ossl_provider_set_fallback(OSSL_PROVIDER *prov); +int ossl_provider_set_module_path(OSSL_PROVIDER *prov, const char *module_path); +int ossl_provider_add_parameter(OSSL_PROVIDER *prov, const char *name, + const char *value); + +int ossl_provider_is_child(const OSSL_PROVIDER *prov); +int ossl_provider_set_child(OSSL_PROVIDER *prov, const OSSL_CORE_HANDLE *handle); +const OSSL_CORE_HANDLE *ossl_provider_get_parent(OSSL_PROVIDER *prov); +int ossl_provider_up_ref_parent(OSSL_PROVIDER *prov, int activate); +int ossl_provider_free_parent(OSSL_PROVIDER *prov, int deactivate); +int ossl_provider_default_props_update(OSSL_LIB_CTX *libctx, const char *props); + +/* Disable fallback loading */ +int ossl_provider_disable_fallback_loading(OSSL_LIB_CTX *libctx); + +/* + * Activate the Provider + * If the Provider is a module, the module will be loaded + */ +int ossl_provider_activate(OSSL_PROVIDER *prov, int upcalls, int aschild); +int ossl_provider_deactivate(OSSL_PROVIDER *prov, int removechildren); +int ossl_provider_add_to_store(OSSL_PROVIDER *prov, OSSL_PROVIDER **actualprov, + int retain_fallbacks); + +/* Return pointer to the provider's context */ +void *ossl_provider_ctx(const OSSL_PROVIDER *prov); + +/* Iterate over all loaded providers */ +int ossl_provider_doall_activated(OSSL_LIB_CTX *, + int (*cb)(OSSL_PROVIDER *provider, + void *cbdata), + void *cbdata); + +/* Getters for other library functions */ +const char *ossl_provider_name(const OSSL_PROVIDER *prov); +const DSO *ossl_provider_dso(const OSSL_PROVIDER *prov); +const char *ossl_provider_module_name(const OSSL_PROVIDER *prov); +const char *ossl_provider_module_path(const OSSL_PROVIDER *prov); +void *ossl_provider_prov_ctx(const OSSL_PROVIDER *prov); +const OSSL_DISPATCH *ossl_provider_get0_dispatch(const OSSL_PROVIDER *prov); +OSSL_LIB_CTX *ossl_provider_libctx(const OSSL_PROVIDER *prov); + +/* Thin wrappers around calls to the provider */ +void ossl_provider_teardown(const OSSL_PROVIDER *prov); +const OSSL_PARAM *ossl_provider_gettable_params(const OSSL_PROVIDER *prov); +int ossl_provider_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[]); +int ossl_provider_get_capabilities(const OSSL_PROVIDER *prov, + const char *capability, + OSSL_CALLBACK *cb, + void *arg); +int ossl_provider_self_test(const OSSL_PROVIDER *prov); +const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov, + int operation_id, + int *no_cache); +void ossl_provider_unquery_operation(const OSSL_PROVIDER *prov, + int operation_id, + const OSSL_ALGORITHM *algs); + +/* Cache of bits to see if we already queried an operation */ +int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum); +int ossl_provider_test_operation_bit(OSSL_PROVIDER *provider, size_t bitnum, + int *result); +int ossl_provider_clear_all_operation_bits(OSSL_LIB_CTX *libctx); + +/* Configuration */ +void ossl_provider_add_conf_module(void); + +/* Child providers */ +int ossl_provider_init_as_child(OSSL_LIB_CTX *ctx, + const OSSL_CORE_HANDLE *handle, + const OSSL_DISPATCH *in); +void ossl_provider_deinit_child(OSSL_LIB_CTX *ctx); + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/include/internal/refcount.h b/include/internal/refcount.h new file mode 100644 index 00000000..7412d62f --- /dev/null +++ b/include/internal/refcount.h @@ -0,0 +1,178 @@ +/* + * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#ifndef OSSL_INTERNAL_REFCOUNT_H +# define OSSL_INTERNAL_REFCOUNT_H +# pragma once + +# include <openssl/e_os2.h> +# include <openssl/trace.h> + +# ifndef OPENSSL_DEV_NO_ATOMICS +# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \ + && !defined(__STDC_NO_ATOMICS__) +# include <stdatomic.h> +# define HAVE_C11_ATOMICS +# endif + +# if defined(HAVE_C11_ATOMICS) && defined(ATOMIC_INT_LOCK_FREE) \ + && ATOMIC_INT_LOCK_FREE > 0 + +# define HAVE_ATOMICS 1 + +typedef _Atomic int CRYPTO_REF_COUNT; + +static inline int CRYPTO_UP_REF(_Atomic int *val, int *ret, + ossl_unused void *lock) +{ + *ret = atomic_fetch_add_explicit(val, 1, memory_order_relaxed) + 1; + return 1; +} + +/* + * Changes to shared structure other than reference counter have to be + * serialized. And any kind of serialization implies a release fence. This + * means that by the time reference counter is decremented all other + * changes are visible on all processors. Hence decrement itself can be + * relaxed. In case it hits zero, object will be destructed. Since it's + * last use of the object, destructor programmer might reason that access + * to mutable members doesn't have to be serialized anymore, which would + * otherwise imply an acquire fence. Hence conditional acquire fence... + */ +static inline int CRYPTO_DOWN_REF(_Atomic int *val, int *ret, + ossl_unused void *lock) +{ + *ret = atomic_fetch_sub_explicit(val, 1, memory_order_relaxed) - 1; + if (*ret == 0) + atomic_thread_fence(memory_order_acquire); + return 1; +} + +# elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) && __GCC_ATOMIC_INT_LOCK_FREE > 0 + +# define HAVE_ATOMICS 1 + +typedef int CRYPTO_REF_COUNT; + +static __inline__ int CRYPTO_UP_REF(int *val, int *ret, ossl_unused void *lock) +{ + *ret = __atomic_fetch_add(val, 1, __ATOMIC_RELAXED) + 1; + return 1; +} + +static __inline__ int CRYPTO_DOWN_REF(int *val, int *ret, + ossl_unused void *lock) +{ + *ret = __atomic_fetch_sub(val, 1, __ATOMIC_RELAXED) - 1; + if (*ret == 0) + __atomic_thread_fence(__ATOMIC_ACQUIRE); + return 1; +} +# elif defined(__ICL) && defined(_WIN32) +# define HAVE_ATOMICS 1 +typedef volatile int CRYPTO_REF_COUNT; + +static __inline int CRYPTO_UP_REF(volatile int *val, int *ret, + ossl_unused void *lock) +{ + *ret = _InterlockedExchangeAdd((void *)val, 1) + 1; + return 1; +} + +static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret, + ossl_unused void *lock) +{ + *ret = _InterlockedExchangeAdd((void *)val, -1) - 1; + return 1; +} + +# elif defined(_MSC_VER) && _MSC_VER>=1200 + +# define HAVE_ATOMICS 1 + +typedef volatile int CRYPTO_REF_COUNT; + +# if (defined(_M_ARM) && _M_ARM>=7 && !defined(_WIN32_WCE)) || defined(_M_ARM64) +# include <intrin.h> +# if defined(_M_ARM64) && !defined(_ARM_BARRIER_ISH) +# define _ARM_BARRIER_ISH _ARM64_BARRIER_ISH +# endif + +static __inline int CRYPTO_UP_REF(volatile int *val, int *ret, + ossl_unused void *lock) +{ + *ret = _InterlockedExchangeAdd_nf(val, 1) + 1; + return 1; +} + +static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret, + ossl_unused void *lock) +{ + *ret = _InterlockedExchangeAdd_nf(val, -1) - 1; + if (*ret == 0) + __dmb(_ARM_BARRIER_ISH); + return 1; +} +# else +# if !defined(_WIN32_WCE) +# pragma intrinsic(_InterlockedExchangeAdd) +# else +# if _WIN32_WCE >= 0x600 + extern long __cdecl _InterlockedExchangeAdd(long volatile*, long); +# else + /* under Windows CE we still have old-style Interlocked* functions */ + extern long __cdecl InterlockedExchangeAdd(long volatile*, long); +# define _InterlockedExchangeAdd InterlockedExchangeAdd +# endif +# endif + +static __inline int CRYPTO_UP_REF(volatile int *val, int *ret, + ossl_unused void *lock) +{ + *ret = _InterlockedExchangeAdd(val, 1) + 1; + return 1; +} + +static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret, + ossl_unused void *lock) +{ + *ret = _InterlockedExchangeAdd(val, -1) - 1; + return 1; +} +# endif + +# endif +# endif /* !OPENSSL_DEV_NO_ATOMICS */ + +/* + * All the refcounting implementations above define HAVE_ATOMICS, so if it's + * still undefined here (such as when OPENSSL_DEV_NO_ATOMICS is defined), it + * means we need to implement a fallback. This fallback uses locks. + */ +# ifndef HAVE_ATOMICS + +typedef int CRYPTO_REF_COUNT; + +# define CRYPTO_UP_REF(val, ret, lock) CRYPTO_atomic_add(val, 1, ret, lock) +# define CRYPTO_DOWN_REF(val, ret, lock) CRYPTO_atomic_add(val, -1, ret, lock) + +# endif + +# if !defined(NDEBUG) && !defined(OPENSSL_NO_STDIO) +# define REF_ASSERT_ISNT(test) \ + (void)((test) ? (OPENSSL_die("refcount error", __FILE__, __LINE__), 1) : 0) +# else +# define REF_ASSERT_ISNT(i) +# endif + +# define REF_PRINT_EX(text, count, object) \ + OSSL_TRACE3(REF_COUNT, "%p:%4d:%s\n", (object), (count), (text)); +# define REF_PRINT_COUNT(text, object) \ + REF_PRINT_EX(text, object->references, (void *)object) + +#endif diff --git a/include/internal/sha3.h b/include/internal/sha3.h new file mode 100644 index 00000000..80ad86e5 --- /dev/null +++ b/include/internal/sha3.h @@ -0,0 +1,54 @@ +/* + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* This header can move into provider when legacy support is removed */ +#ifndef OSSL_INTERNAL_SHA3_H +# define OSSL_INTERNAL_SHA3_H +# pragma once + +# include <openssl/e_os2.h> +# include <stddef.h> + +# define KECCAK1600_WIDTH 1600 +# define SHA3_MDSIZE(bitlen) (bitlen / 8) +# define KMAC_MDSIZE(bitlen) 2 * (bitlen / 8) +# define SHA3_BLOCKSIZE(bitlen) (KECCAK1600_WIDTH - bitlen * 2) / 8 + +typedef struct keccak_st KECCAK1600_CTX; + +typedef size_t (sha3_absorb_fn)(void *vctx, const void *inp, size_t len); +typedef int (sha3_final_fn)(unsigned char *md, void *vctx); + +typedef struct prov_sha3_meth_st +{ + sha3_absorb_fn *absorb; + sha3_final_fn *final; +} PROV_SHA3_METHOD; + +struct keccak_st { + uint64_t A[5][5]; + size_t block_size; /* cached ctx->digest->block_size */ + size_t md_size; /* output length, variable in XOF */ + size_t bufsz; /* used bytes in below buffer */ + unsigned char buf[KECCAK1600_WIDTH / 8 - 32]; + unsigned char pad; + PROV_SHA3_METHOD meth; +}; + +void ossl_sha3_reset(KECCAK1600_CTX *ctx); +int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen); +int ossl_keccak_kmac_init(KECCAK1600_CTX *ctx, unsigned char pad, + size_t bitlen); +int ossl_sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len); +int ossl_sha3_final(unsigned char *md, KECCAK1600_CTX *ctx); + +size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len, + size_t r); + +#endif /* OSSL_INTERNAL_SHA3_H */ diff --git a/include/internal/sizes.h b/include/internal/sizes.h new file mode 100644 index 00000000..f6496c81 --- /dev/null +++ b/include/internal/sizes.h @@ -0,0 +1,22 @@ +/* + * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_SIZES_H +# define OSSL_INTERNAL_SIZES_H +# pragma once + +/* + * Max sizes used to allocate buffers with a fixed sizes, for example for + * stack allocations, structure fields, ... + */ +# define OSSL_MAX_NAME_SIZE 50 /* Algorithm name */ +# define OSSL_MAX_PROPQUERY_SIZE 256 /* Property query strings */ +# define OSSL_MAX_ALGORITHM_ID_SIZE 256 /* AlgorithmIdentifier DER */ + +#endif diff --git a/include/internal/sm3.h b/include/internal/sm3.h new file mode 100644 index 00000000..db1d61f0 --- /dev/null +++ b/include/internal/sm3.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017 Ribose Inc. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* This header can move into provider when legacy support is removed */ +#ifndef OSSL_INTERNAL_SM3_H +# define OSSL_INTERNAL_SM3_H +# pragma once + +# include <openssl/opensslconf.h> + +# ifdef OPENSSL_NO_SM3 +# error SM3 is disabled. +# endif + +# define SM3_DIGEST_LENGTH 32 +# define SM3_WORD unsigned int + +# define SM3_CBLOCK 64 +# define SM3_LBLOCK (SM3_CBLOCK/4) + +typedef struct SM3state_st { + SM3_WORD A, B, C, D, E, F, G, H; + SM3_WORD Nl, Nh; + SM3_WORD data[SM3_LBLOCK]; + unsigned int num; +} SM3_CTX; + +int ossl_sm3_init(SM3_CTX *c); +int ossl_sm3_update(SM3_CTX *c, const void *data, size_t len); +int ossl_sm3_final(unsigned char *md, SM3_CTX *c); + +#endif /* OSSL_INTERNAL_SM3_H */ diff --git a/include/internal/sockets.h b/include/internal/sockets.h new file mode 100644 index 00000000..6e882fa6 --- /dev/null +++ b/include/internal/sockets.h @@ -0,0 +1,175 @@ +/* + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_SOCKETS_H +# define OSSL_INTERNAL_SOCKETS_H +# pragma once + +# include <openssl/opensslconf.h> + +# if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI) +# define NO_SYS_PARAM_H +# endif +# ifdef WIN32 +# define NO_SYS_UN_H +# endif +# ifdef OPENSSL_SYS_VMS +# define NO_SYS_PARAM_H +# define NO_SYS_UN_H +# endif + +# ifdef OPENSSL_NO_SOCK + +# elif defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) +# if defined(__DJGPP__) +# include <sys/socket.h> +# include <sys/un.h> +# include <tcp.h> +# include <netdb.h> +# elif defined(_WIN32_WCE) && _WIN32_WCE<410 +# define getservbyname _masked_declaration_getservbyname +# endif +# if !defined(IPPROTO_IP) + /* winsock[2].h was included already? */ +# include <winsock.h> +# endif +# ifdef getservbyname + /* this is used to be wcecompat/include/winsock_extras.h */ +# undef getservbyname +struct servent *PASCAL getservbyname(const char *, const char *); +# endif + +# ifdef _WIN64 +/* + * Even though sizeof(SOCKET) is 8, it's safe to cast it to int, because + * the value constitutes an index in per-process table of limited size + * and not a real pointer. And we also depend on fact that all processors + * Windows run on happen to be two's-complement, which allows to + * interchange INVALID_SOCKET and -1. + */ +# define socket(d,t,p) ((int)socket(d,t,p)) +# define accept(s,f,l) ((int)accept(s,f,l)) +# endif + +# else + +# ifndef NO_SYS_PARAM_H +# include <sys/param.h> +# endif +# ifdef OPENSSL_SYS_VXWORKS +# include <time.h> +# endif + +# include <netdb.h> +# if defined(OPENSSL_SYS_VMS_NODECC) +# include <socket.h> +# include <in.h> +# include <inet.h> +# else +# include <sys/socket.h> +# ifndef NO_SYS_UN_H +# include <sys/un.h> +# ifndef UNIX_PATH_MAX +# define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)NULL)->sun_path) +# endif +# endif +# ifdef FILIO_H +# include <sys/filio.h> /* FIONBIO in some SVR4, e.g. unixware, solaris */ +# endif +# include <netinet/in.h> +# include <arpa/inet.h> +# include <netinet/tcp.h> +# endif + +# ifdef OPENSSL_SYS_AIX +# include <sys/select.h> +# endif + +# ifndef VMS +# include <sys/ioctl.h> +# else +# if !defined(TCPIP_TYPE_SOCKETSHR) && defined(__VMS_VER) && (__VMS_VER > 70000000) + /* ioctl is only in VMS > 7.0 and when socketshr is not used */ +# include <sys/ioctl.h> +# endif +# include <unixio.h> +# if defined(TCPIP_TYPE_SOCKETSHR) +# include <socketshr.h> +# endif +# endif + +# ifndef INVALID_SOCKET +# define INVALID_SOCKET (-1) +# endif +# endif + +/* + * Some IPv6 implementations are broken, you can disable them in known + * bad versions. + */ +# if !defined(OPENSSL_USE_IPV6) +# if defined(AF_INET6) +# define OPENSSL_USE_IPV6 1 +# else +# define OPENSSL_USE_IPV6 0 +# endif +# endif + +# define get_last_socket_error() errno +# define clear_socket_error() errno=0 + +# if defined(OPENSSL_SYS_WINDOWS) +# undef get_last_socket_error +# undef clear_socket_error +# define get_last_socket_error() WSAGetLastError() +# define clear_socket_error() WSASetLastError(0) +# define readsocket(s,b,n) recv((s),(b),(n),0) +# define writesocket(s,b,n) send((s),(b),(n),0) +# elif defined(__DJGPP__) +# define WATT32 +# define WATT32_NO_OLDIES +# define closesocket(s) close_s(s) +# define readsocket(s,b,n) read_s(s,b,n) +# define writesocket(s,b,n) send(s,b,n,0) +# elif defined(OPENSSL_SYS_VMS) +# define ioctlsocket(a,b,c) ioctl(a,b,c) +# define closesocket(s) close(s) +# define readsocket(s,b,n) recv((s),(b),(n),0) +# define writesocket(s,b,n) send((s),(b),(n),0) +# elif defined(OPENSSL_SYS_VXWORKS) +# define ioctlsocket(a,b,c) ioctl((a),(b),(int)(c)) +# define closesocket(s) close(s) +# define readsocket(s,b,n) read((s),(b),(n)) +# define writesocket(s,b,n) write((s),(char *)(b),(n)) +# elif defined(OPENSSL_SYS_TANDEM) +# if defined(OPENSSL_TANDEM_FLOSS) +# include <floss.h(floss_read, floss_write)> +# define readsocket(s,b,n) floss_read((s),(b),(n)) +# define writesocket(s,b,n) floss_write((s),(b),(n)) +# else +# define readsocket(s,b,n) read((s),(b),(n)) +# define writesocket(s,b,n) write((s),(b),(n)) +# endif +# define ioctlsocket(a,b,c) ioctl(a,b,c) +# define closesocket(s) close(s) +# else +# define ioctlsocket(a,b,c) ioctl(a,b,c) +# define closesocket(s) close(s) +# define readsocket(s,b,n) read((s),(b),(n)) +# define writesocket(s,b,n) write((s),(b),(n)) +# endif + +/* also in apps/include/apps.h */ +# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINCE) +# define openssl_fdset(a, b) FD_SET((unsigned int)(a), b) +# else +# define openssl_fdset(a, b) FD_SET(a, b) +# endif + +#endif diff --git a/include/internal/sslconf.h b/include/internal/sslconf.h new file mode 100644 index 00000000..fd7f7e33 --- /dev/null +++ b/include/internal/sslconf.h @@ -0,0 +1,21 @@ +/* + * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_SSLCONF_H +# define OSSL_INTERNAL_SSLCONF_H +# pragma once + +typedef struct ssl_conf_cmd_st SSL_CONF_CMD; + +const SSL_CONF_CMD *conf_ssl_get(size_t idx, const char **name, size_t *cnt); +int conf_ssl_name_find(const char *name, size_t *idx); +void conf_ssl_get_cmd(const SSL_CONF_CMD *cmd, size_t idx, char **cmdstr, + char **arg); + +#endif diff --git a/include/internal/symhacks.h b/include/internal/symhacks.h new file mode 100644 index 00000000..33bae51e --- /dev/null +++ b/include/internal/symhacks.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_SYMHACKS_H +# define OSSL_INTERNAL_SYMHACKS_H +# pragma once + +# include <openssl/e_os2.h> + +# if defined(OPENSSL_SYS_VMS) + +/* ossl_provider_gettable_params vs OSSL_PROVIDER_gettable_params */ +# undef ossl_provider_gettable_params +# define ossl_provider_gettable_params ossl_int_prov_gettable_params +/* ossl_provider_get_params vs OSSL_PROVIDER_get_params */ +# undef ossl_provider_get_params +# define ossl_provider_get_params ossl_int_prov_get_params + +# endif + +#endif /* ! defined HEADER_VMS_IDHACKS_H */ diff --git a/include/internal/thread_once.h b/include/internal/thread_once.h new file mode 100644 index 00000000..d6cb2eee --- /dev/null +++ b/include/internal/thread_once.h @@ -0,0 +1,151 @@ +/* + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_THREAD_ONCE_H +# define OSSL_INTERNAL_THREAD_ONCE_H +# pragma once + +# include <openssl/crypto.h> + +/* + * Initialisation of global data should never happen via "RUN_ONCE" inside the + * FIPS module. Global data should instead always be associated with a specific + * OSSL_LIB_CTX object. In this way data will get cleaned up correctly when the + * module gets unloaded. + */ +# if !defined(FIPS_MODULE) || defined(ALLOW_RUN_ONCE_IN_FIPS) +/* + * DEFINE_RUN_ONCE: Define an initialiser function that should be run exactly + * once. It takes no arguments and returns an int result (1 for success or + * 0 for failure). Typical usage might be: + * + * DEFINE_RUN_ONCE(myinitfunc) + * { + * do_some_initialisation(); + * if (init_is_successful()) + * return 1; + * + * return 0; + * } + */ +# define DEFINE_RUN_ONCE(init) \ + static int init(void); \ + int init##_ossl_ret_ = 0; \ + void init##_ossl_(void) \ + { \ + init##_ossl_ret_ = init(); \ + } \ + static int init(void) + +/* + * DECLARE_RUN_ONCE: Declare an initialiser function that should be run exactly + * once that has been defined in another file via DEFINE_RUN_ONCE(). + */ +# define DECLARE_RUN_ONCE(init) \ + extern int init##_ossl_ret_; \ + void init##_ossl_(void); + +/* + * DEFINE_RUN_ONCE_STATIC: Define an initialiser function that should be run + * exactly once. This function will be declared as static within the file. It + * takes no arguments and returns an int result (1 for success or 0 for + * failure). Typical usage might be: + * + * DEFINE_RUN_ONCE_STATIC(myinitfunc) + * { + * do_some_initialisation(); + * if (init_is_successful()) + * return 1; + * + * return 0; + * } + */ +# define DEFINE_RUN_ONCE_STATIC(init) \ + static int init(void); \ + static int init##_ossl_ret_ = 0; \ + static void init##_ossl_(void) \ + { \ + init##_ossl_ret_ = init(); \ + } \ + static int init(void) + +/* + * DEFINE_RUN_ONCE_STATIC_ALT: Define an alternative initialiser function. This + * function will be declared as static within the file. It takes no arguments + * and returns an int result (1 for success or 0 for failure). An alternative + * initialiser function is expected to be associated with a primary initialiser + * function defined via DEFINE_ONCE_STATIC where both functions use the same + * CRYPTO_ONCE object to synchronise. Where an alternative initialiser function + * is used only one of the primary or the alternative initialiser function will + * ever be called - and that function will be called exactly once. Definition + * of an alternative initialiser function MUST occur AFTER the definition of the + * primary initialiser function. + * + * Typical usage might be: + * + * DEFINE_RUN_ONCE_STATIC(myinitfunc) + * { + * do_some_initialisation(); + * if (init_is_successful()) + * return 1; + * + * return 0; + * } + * + * DEFINE_RUN_ONCE_STATIC_ALT(myaltinitfunc, myinitfunc) + * { + * do_some_alternative_initialisation(); + * if (init_is_successful()) + * return 1; + * + * return 0; + * } + */ +# define DEFINE_RUN_ONCE_STATIC_ALT(initalt, init) \ + static int initalt(void); \ + static void initalt##_ossl_(void) \ + { \ + init##_ossl_ret_ = initalt(); \ + } \ + static int initalt(void) + +/* + * RUN_ONCE - use CRYPTO_THREAD_run_once, and check if the init succeeded + * @once: pointer to static object of type CRYPTO_ONCE + * @init: function name that was previously given to DEFINE_RUN_ONCE, + * DEFINE_RUN_ONCE_STATIC or DECLARE_RUN_ONCE. This function + * must return 1 for success or 0 for failure. + * + * The return value is 1 on success (*) or 0 in case of error. + * + * (*) by convention, since the init function must return 1 on success. + */ +# define RUN_ONCE(once, init) \ + (CRYPTO_THREAD_run_once(once, init##_ossl_) ? init##_ossl_ret_ : 0) + +/* + * RUN_ONCE_ALT - use CRYPTO_THREAD_run_once, to run an alternative initialiser + * function and check if that initialisation succeeded + * @once: pointer to static object of type CRYPTO_ONCE + * @initalt: alternative initialiser function name that was previously given to + * DEFINE_RUN_ONCE_STATIC_ALT. This function must return 1 for + * success or 0 for failure. + * @init: primary initialiser function name that was previously given to + * DEFINE_RUN_ONCE_STATIC. This function must return 1 for success or + * 0 for failure. + * + * The return value is 1 on success (*) or 0 in case of error. + * + * (*) by convention, since the init function must return 1 on success. + */ +# define RUN_ONCE_ALT(once, initalt, init) \ + (CRYPTO_THREAD_run_once(once, initalt##_ossl_) ? init##_ossl_ret_ : 0) + +# endif /* FIPS_MODULE */ +#endif /* OSSL_INTERNAL_THREAD_ONCE_H */ diff --git a/include/internal/tlsgroups.h b/include/internal/tlsgroups.h new file mode 100644 index 00000000..8a35ced1 --- /dev/null +++ b/include/internal/tlsgroups.h @@ -0,0 +1,50 @@ +/* + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_TLSGROUPS_H +# define OSSL_INTERNAL_TLSGROUPS_H +# pragma once + +# define OSSL_TLS_GROUP_ID_sect163k1 0x0001 +# define OSSL_TLS_GROUP_ID_sect163r1 0x0002 +# define OSSL_TLS_GROUP_ID_sect163r2 0x0003 +# define OSSL_TLS_GROUP_ID_sect193r1 0x0004 +# define OSSL_TLS_GROUP_ID_sect193r2 0x0005 +# define OSSL_TLS_GROUP_ID_sect233k1 0x0006 +# define OSSL_TLS_GROUP_ID_sect233r1 0x0007 +# define OSSL_TLS_GROUP_ID_sect239k1 0x0008 +# define OSSL_TLS_GROUP_ID_sect283k1 0x0009 +# define OSSL_TLS_GROUP_ID_sect283r1 0x000A +# define OSSL_TLS_GROUP_ID_sect409k1 0x000B +# define OSSL_TLS_GROUP_ID_sect409r1 0x000C +# define OSSL_TLS_GROUP_ID_sect571k1 0x000D +# define OSSL_TLS_GROUP_ID_sect571r1 0x000E +# define OSSL_TLS_GROUP_ID_secp160k1 0x000F +# define OSSL_TLS_GROUP_ID_secp160r1 0x0010 +# define OSSL_TLS_GROUP_ID_secp160r2 0x0011 +# define OSSL_TLS_GROUP_ID_secp192k1 0x0012 +# define OSSL_TLS_GROUP_ID_secp192r1 0x0013 +# define OSSL_TLS_GROUP_ID_secp224k1 0x0014 +# define OSSL_TLS_GROUP_ID_secp224r1 0x0015 +# define OSSL_TLS_GROUP_ID_secp256k1 0x0016 +# define OSSL_TLS_GROUP_ID_secp256r1 0x0017 +# define OSSL_TLS_GROUP_ID_secp384r1 0x0018 +# define OSSL_TLS_GROUP_ID_secp521r1 0x0019 +# define OSSL_TLS_GROUP_ID_brainpoolP256r1 0x001A +# define OSSL_TLS_GROUP_ID_brainpoolP384r1 0x001B +# define OSSL_TLS_GROUP_ID_brainpoolP512r1 0x001C +# define OSSL_TLS_GROUP_ID_x25519 0x001D +# define OSSL_TLS_GROUP_ID_x448 0x001E +# define OSSL_TLS_GROUP_ID_ffdhe2048 0x0100 +# define OSSL_TLS_GROUP_ID_ffdhe3072 0x0101 +# define OSSL_TLS_GROUP_ID_ffdhe4096 0x0102 +# define OSSL_TLS_GROUP_ID_ffdhe6144 0x0103 +# define OSSL_TLS_GROUP_ID_ffdhe8192 0x0104 + +#endif diff --git a/include/internal/tsan_assist.h b/include/internal/tsan_assist.h new file mode 100644 index 00000000..f8285b1d --- /dev/null +++ b/include/internal/tsan_assist.h @@ -0,0 +1,144 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Contemporary compilers implement lock-free atomic memory access + * primitives that facilitate writing "thread-opportunistic" or even real + * multi-threading low-overhead code. "Thread-opportunistic" is when + * exact result is not required, e.g. some statistics, or execution flow + * doesn't have to be unambiguous. Simplest example is lazy "constant" + * initialization when one can synchronize on variable itself, e.g. + * + * if (var == NOT_YET_INITIALIZED) + * var = function_returning_same_value(); + * + * This does work provided that loads and stores are single-instruction + * operations (and integer ones are on *all* supported platforms), but + * it upsets Thread Sanitizer. Suggested solution is + * + * if (tsan_load(&var) == NOT_YET_INITIALIZED) + * tsan_store(&var, function_returning_same_value()); + * + * Production machine code would be the same, so one can wonder why + * bother. Having Thread Sanitizer accept "thread-opportunistic" code + * allows to move on trouble-shooting real bugs. + * + * Resolving Thread Sanitizer nits was the initial purpose for this module, + * but it was later extended with more nuanced primitives that are useful + * even in "non-opportunistic" scenarios. Most notably verifying if a shared + * structure is fully initialized and bypassing the initialization lock. + * It's suggested to view macros defined in this module as "annotations" for + * thread-safe lock-free code, "Thread-Safe ANnotations"... + * + * It's assumed that ATOMIC_{LONG|INT}_LOCK_FREE are assigned same value as + * ATOMIC_POINTER_LOCK_FREE. And check for >= 2 ensures that corresponding + * code is inlined. It should be noted that statistics counters become + * accurate in such case. + * + * Special note about TSAN_QUALIFIER. It might be undesired to use it in + * a shared header. Because whether operation on specific variable or member + * is atomic or not might be irrelevant in other modules. In such case one + * can use TSAN_QUALIFIER in cast specifically when it has to count. + */ + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \ + && !defined(__STDC_NO_ATOMICS__) +# include <stdatomic.h> + +# if defined(ATOMIC_POINTER_LOCK_FREE) \ + && ATOMIC_POINTER_LOCK_FREE >= 2 +# define TSAN_QUALIFIER _Atomic +# define tsan_load(ptr) atomic_load_explicit((ptr), memory_order_relaxed) +# define tsan_store(ptr, val) atomic_store_explicit((ptr), (val), memory_order_relaxed) +# define tsan_counter(ptr) atomic_fetch_add_explicit((ptr), 1, memory_order_relaxed) +# define tsan_decr(ptr) atomic_fetch_add_explicit((ptr), -1, memory_order_relaxed) +# define tsan_ld_acq(ptr) atomic_load_explicit((ptr), memory_order_acquire) +# define tsan_st_rel(ptr, val) atomic_store_explicit((ptr), (val), memory_order_release) +# endif + +#elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) + +# if defined(__GCC_ATOMIC_POINTER_LOCK_FREE) \ + && __GCC_ATOMIC_POINTER_LOCK_FREE >= 2 +# define TSAN_QUALIFIER volatile +# define tsan_load(ptr) __atomic_load_n((ptr), __ATOMIC_RELAXED) +# define tsan_store(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_RELAXED) +# define tsan_counter(ptr) __atomic_fetch_add((ptr), 1, __ATOMIC_RELAXED) +# define tsan_decr(ptr) __atomic_fetch_add((ptr), -1, __ATOMIC_RELAXED) +# define tsan_ld_acq(ptr) __atomic_load_n((ptr), __ATOMIC_ACQUIRE) +# define tsan_st_rel(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_RELEASE) +# endif + +#elif defined(_MSC_VER) && _MSC_VER>=1200 \ + && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || \ + defined(_M_ARM64) || (defined(_M_ARM) && _M_ARM >= 7 && !defined(_WIN32_WCE))) +/* + * There is subtle dependency on /volatile:<iso|ms> command-line option. + * "ms" implies same semantic as memory_order_acquire for loads and + * memory_order_release for stores, while "iso" - memory_order_relaxed for + * either. Real complication is that defaults are different on x86 and ARM. + * There is explanation for that, "ms" is backward compatible with earlier + * compiler versions, while multi-processor ARM can be viewed as brand new + * platform to MSC and its users, and with non-relaxed semantic taking toll + * with additional instructions and penalties, it kind of makes sense to + * default to "iso"... + */ +# define TSAN_QUALIFIER volatile +# if defined(_M_ARM) || defined(_M_ARM64) +# define _InterlockedExchangeAdd _InterlockedExchangeAdd_nf +# pragma intrinsic(_InterlockedExchangeAdd_nf) +# pragma intrinsic(__iso_volatile_load32, __iso_volatile_store32) +# ifdef _WIN64 +# define _InterlockedExchangeAdd64 _InterlockedExchangeAdd64_nf +# pragma intrinsic(_InterlockedExchangeAdd64_nf) +# pragma intrinsic(__iso_volatile_load64, __iso_volatile_store64) +# define tsan_load(ptr) (sizeof(*(ptr)) == 8 ? __iso_volatile_load64(ptr) \ + : __iso_volatile_load32(ptr)) +# define tsan_store(ptr, val) (sizeof(*(ptr)) == 8 ? __iso_volatile_store64((ptr), (val)) \ + : __iso_volatile_store32((ptr), (val))) +# else +# define tsan_load(ptr) __iso_volatile_load32(ptr) +# define tsan_store(ptr, val) __iso_volatile_store32((ptr), (val)) +# endif +# else +# define tsan_load(ptr) (*(ptr)) +# define tsan_store(ptr, val) (*(ptr) = (val)) +# endif +# pragma intrinsic(_InterlockedExchangeAdd) +# ifdef _WIN64 +# pragma intrinsic(_InterlockedExchangeAdd64) +# define tsan_counter(ptr) (sizeof(*(ptr)) == 8 ? _InterlockedExchangeAdd64((ptr), 1) \ + : _InterlockedExchangeAdd((ptr), 1)) +# define tsan_decr(ptr) (sizeof(*(ptr)) == 8 ? _InterlockedExchangeAdd64((ptr), -1) \ + : _InterlockedExchangeAdd((ptr), -1)) +# else +# define tsan_counter(ptr) _InterlockedExchangeAdd((ptr), 1) +# define tsan_decr(ptr) _InterlockedExchangeAdd((ptr), -1) +# endif +# if !defined(_ISO_VOLATILE) +# define tsan_ld_acq(ptr) (*(ptr)) +# define tsan_st_rel(ptr, val) (*(ptr) = (val)) +# endif + +#endif + +#ifndef TSAN_QUALIFIER + +# define TSAN_QUALIFIER volatile +# define tsan_load(ptr) (*(ptr)) +# define tsan_store(ptr, val) (*(ptr) = (val)) +# define tsan_counter(ptr) ((*(ptr))++) +# define tsan_decr(ptr) ((*(ptr))--) +/* + * Lack of tsan_ld_acq and tsan_ld_rel means that compiler support is not + * sophisticated enough to support them. Code that relies on them should be + * protected with #ifdef tsan_ld_acq with locked fallback. + */ + +#endif diff --git a/include/internal/unicode.h b/include/internal/unicode.h new file mode 100644 index 00000000..a6de8352 --- /dev/null +++ b/include/internal/unicode.h @@ -0,0 +1,31 @@ +/* + * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_INTERNAL_UNICODE_H +# define OSSL_INTERNAL_UNICODE_H +# pragma once + +typedef enum { + SURROGATE_MIN = 0xd800UL, + SURROGATE_MAX = 0xdfffUL, + UNICODE_MAX = 0x10ffffUL, + UNICODE_LIMIT +} UNICODE_CONSTANTS; + +static ossl_unused ossl_inline int is_unicode_surrogate(unsigned long value) +{ + return value >= SURROGATE_MIN && value <= SURROGATE_MAX; +} + +static ossl_unused ossl_inline int is_unicode_valid(unsigned long value) +{ + return value <= UNICODE_MAX && !is_unicode_surrogate(value); +} + +#endif |