From 382490ea484b0ed3d4911146108004dd755813f0 Mon Sep 17 00:00:00 2001 From: K1 Date: Thu, 10 Feb 2022 02:30:25 +0800 Subject: [PATCH 01/66] Add define guards to avoid multi-inclusion This header files are included by multiple other headers. It's better to add define guards to prevent multi-inclusion. Adhere to the coding style, all preprocessor directives inside the guards gain a space. Signed-off-by: Weiguo Li Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale Reviewed-by: Matthias St. Pierre (Merged from https://github.com/openssl/openssl/pull/17666) --- include/crypto/md32_common.h | 96 +++++++------ include/internal/der.h | 76 +++++----- include/internal/tsan_assist.h | 135 +++++++++--------- .../include/prov/ciphercommon.h | 82 ++++++----- .../include/prov/ciphercommon_aead.h | 12 +- .../include/prov/ciphercommon_ccm.h | 12 +- .../include/prov/ciphercommon_gcm.h | 22 +-- 7 files changed, 237 insertions(+), 198 deletions(-) diff --git a/include/crypto/md32_common.h b/include/crypto/md32_common.h index 2c750af36..98543b896 100644 --- a/include/crypto/md32_common.h +++ b/include/crypto/md32_common.h @@ -63,63 +63,67 @@ * #define HASH_BLOCK_DATA_ORDER md5_block_data_order */ -#include +#ifndef OSSL_CRYPTO_MD32_COMMON_H +# define OSSL_CRYPTO_MD32_COMMON_H +# pragma once -#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) -# error "DATA_ORDER must be defined!" -#endif +# include -#ifndef HASH_CBLOCK -# error "HASH_CBLOCK must be defined!" -#endif -#ifndef HASH_LONG -# error "HASH_LONG must be defined!" -#endif -#ifndef HASH_CTX -# error "HASH_CTX must be defined!" -#endif +# if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) +# error "DATA_ORDER must be defined!" +# endif -#ifndef HASH_UPDATE -# error "HASH_UPDATE must be defined!" -#endif -#ifndef HASH_TRANSFORM -# error "HASH_TRANSFORM must be defined!" -#endif -#ifndef HASH_FINAL -# error "HASH_FINAL must be defined!" -#endif +# ifndef HASH_CBLOCK +# error "HASH_CBLOCK must be defined!" +# endif +# ifndef HASH_LONG +# error "HASH_LONG must be defined!" +# endif +# ifndef HASH_CTX +# error "HASH_CTX must be defined!" +# endif -#ifndef HASH_BLOCK_DATA_ORDER -# error "HASH_BLOCK_DATA_ORDER must be defined!" -#endif +# ifndef HASH_UPDATE +# error "HASH_UPDATE must be defined!" +# endif +# ifndef HASH_TRANSFORM +# error "HASH_TRANSFORM must be defined!" +# endif +# ifndef HASH_FINAL +# error "HASH_FINAL must be defined!" +# endif + +# ifndef HASH_BLOCK_DATA_ORDER +# error "HASH_BLOCK_DATA_ORDER must be defined!" +# endif -#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) +# define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) -#if defined(DATA_ORDER_IS_BIG_ENDIAN) +# if defined(DATA_ORDER_IS_BIG_ENDIAN) -# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ +# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ l|=(((unsigned long)(*((c)++)))<<16), \ l|=(((unsigned long)(*((c)++)))<< 8), \ l|=(((unsigned long)(*((c)++))) ) ) -# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ +# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ *((c)++)=(unsigned char)(((l)>>16)&0xff), \ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ *((c)++)=(unsigned char)(((l) )&0xff), \ l) -#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) +# elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) -# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ +# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ l|=(((unsigned long)(*((c)++)))<< 8), \ l|=(((unsigned long)(*((c)++)))<<16), \ l|=(((unsigned long)(*((c)++)))<<24) ) -# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ +# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ *((c)++)=(unsigned char)(((l)>>16)&0xff), \ *((c)++)=(unsigned char)(((l)>>24)&0xff), \ l) -#endif +# endif /* * Time for some action :-) @@ -204,30 +208,30 @@ int HASH_FINAL(unsigned char *md, HASH_CTX *c) memset(p + n, 0, HASH_CBLOCK - 8 - n); p += HASH_CBLOCK - 8; -#if defined(DATA_ORDER_IS_BIG_ENDIAN) +# if defined(DATA_ORDER_IS_BIG_ENDIAN) (void)HOST_l2c(c->Nh, p); (void)HOST_l2c(c->Nl, p); -#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) +# elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) (void)HOST_l2c(c->Nl, p); (void)HOST_l2c(c->Nh, p); -#endif +# endif p -= HASH_CBLOCK; HASH_BLOCK_DATA_ORDER(c, p, 1); c->num = 0; OPENSSL_cleanse(p, HASH_CBLOCK); -#ifndef HASH_MAKE_STRING -# error "HASH_MAKE_STRING must be defined!" -#else +# ifndef HASH_MAKE_STRING +# error "HASH_MAKE_STRING must be defined!" +# else HASH_MAKE_STRING(c, md); -#endif +# endif return 1; } -#ifndef MD32_REG_T -# if defined(__alpha) || defined(__mips) -# define MD32_REG_T long +# ifndef MD32_REG_T +# if defined(__alpha) || defined(__mips) +# define MD32_REG_T long /* * This comment was originally written for MD5, which is why it * discusses A-D. But it basically applies to all 32-bit digests, @@ -244,13 +248,15 @@ int HASH_FINAL(unsigned char *md, HASH_CTX *c) * Well, to be honest it should say that this *prevents* * performance degradation. */ -# else +# else /* * Above is not absolute and there are LP64 compilers that * generate better code if MD32_REG_T is defined int. The above * pre-processor condition reflects the circumstances under which * the conclusion was made and is subject to further extension. */ -# define MD32_REG_T int +# define MD32_REG_T int +# endif # endif + #endif diff --git a/include/internal/der.h b/include/internal/der.h index a3e56d0dc..3dfecd58a 100644 --- a/include/internal/der.h +++ b/include/internal/der.h @@ -7,8 +7,12 @@ * https://www.openssl.org/source/license.html */ -#include -#include "internal/packet.h" +#ifndef OSSL_INTERNAL_DER_H +# define OSSL_INTERNAL_DER_H +# pragma once + +# include +# include "internal/packet.h" /* * NOTE: X.690 numbers the identifier octet bits 1 to 8. @@ -22,42 +26,42 @@ * 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 +# 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 +# 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 +# define DER_C_UNIVERSAL 0x00 +# define DER_C_APPLICATION 0x40 +# define DER_C_CONTEXT 0x80 +# define DER_C_PRIVATE 0xC0 /* * Run-time constructors. @@ -67,7 +71,7 @@ */ /* This can be used for all items that don't have a context */ -#define DER_NO_CONTEXT -1 +# define DER_NO_CONTEXT -1 int ossl_DER_w_precompiled(WPACKET *pkt, int tag, const unsigned char *precompiled, @@ -86,3 +90,5 @@ int ossl_DER_w_octet_string_uint32(WPACKET *pkt, int tag, uint32_t value); */ int ossl_DER_w_begin_sequence(WPACKET *pkt, int tag); int ossl_DER_w_end_sequence(WPACKET *pkt, int tag); + +#endif diff --git a/include/internal/tsan_assist.h b/include/internal/tsan_assist.h index 60ecbd5f0..a840df0b2 100644 --- a/include/internal/tsan_assist.h +++ b/include/internal/tsan_assist.h @@ -47,35 +47,37 @@ * can use TSAN_QUALIFIER in cast specifically when it has to count. */ -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \ +#ifndef OSSL_INTERNAL_TSAN_ASSIST_H +# define OSSL_INTERNAL_TSAN_ASSIST_H +# pragma once + +# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \ && !defined(__STDC_NO_ATOMICS__) -# include +# include -# if defined(ATOMIC_POINTER_LOCK_FREE) \ +# 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 +# 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_add(ptr, n) atomic_fetch_add_explicit((ptr), (n), 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) +# elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) -# if defined(__GCC_ATOMIC_POINTER_LOCK_FREE) \ +# 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 +# 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_add(ptr, n) __atomic_fetch_add((ptr), (n), __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 \ +# 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))) /* @@ -89,62 +91,63 @@ * 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) \ +# 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)) \ +# 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) __iso_volatile_load32(ptr) -# define tsan_store(ptr, val) __iso_volatile_store32((ptr), (val)) +# define tsan_load(ptr) (*(ptr)) +# define tsan_store(ptr, val) (*(ptr) = (val)) +# endif +# pragma intrinsic(_InterlockedExchangeAdd) +# ifdef _WIN64 +# pragma intrinsic(_InterlockedExchangeAdd64) +# define tsan_add(ptr, n) (sizeof(*(ptr)) == 8 ? _InterlockedExchangeAdd64((ptr), (n)) \ + : _InterlockedExchangeAdd((ptr), (n))) +# else +# define tsan_add(ptr, n) _InterlockedExchangeAdd((ptr), (n)) +# endif +# if !defined(_ISO_VOLATILE) +# define tsan_ld_acq(ptr) (*(ptr)) +# define tsan_st_rel(ptr, val) (*(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 +# endif -#ifndef TSAN_QUALIFIER +# ifndef TSAN_QUALIFIER -# ifdef OPENSSL_THREADS -# define TSAN_QUALIFIER volatile -# define TSAN_REQUIRES_LOCKING -# else /* OPENSSL_THREADS */ -# define TSAN_QUALIFIER -# endif /* OPENSSL_THREADS */ +# ifdef OPENSSL_THREADS +# define TSAN_QUALIFIER volatile +# define TSAN_REQUIRES_LOCKING +# else /* OPENSSL_THREADS */ +# define TSAN_QUALIFIER +# endif /* OPENSSL_THREADS */ -# define tsan_load(ptr) (*(ptr)) -# define tsan_store(ptr, val) (*(ptr) = (val)) -# define tsan_counter(ptr) ((*(ptr))++) -# define tsan_decr(ptr) ((*(ptr))--) +# define tsan_load(ptr) (*(ptr)) +# define tsan_store(ptr, val) (*(ptr) = (val)) +# define tsan_add(ptr, n) (*(ptr) += (n)) /* * 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 + +# define tsan_counter(ptr) tsan_add((ptr), 1) +# define tsan_decr(ptr) tsan_add((ptr), -1) + #endif diff --git a/providers/implementations/include/prov/ciphercommon.h b/providers/implementations/include/prov/ciphercommon.h index 91c4c914b..727c00612 100644 --- a/providers/implementations/include/prov/ciphercommon.h +++ b/providers/implementations/include/prov/ciphercommon.h @@ -7,23 +7,27 @@ * https://www.openssl.org/source/license.html */ -#include -#include -#include -#include -#include "internal/cryptlib.h" -#include "crypto/modes.h" +#ifndef OSSL_PROV_CIPHERCOMMON_H +# define OSSL_PROV_CIPHERCOMMON_H +# pragma once -#define MAXCHUNK ((size_t)1 << (sizeof(long) * 8 - 2)) -#define MAXBITCHUNK ((size_t)1 << (sizeof(size_t) * 8 - 4)) +# include +# include +# include +# include +# include "internal/cryptlib.h" +# include "crypto/modes.h" -#define GENERIC_BLOCK_SIZE 16 -#define IV_STATE_UNINITIALISED 0 /* initial state is not initialized */ -#define IV_STATE_BUFFERED 1 /* iv has been copied to the iv buffer */ -#define IV_STATE_COPIED 2 /* iv has been copied from the iv buffer */ -#define IV_STATE_FINISHED 3 /* the iv has been used - so don't reuse it */ +# define MAXCHUNK ((size_t)1 << (sizeof(long) * 8 - 2)) +# define MAXBITCHUNK ((size_t)1 << (sizeof(size_t) * 8 - 4)) -#define PROV_CIPHER_FUNC(type, name, args) typedef type (* OSSL_##name##_fn)args +# define GENERIC_BLOCK_SIZE 16 +# define IV_STATE_UNINITIALISED 0 /* initial state is not initialized */ +# define IV_STATE_BUFFERED 1 /* iv has been copied to the iv buffer */ +# define IV_STATE_COPIED 2 /* iv has been copied from the iv buffer */ +# define IV_STATE_FINISHED 3 /* the iv has been used - so don't reuse it */ + +# define PROV_CIPHER_FUNC(type, name, args) typedef type (* OSSL_##name##_fn)args typedef struct prov_cipher_hw_st PROV_CIPHER_HW; typedef struct prov_cipher_ctx_st PROV_CIPHER_CTX; @@ -32,14 +36,14 @@ typedef int (PROV_CIPHER_HW_FN)(PROV_CIPHER_CTX *dat, unsigned char *out, const unsigned char *in, size_t len); /* Internal flags that can be queried */ -#define PROV_CIPHER_FLAG_AEAD 0x0001 -#define PROV_CIPHER_FLAG_CUSTOM_IV 0x0002 -#define PROV_CIPHER_FLAG_CTS 0x0004 -#define PROV_CIPHER_FLAG_TLS1_MULTIBLOCK 0x0008 -#define PROV_CIPHER_FLAG_RAND_KEY 0x0010 +# define PROV_CIPHER_FLAG_AEAD 0x0001 +# define PROV_CIPHER_FLAG_CUSTOM_IV 0x0002 +# define PROV_CIPHER_FLAG_CTS 0x0004 +# define PROV_CIPHER_FLAG_TLS1_MULTIBLOCK 0x0008 +# define PROV_CIPHER_FLAG_RAND_KEY 0x0010 /* Internal flags that are only used within the provider */ -#define PROV_CIPHER_FLAG_VARIABLE_LENGTH 0x0100 -#define PROV_CIPHER_FLAG_INVERSE_CIPHER 0x0200 +# define PROV_CIPHER_FLAG_VARIABLE_LENGTH 0x0100 +# define PROV_CIPHER_FLAG_INVERSE_CIPHER 0x0200 struct prov_cipher_ctx_st { block128_f block; @@ -125,7 +129,7 @@ void ossl_cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits, uint64_t flags, const PROV_CIPHER_HW *hw, void *provctx); -#define IMPLEMENT_generic_cipher_func(alg, UCALG, lcmode, UCMODE, flags, kbits,\ +# define IMPLEMENT_generic_cipher_func(alg, UCALG, lcmode, UCMODE, flags, kbits,\ blkbits, ivbits, typ) \ const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_functions[] = { \ { OSSL_FUNC_CIPHER_NEWCTX, \ @@ -152,7 +156,7 @@ const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_functions[] = { \ { 0, NULL } \ }; -#define IMPLEMENT_var_keylen_cipher_func(alg, UCALG, lcmode, UCMODE, flags, \ +# define IMPLEMENT_var_keylen_cipher_func(alg, UCALG, lcmode, UCMODE, flags, \ kbits, blkbits, ivbits, typ) \ const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_functions[] = { \ { OSSL_FUNC_CIPHER_NEWCTX, \ @@ -180,7 +184,7 @@ const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_functions[] = { \ }; -#define IMPLEMENT_generic_cipher_genfn(alg, UCALG, lcmode, UCMODE, flags, \ +# define IMPLEMENT_generic_cipher_genfn(alg, UCALG, lcmode, UCMODE, flags, \ kbits, blkbits, ivbits, typ) \ static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \ static int alg##_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \ @@ -202,14 +206,14 @@ static void * alg##_##kbits##_##lcmode##_newctx(void *provctx) \ return ctx; \ } \ -#define IMPLEMENT_generic_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \ +# define IMPLEMENT_generic_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \ blkbits, ivbits, typ) \ IMPLEMENT_generic_cipher_genfn(alg, UCALG, lcmode, UCMODE, flags, kbits, \ blkbits, ivbits, typ) \ IMPLEMENT_generic_cipher_func(alg, UCALG, lcmode, UCMODE, flags, kbits, \ blkbits, ivbits, typ) -#define IMPLEMENT_var_keylen_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \ +# define IMPLEMENT_var_keylen_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \ blkbits, ivbits, typ) \ IMPLEMENT_generic_cipher_genfn(alg, UCALG, lcmode, UCMODE, flags, kbits, \ blkbits, ivbits, typ) \ @@ -227,11 +231,11 @@ PROV_CIPHER_HW_FN ossl_cipher_hw_chunked_cbc; PROV_CIPHER_HW_FN ossl_cipher_hw_chunked_cfb8; PROV_CIPHER_HW_FN ossl_cipher_hw_chunked_cfb128; PROV_CIPHER_HW_FN ossl_cipher_hw_chunked_ofb128; -#define ossl_cipher_hw_chunked_ecb ossl_cipher_hw_generic_ecb -#define ossl_cipher_hw_chunked_ctr ossl_cipher_hw_generic_ctr -#define ossl_cipher_hw_chunked_cfb1 ossl_cipher_hw_generic_cfb1 +# define ossl_cipher_hw_chunked_ecb ossl_cipher_hw_generic_ecb +# define ossl_cipher_hw_chunked_ctr ossl_cipher_hw_generic_ctr +# define ossl_cipher_hw_chunked_cfb1 ossl_cipher_hw_generic_cfb1 -#define IMPLEMENT_CIPHER_HW_OFB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ +# define IMPLEMENT_CIPHER_HW_OFB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ unsigned char *out, \ const unsigned char *in, size_t len) \ @@ -252,7 +256,7 @@ static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ return 1; \ } -#define IMPLEMENT_CIPHER_HW_ECB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ +# define IMPLEMENT_CIPHER_HW_ECB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ unsigned char *out, \ const unsigned char *in, size_t len) \ @@ -267,7 +271,7 @@ static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ return 1; \ } -#define IMPLEMENT_CIPHER_HW_CBC(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ +# define IMPLEMENT_CIPHER_HW_CBC(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ unsigned char *out, \ const unsigned char *in, size_t len) \ @@ -285,7 +289,7 @@ static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ return 1; \ } -#define IMPLEMENT_CIPHER_HW_CFB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ +# define IMPLEMENT_CIPHER_HW_CFB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ unsigned char *out, \ const unsigned char *in, size_t len) \ @@ -309,7 +313,7 @@ static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ return 1; \ } -#define IMPLEMENT_CIPHER_HW_COPYCTX(name, CTX_TYPE) \ +# define IMPLEMENT_CIPHER_HW_COPYCTX(name, CTX_TYPE) \ static void name(PROV_CIPHER_CTX *dst, const PROV_CIPHER_CTX *src) \ { \ CTX_TYPE *sctx = (CTX_TYPE *)src; \ @@ -319,7 +323,7 @@ static void name(PROV_CIPHER_CTX *dst, const PROV_CIPHER_CTX *src) \ dst->ks = &dctx->ks.ks; \ } -#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(name) \ +# define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(name) \ static const OSSL_PARAM name##_known_gettable_ctx_params[] = { \ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), \ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), \ @@ -328,7 +332,7 @@ static const OSSL_PARAM name##_known_gettable_ctx_params[] = { \ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0), \ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_UPDATED_IV, NULL, 0), -#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(name) \ +# define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(name) \ OSSL_PARAM_END \ }; \ const OSSL_PARAM * name##_gettable_ctx_params(ossl_unused void *cctx, \ @@ -337,11 +341,11 @@ const OSSL_PARAM * name##_gettable_ctx_params(ossl_unused void *cctx, \ return name##_known_gettable_ctx_params; \ } -#define CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(name) \ +# define CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(name) \ static const OSSL_PARAM name##_known_settable_ctx_params[] = { \ OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL), \ OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL), -#define CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(name) \ +# define CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(name) \ OSSL_PARAM_END \ }; \ const OSSL_PARAM * name##_settable_ctx_params(ossl_unused void *cctx, \ @@ -359,3 +363,5 @@ size_t ossl_cipher_fillblock(unsigned char *buf, size_t *buflen, int ossl_cipher_trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize, const unsigned char **in, size_t *inlen); + +#endif diff --git a/providers/implementations/include/prov/ciphercommon_aead.h b/providers/implementations/include/prov/ciphercommon_aead.h index 1d017175d..e64f004be 100644 --- a/providers/implementations/include/prov/ciphercommon_aead.h +++ b/providers/implementations/include/prov/ciphercommon_aead.h @@ -7,11 +7,15 @@ * https://www.openssl.org/source/license.html */ -#define UNINITIALISED_SIZET ((size_t)-1) +#ifndef OSSL_PROV_CIPHERCOMMON_AEAD_H +# define OSSL_PROV_CIPHERCOMMON_AEAD_H +# pragma once -#define AEAD_FLAGS (PROV_CIPHER_FLAG_AEAD | PROV_CIPHER_FLAG_CUSTOM_IV) +# define UNINITIALISED_SIZET ((size_t)-1) -#define IMPLEMENT_aead_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits) \ +# define AEAD_FLAGS (PROV_CIPHER_FLAG_AEAD | PROV_CIPHER_FLAG_CUSTOM_IV) + +# define IMPLEMENT_aead_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits) \ static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lc##_get_params; \ static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \ { \ @@ -45,3 +49,5 @@ const OSSL_DISPATCH ossl_##alg##kbits##lc##_functions[] = { \ (void (*)(void))ossl_cipher_aead_settable_ctx_params }, \ { 0, NULL } \ } + +#endif diff --git a/providers/implementations/include/prov/ciphercommon_ccm.h b/providers/implementations/include/prov/ciphercommon_ccm.h index 4c184b395..93c3d6383 100644 --- a/providers/implementations/include/prov/ciphercommon_ccm.h +++ b/providers/implementations/include/prov/ciphercommon_ccm.h @@ -7,11 +7,15 @@ * https://www.openssl.org/source/license.html */ -#include "ciphercommon_aead.h" +#ifndef OSSL_PROV_CIPHERCOMMON_CCM_H +# define OSSL_PROV_CIPHERCOMMON_CCM_H +# pragma once + +# include "ciphercommon_aead.h" typedef struct prov_ccm_hw_st PROV_CCM_HW; -#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) +# if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) /*- * KMAC-AES parameter block - begin * (see z/Architecture Principles of Operation >= SA22-7832-08) @@ -24,7 +28,7 @@ typedef struct S390X_kmac_params_st { unsigned char k[32]; } S390X_KMAC_PARAMS; /* KMAC-AES parameter block - end */ -#endif +# endif /* Base structure that is shared by AES & ARIA for CCM MODE */ typedef struct prov_ccm_st { @@ -98,3 +102,5 @@ int ossl_ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in, int ossl_ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in, unsigned char *out, size_t len, unsigned char *expected_tag, size_t taglen); + +#endif diff --git a/providers/implementations/include/prov/ciphercommon_gcm.h b/providers/implementations/include/prov/ciphercommon_gcm.h index 7c4a548f9..801a89b29 100644 --- a/providers/implementations/include/prov/ciphercommon_gcm.h +++ b/providers/implementations/include/prov/ciphercommon_gcm.h @@ -8,16 +8,20 @@ * https://www.openssl.org/source/license.html */ -#include -#include "ciphercommon_aead.h" +#ifndef OSSL_PROV_CIPHERCOMMON_GCM_H +# define OSSL_PROV_CIPHERCOMMON_GCM_H +# pragma once + +# include +# include "ciphercommon_aead.h" typedef struct prov_gcm_hw_st PROV_GCM_HW; -#define GCM_IV_DEFAULT_SIZE 12 /* IV's for AES_GCM should normally be 12 bytes */ -#define GCM_IV_MAX_SIZE (1024 / 8) -#define GCM_TAG_MAX_SIZE 16 +# define GCM_IV_DEFAULT_SIZE 12 /* IV's for AES_GCM should normally be 12 bytes */ +# define GCM_IV_MAX_SIZE (1024 / 8) +# define GCM_TAG_MAX_SIZE 16 -#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) +# if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) /*- * KMA-GCM-AES parameter block - begin * (see z/Architecture Principles of Operation >= SA22-7832-11) @@ -42,7 +46,7 @@ typedef struct S390X_kma_params_st { unsigned char k[32]; /* key */ } S390X_KMA_PARAMS; -#endif +# endif typedef struct prov_gcm_ctx_st { unsigned int mode; /* The mode that we are using */ @@ -121,9 +125,11 @@ int ossl_gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len, int ossl_gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in, size_t len, unsigned char *out); -#define GCM_HW_SET_KEY_CTR_FN(ks, fn_set_enc_key, fn_block, fn_ctr) \ +# define GCM_HW_SET_KEY_CTR_FN(ks, fn_set_enc_key, fn_block, fn_ctr) \ ctx->ks = ks; \ fn_set_enc_key(key, keylen * 8, ks); \ CRYPTO_gcm128_init(&ctx->gcm, ks, (block128_f)fn_block); \ ctx->ctr = (ctr128_f)fn_ctr; \ ctx->key_set = 1; + +#endif From 59640e080a173981240220c9a416c4a6809a4cbb Mon Sep 17 00:00:00 2001 From: K1 Date: Thu, 7 Mar 2024 21:19:31 +0800 Subject: [PATCH 02/66] Limit the size of various MAXCHUNK definitions The current code has issues when sizeof(long) <> sizeof(size_t). The two types are assumed to be interchangeable and them being different will cause crashes and endless loops. This fix limits the maximum chunk size for many of the symmetric ciphers to 2^30 bytes. This chunk size limits the amount of data that will be encrypted/decrypted in one lump. The code internally handles block of data later than the chunk limit, so this will present no difference to the caller. Any loss of efficiency due to limiting the chunking to 1Gbyte rather than more should be insignificant. Fixes Coverity issues: 1508498, 1508500 - 1508505, 1508507 - 1508527, 1508529 - 1508533, 1508535 - 1508537, 1508539, 1508541 - 1508549, 1508551 - 1508569 & 1508571 - 1508582. Reviewed-by: Dmitry Belyavskiy Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/18997) --- include/crypto/evp.h | 2 +- providers/implementations/include/prov/ciphercommon.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/crypto/evp.h b/include/crypto/evp.h index 206ac2633..14b1c91e5 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -365,7 +365,7 @@ static int cname##_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const uns return 1;\ } -#define EVP_MAXCHUNK ((size_t)1<<(sizeof(long)*8-2)) +#define EVP_MAXCHUNK ((size_t)1 << 30) #define BLOCK_CIPHER_func_ofb(cname, cprefix, cbits, kstruct, ksched) \ static int cname##_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \ diff --git a/providers/implementations/include/prov/ciphercommon.h b/providers/implementations/include/prov/ciphercommon.h index 727c00612..efea70615 100644 --- a/providers/implementations/include/prov/ciphercommon.h +++ b/providers/implementations/include/prov/ciphercommon.h @@ -18,7 +18,7 @@ # include "internal/cryptlib.h" # include "crypto/modes.h" -# define MAXCHUNK ((size_t)1 << (sizeof(long) * 8 - 2)) +# define MAXCHUNK ((size_t)1 << 30) # define MAXBITCHUNK ((size_t)1 << (sizeof(size_t) * 8 - 4)) # define GENERIC_BLOCK_SIZE 16 From d7083542d1e95c5d080efd2d9b1d10c3a0ea5056 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 11:50:54 +0800 Subject: [PATCH 03/66] poly1305-ppc.pl: Fix vector register clobbering Fixes CVE-2023-6129 The POLY1305 MAC (message authentication code) implementation in OpenSSL for PowerPC CPUs saves the the contents of vector registers in different order than they are restored. Thus the contents of some of these vector registers is corrupted when returning to the caller. The vulnerable code is used only on newer PowerPC processors supporting the PowerISA 2.07 instructions. Reviewed-by: Matt Caswell Reviewed-by: Richard Levitte Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23200) --- crypto/poly1305/asm/poly1305-ppc.pl | 42 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/crypto/poly1305/asm/poly1305-ppc.pl b/crypto/poly1305/asm/poly1305-ppc.pl index 9f86134d9..2e601bb9c 100755 --- a/crypto/poly1305/asm/poly1305-ppc.pl +++ b/crypto/poly1305/asm/poly1305-ppc.pl @@ -744,7 +744,7 @@ my $LOCALS= 6*$SIZE_T; my $VSXFRAME = $LOCALS + 6*$SIZE_T; $VSXFRAME += 128; # local variables - $VSXFRAME += 13*16; # v20-v31 offload + $VSXFRAME += 12*16; # v20-v31 offload my $BIG_ENDIAN = ($flavour !~ /le/) ? 4 : 0; @@ -919,12 +919,12 @@ addi r11,r11,32 stvx v22,r10,$sp addi r10,r10,32 - stvx v23,r10,$sp - addi r10,r10,32 - stvx v24,r11,$sp + stvx v23,r11,$sp addi r11,r11,32 - stvx v25,r10,$sp + stvx v24,r10,$sp addi r10,r10,32 + stvx v25,r11,$sp + addi r11,r11,32 stvx v26,r10,$sp addi r10,r10,32 stvx v27,r11,$sp @@ -1153,12 +1153,12 @@ addi r11,r11,32 stvx v22,r10,$sp addi r10,r10,32 - stvx v23,r10,$sp - addi r10,r10,32 - stvx v24,r11,$sp + stvx v23,r11,$sp addi r11,r11,32 - stvx v25,r10,$sp + stvx v24,r10,$sp addi r10,r10,32 + stvx v25,r11,$sp + addi r11,r11,32 stvx v26,r10,$sp addi r10,r10,32 stvx v27,r11,$sp @@ -1899,26 +1899,26 @@ mtspr 256,r12 # restore vrsave lvx v20,r10,$sp addi r10,r10,32 - lvx v21,r10,$sp - addi r10,r10,32 - lvx v22,r11,$sp + lvx v21,r11,$sp addi r11,r11,32 - lvx v23,r10,$sp + lvx v22,r10,$sp addi r10,r10,32 - lvx v24,r11,$sp + lvx v23,r11,$sp addi r11,r11,32 - lvx v25,r10,$sp + lvx v24,r10,$sp addi r10,r10,32 - lvx v26,r11,$sp + lvx v25,r11,$sp addi r11,r11,32 - lvx v27,r10,$sp + lvx v26,r10,$sp addi r10,r10,32 - lvx v28,r11,$sp + lvx v27,r11,$sp addi r11,r11,32 - lvx v29,r10,$sp + lvx v28,r10,$sp addi r10,r10,32 - lvx v30,r11,$sp - lvx v31,r10,$sp + lvx v29,r11,$sp + addi r11,r11,32 + lvx v30,r10,$sp + lvx v31,r11,$sp $POP r27,`$VSXFRAME-$SIZE_T*5`($sp) $POP r28,`$VSXFRAME-$SIZE_T*4`($sp) $POP r29,`$VSXFRAME-$SIZE_T*3`($sp) From a37675e24c029db0f5ef5e09ad2150785c381b54 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 11:51:57 +0800 Subject: [PATCH 04/66] Add CHANGES entry for CVE-2023-6129 --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index fb1e52f1a..9a1c3e5dc 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,8 @@ Changes between 8.4.0 and 8.5.0 [xx XXX xxxx] + *) 修复CVE-2023-6129 + *) 增加SM2两方门限解密算法 *) 增加SM2两方门限签名算法 [with work originated from FullyRobert] From 81cd979e4edd54498742f45453d7616a32e5a4c1 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 14:55:46 +0800 Subject: [PATCH 05/66] test_pkey_check: Positive testcase for private key with unknown parameters Reviewed-by: Shane Lontis Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/18099) --- test/recipes/91-test_pkey_check.t | 41 ++++++++++++++----- .../91-test_pkey_check_data/dhpkey.pem | 14 +++++++ 2 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 test/recipes/91-test_pkey_check_data/dhpkey.pem diff --git a/test/recipes/91-test_pkey_check.t b/test/recipes/91-test_pkey_check.t index a415fee24..354e33575 100644 --- a/test/recipes/91-test_pkey_check.t +++ b/test/recipes/91-test_pkey_check.t @@ -14,21 +14,30 @@ use File::Spec; use OpenSSL::Test qw/:DEFAULT data_file/; use OpenSSL::Test::Utils; -sub check_key { +sub pkey_check { my $f = shift; return run(app(['openssl', 'pkey', '-check', '-text', '-in', $f])); } -sub check_key_notok { +sub check_key { my $f = shift; - my $str = "$f should fail validation"; + my $should_fail = shift; + my $str; + + + $str = "$f should fail validation" if $should_fail; + $str = "$f should pass validation" unless $should_fail; $f = data_file($f); if ( -s $f ) { - ok(!check_key($f), $str); + if ($should_fail) { + ok(!pkey_check($f), $str); + } else { + ok(pkey_check($f), $str); + } } else { fail("Missing file $f"); } @@ -36,26 +45,36 @@ sub check_key_notok { setup("test_pkey_check"); -my @tests = (); +my @negative_tests = (); -push(@tests, ( +push(@negative_tests, ( # For EC keys the range for the secret scalar `k` is `1 <= k <= n-1` "ec_p256_bad_0.pem", # `k` set to `n` (equivalent to `0 mod n`, invalid) "ec_p256_bad_1.pem", # `k` set to `n+1` (equivalent to `1 mod n`, invalid) )) unless disabled("ec"); -push(@tests, ( +push(@negative_tests, ( # For SM2 keys the range for the secret scalar `k` is `1 <= k < n-1` "sm2_bad_neg1.pem", # `k` set to `n-1` (invalid, because SM2 range) "sm2_bad_0.pem", # `k` set to `n` (equivalent to `0 mod n`, invalid) "sm2_bad_1.pem", # `k` set to `n+1` (equivalent to `1 mod n`, invalid) )) unless disabled("sm2"); +my @positive_tests = (); + +push(@positive_tests, ( + "dhpkey.pem" + )) unless disabled("dh"); + plan skip_all => "No tests within the current enabled feature set" - unless @tests; + unless @negative_tests && @positive_tests; -plan tests => scalar(@tests); +plan tests => scalar(@negative_tests) + scalar(@positive_tests); + +foreach my $t (@negative_tests) { + check_key($t, 1); +} -foreach my $t (@tests) { - check_key_notok($t); +foreach my $t (@positive_tests) { + check_key($t, 0); } diff --git a/test/recipes/91-test_pkey_check_data/dhpkey.pem b/test/recipes/91-test_pkey_check_data/dhpkey.pem new file mode 100644 index 000000000..aa5b8630a --- /dev/null +++ b/test/recipes/91-test_pkey_check_data/dhpkey.pem @@ -0,0 +1,14 @@ +-----BEGIN PRIVATE KEY----- +MIICJgIBADCCARcGCSqGSIb3DQEDATCCAQgCggEBAMwWCRizXuSpEcD1rlHABvnQ +NzZarWoOCGfuYe2NzM6b0BiR13l7zrcBocQLE401xxLUn6qkFfFMJOP3x6tbDx7w +1DwsHjplqVSW8sLDipf37940aLjvcjhJ0ZSDOwkpUeO2WSJLZdNSxvygHG5bZ/e1 +V5c5BToWUzHsbx3It4EgddtRfgELgl0K6kY7YsxfeVKc+bNA40elhk8/gGr5xLko +0fUSk4xPIqbHEkKVuusYvaxXrBXUmFdCuY/dokhhrahp3CFSEzxMCKrS75Kq+6Jx +Xc4qJ1QsgHWxwO5C+KPRhWsePJ5zmGI/D++TAXKu70QgcQs8fnM61cXhUylnchsC +AQIEggEEAoIBAGj8dNturd5CiUbDmzc/zMuSW+wIZFtH0XTlhie6Xap8ybXs53Dd +vr2QwKbZpvbwpT+GrQM8K6lTYSW2AqeV29b23KstGGRDxyF9nrTM2a+la+m+YCuy +XG3AeildriXHViJHe9BnpvqsArkv2kIMLsXwsrvJsbUU3ENJUGyTehOglmoiESW1 +kVq3PoYTuls7ynRDnZAcFZidMJmOynU182klgqjxy0Md0X1cX0SXdYVBtai+iwH8 +kNKnbs2nn0Dfprau/OlmLFL4JpiagOWBJCwZafELpXzLor4t0m0t1Mzy/XkxtmKT +e6L4veD6kojaU7H8iCTjA6d7hPBWmXoslZI= +-----END PRIVATE KEY----- From bad48b7536772a3763fea993d4a9aa6e74a899ac Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 14:56:59 +0800 Subject: [PATCH 06/66] Add test for DSA pubkey without param import and check Reviewed-by: Paul Dale Reviewed-by: Matt Caswell --- test/recipes/91-test_pkey_check.t | 48 ++++++++++++++---- .../91-test_pkey_check_data/dsapub.pem | 12 +++++ .../dsapub_noparam.der | Bin 0 -> 108 bytes 3 files changed, 49 insertions(+), 11 deletions(-) create mode 100644 test/recipes/91-test_pkey_check_data/dsapub.pem create mode 100644 test/recipes/91-test_pkey_check_data/dsapub_noparam.der diff --git a/test/recipes/91-test_pkey_check.t b/test/recipes/91-test_pkey_check.t index 354e33575..c290b0ba7 100644 --- a/test/recipes/91-test_pkey_check.t +++ b/test/recipes/91-test_pkey_check.t @@ -11,19 +11,24 @@ use strict; use warnings; use File::Spec; -use OpenSSL::Test qw/:DEFAULT data_file/; +use OpenSSL::Test qw/:DEFAULT data_file with/; use OpenSSL::Test::Utils; sub pkey_check { my $f = shift; + my $pubcheck = shift; + my @checkopt = ('-check'); - return run(app(['openssl', 'pkey', '-check', '-text', + @checkopt = ('-pubcheck', '-pubin') if $pubcheck; + + return run(app(['openssl', 'pkey', @checkopt, '-text', '-in', $f])); } sub check_key { my $f = shift; my $should_fail = shift; + my $pubcheck = shift; my $str; @@ -33,11 +38,10 @@ sub check_key { $f = data_file($f); if ( -s $f ) { - if ($should_fail) { - ok(!pkey_check($f), $str); - } else { - ok(pkey_check($f), $str); - } + with({ exit_checker => sub { return shift == $should_fail; } }, + sub { + ok(pkey_check($f, $pubcheck), $str); + }); } else { fail("Missing file $f"); } @@ -66,15 +70,37 @@ push(@positive_tests, ( "dhpkey.pem" )) unless disabled("dh"); +my @negative_pubtests = (); + +push(@negative_pubtests, ( + "dsapub_noparam.der" + )) unless disabled("dsa"); + +my @positive_pubtests = (); + +push(@positive_pubtests, ( + "dsapub.pem" + )) unless disabled("dsa"); + plan skip_all => "No tests within the current enabled feature set" - unless @negative_tests && @positive_tests; + unless @negative_tests && @positive_tests + && @negative_pubtests && @positive_pubtests; -plan tests => scalar(@negative_tests) + scalar(@positive_tests); +plan tests => scalar(@negative_tests) + scalar(@positive_tests) + + scalar(@negative_pubtests) + scalar(@positive_pubtests); foreach my $t (@negative_tests) { - check_key($t, 1); + check_key($t, 1, 0); } foreach my $t (@positive_tests) { - check_key($t, 0); + check_key($t, 0, 0); +} + +foreach my $t (@negative_pubtests) { + check_key($t, 1, 1); +} + +foreach my $t (@positive_pubtests) { + check_key($t, 0, 1); } diff --git a/test/recipes/91-test_pkey_check_data/dsapub.pem b/test/recipes/91-test_pkey_check_data/dsapub.pem new file mode 100644 index 000000000..0ff4bd83e --- /dev/null +++ b/test/recipes/91-test_pkey_check_data/dsapub.pem @@ -0,0 +1,12 @@ +-----BEGIN PUBLIC KEY----- +MIIBvzCCATQGByqGSM44BAEwggEnAoGBAIjbXpOVVciVNuagg26annKkghIIZFI4 +4WdMomnV+I/oXyxHbZTBBBpW9xy/E1+yMjbp4GmX+VxyDj3WxUWxXllzL+miEkzD +9Xz638VzIBhjFbMvk1/N4kS4bKVUd9yk7HfvYzAdnRphk0WI+RoDiDrBNPPxSoQD +CEWgvwgsLIDhAh0A6dbz1IQpQwGF4+Ca28x6OO+UfJJv3ggeZ++fNwKBgQCA9XKV +lRrTY8ALBxS0KbZjpaIXuUj5nr3i1lIDyP3ISksDF0ekyLtn6eK9VijX6Pm65Np+ +4ic9Nr5WKLKhPaUSpLNRx1gDqo3sd92hYgiEUifzEuhLYfK/CsgFED+l2hDXtJUq +bISNSHVwI5lsyNXLu7HI1Fk8F5UO3LqsboFAngOBhAACgYATxFY89nEYcUhgHGgr +YDHhXBQfMKnTKYdvon4DN7WQ9ip+t4VUsLpTD1ZE9zrM2R/B04+8C6KGoViwyeER +kS4dxWOkX71x4X2DlNpYevcR53tNcTDqmMD7YKfDDmrb0lftMyfW8aESaiymVMys +DRjhKHBjdo0rZeSM8DAk3ctrXA== +-----END PUBLIC KEY----- diff --git a/test/recipes/91-test_pkey_check_data/dsapub_noparam.der b/test/recipes/91-test_pkey_check_data/dsapub_noparam.der new file mode 100644 index 0000000000000000000000000000000000000000..b8135f1ca94da914b6829421e0c13f6daa731862 GIT binary patch literal 108 zcmXpIGT>xm*J|@PXTieE%*wz71|F5F-Nv0Bz9(=Kufz literal 0 HcmV?d00001 From 20465d31ac353548af566d5d2326d9214744cefe Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 14:58:01 +0800 Subject: [PATCH 07/66] Limit the execution time of RSA public key check Fixes CVE-2023-6237 If a large and incorrect RSA public key is checked with EVP_PKEY_public_check() the computation could take very long time due to no limit being applied to the RSA public key size and unnecessarily high number of Miller-Rabin algorithm rounds used for non-primality check of the modulus. Now the keys larger than 16384 bits (OPENSSL_RSA_MAX_MODULUS_BITS) will fail the check with RSA_R_MODULUS_TOO_LARGE error reason. Also the number of Miller-Rabin rounds was set to 5. Reviewed-by: Neil Horman Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/23243) --- crypto/rsa/rsa_sp800_56b_check.c | 8 +++- test/recipes/91-test_pkey_check.t | 2 +- .../91-test_pkey_check_data/rsapub_17k.pem | 48 +++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 test/recipes/91-test_pkey_check_data/rsapub_17k.pem diff --git a/crypto/rsa/rsa_sp800_56b_check.c b/crypto/rsa/rsa_sp800_56b_check.c index fc8f19b48..bcbdd24fb 100644 --- a/crypto/rsa/rsa_sp800_56b_check.c +++ b/crypto/rsa/rsa_sp800_56b_check.c @@ -289,6 +289,11 @@ int ossl_rsa_sp800_56b_check_public(const RSA *rsa) return 0; nbits = BN_num_bits(rsa->n); + if (nbits > OPENSSL_RSA_MAX_MODULUS_BITS) { + ERR_raise(ERR_LIB_RSA, RSA_R_MODULUS_TOO_LARGE); + return 0; + } + #ifdef FIPS_MODULE /* * (Step a): modulus must be 2048 or 3072 (caveat from SP800-56Br1) @@ -324,7 +329,8 @@ int ossl_rsa_sp800_56b_check_public(const RSA *rsa) goto err; } - ret = ossl_bn_miller_rabin_is_prime(rsa->n, 0, ctx, NULL, 1, &status); + /* Highest number of MR rounds from FIPS 186-5 Section B.3 Table B.1 */ + ret = ossl_bn_miller_rabin_is_prime(rsa->n, 5, ctx, NULL, 1, &status); #ifdef FIPS_MODULE if (ret != 1 || status != BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME) { #else diff --git a/test/recipes/91-test_pkey_check.t b/test/recipes/91-test_pkey_check.t index c290b0ba7..76bea983b 100644 --- a/test/recipes/91-test_pkey_check.t +++ b/test/recipes/91-test_pkey_check.t @@ -70,7 +70,7 @@ push(@positive_tests, ( "dhpkey.pem" )) unless disabled("dh"); -my @negative_pubtests = (); +my @negative_pubtests = ("rsapub_17k.pem"); # Too big RSA public key push(@negative_pubtests, ( "dsapub_noparam.der" diff --git a/test/recipes/91-test_pkey_check_data/rsapub_17k.pem b/test/recipes/91-test_pkey_check_data/rsapub_17k.pem new file mode 100644 index 000000000..9a2eaedaf --- /dev/null +++ b/test/recipes/91-test_pkey_check_data/rsapub_17k.pem @@ -0,0 +1,48 @@ +-----BEGIN PUBLIC KEY----- +MIIIbzANBgkqhkiG9w0BAQEFAAOCCFwAMIIIVwKCCE4Ang+cE5H+hg3RbapDAHqR +B9lUnp2MlAwsZxQ/FhYepaR60bFQeumbu7817Eo5YLMObVI99hF1C4u/qcpD4Jph +gZt87/JAYDbP+DIh/5gUXCL9m5Fp4u7mvZaZdnlcftBvR1uKUTCAwc9pZ/Cfr8W2 +GzrRODzsNYnk2DcZMfe2vRDuDZRopE+Y+I72rom2SZLxoN547N1daM/M/CL9KVQ/ +XMI/YOpJrBI0jI3brMRhLkvLckwies9joufydlGbJkeil9H7/grj3fQZtFkZ2Pkj +b87XDzRVX7wsEpAgPJxskL3jApokCp1kQYKG+Uc3dKM9Ade6IAPK7VKcmbAQTYw2 +gZxsc28dtstazmfGz0ACCTSMrmbgWAM3oPL7RRzhrXDWgmYQ0jHefGh8SNTIgtPq +TuHxPYkDMQNaf0LmDGCxqlnf4b5ld3YaU8zZ/RqIRx5v/+w0rJUvU53qY1bYSnL1 +vbqKSnN2mip0GYyQ4AUgkS1NBV4rGYU/VTvzEjLfkg02KOtHKandvEoUjmZPzCT0 +V2ZhGc8K1UJNGYlIiHqCdwCBoghvly/pYajTkDXyd6BsukzA5H3IkZB1xDgl035j +/0Cr7QeZLEOdi9fPdSSaBT6OmD0WFuZfJF0wMr7ucRhWzPXvSensD9v7MBE7tNfH +SLeTSx8tLt8UeWriiM+0CnkPR1IOqMOxubOyf1eV8NQqEWm5wEQG/0IskbOKnaHa +PqLFJZn/bvyL3XK5OxVIJG3z6bnRDOMS9SzkjqgPdIO8tkySEHVSi/6iuGUltx3Y +Fmq6ye/r34ekyHPbfn6UuTON7joM6SIXb5bHM64x4iMVWx4hMvDjfy0UqfywAUyu +C1o7BExSMxxFG8GJcqR0K8akpPp7EM588PC+YuItoxzXgfUJnP3BQ1Beev2Ve7/J +xeGZH0N4ntfr+cuaLAakAER9zDglwChWflw3NNFgIdAgSxXv3XXx5xDXpdP4lxUo +F5zAN4Mero3yV90FaJl7Vhq/UFVidbwFc15jUDwaE0mKRcsBeVd3GOhoECAgE0id +aIPT20z8oVY0FyTJlRk7QSjo8WjJSrHY/Fn14gctX07ZdfkufyL6w+NijBdYluvB +nIrgHEvpkDEWoIa8qcx0EppoIcmqgMV2mTShfFYSybsO33Pm8WXec2FXjwhzs1Pi +R/BuIW8rHPI67xqWm0h8dEw11vtfi9a/BBBikFHe59KBjMTG+lW/gADNvRoTzGh7 +kN4+UVDS3jlSisRZZOn1XoeQtpubNYWgUsecjKy45IwIj8h1SHgn3wkmUesY0woN +mOdoNtq+NezN4RFtbCOHhxFVpKKDi/HQP2ro0ykkXMDjwEIVf2Lii1Mg9UP8m+Ux +AOqkTrIkdogkRx+70h7/wUOfDIFUq2JbKzqxJYamyEphcdAko7/B8efQKc61Z93O +f2SHa4++4WI7wIIx18v5KV4M/cRmrfc8w9WRkQN3gBT5AJMuqwcSHVXBWvNQeGmi +ScMh7X6cCZ0daEujqb8svq4WgsJ8UT4GaGBRIYtt7QUKEh+JQwNJzneRYZ3pzpaH +UJeeoYobMlkp3rM9cYzdq90nBQiI9Jsbim9m9ggb2dMOS5CsI9S/IuG2O5uTjfxx +wkwsd5nLDFtNXHYZ7W6XlVJ1Rc6zShnEmdCn3mmibb6OaMUmun2yl9ryEjVSoXLP +fSA8W9K9yNhKTRkzdXJfqlC+s/ovX2xBGxsuOoUDaXhRVz0qmpKIHeSFjIP4iXq4 +y8gDiwvM3HbZfvVonbg6siPwpn4uvw3hesojk1DKAENS52i6U3uK2fs1ALVxsFNS +Yh914rDu0Q3e4RXVhURaYzoEbLCot6WGYeCCfQOK0rkETMv+sTYYscC8/THuW7SL +HG5zy9Ed95N1Xmf8J+My7gM7ZFodGdHsWvdzEmqsdOFh6IVx/VfHFX0MDBq0t6lZ +eRvVgVCfu3gkYLwPScn/04E02vOom51ISKHsF/I11erC66jjNYV9BSpH8O7sAHxZ +EmPT2ZVVRSgivOHdQW/FZ3UZQQhVaVSympo2Eb4yWEMFn84Q8T+9Honj6gnB5PXz +chmeCsOMlcg1mwWwhn0k+OAWEZy7VRUk5Ahp0fBAGJgwBdqrZ3kM356DjUkVBiYq +4eHyvafNKmjf2mnFsI3g2NKRNyl1Lh63wyCFx60yYvBUfXF/W9PFJbD9CiP83kEW +gV36gxTsbOSfhpO1OXR90ODy0kx06XzWmJCUugK8u9bx4F/CjV+LIHExuNJiethC +A8sIup/MT0fWp4RO/SsVblGqfoqJTaPnhptQzeH2N07pbWkxeMuL6ppPuwFmfVjK +FJndqCVrAukcPEOQ16iVURuloJMudqYRc9QKkJFsnv0W/iMNbqQGmXe8Q/5qFiys +26NIQBiE2ad9hNLnoccEnmYSRgnW3ZPSKuq5TDdYyDqTZH2r8cam65pr3beKw2XC +xw4cc7VaxiwGC2Mg2wRmwwPaTjrcEt6sMa3RjwFEVBxBFyM26wnTEZsTBquCxV0J +pgERaeplkixP2Q0m7XAdlDaob973SM2vOoUgypzDchWmpx7u775bnOfU5CihwXl+ +k0i09WZuT8bPmhEAiGCw5sNzMkz1BC2cCZFfJIkE2vc/wXYOrGxBTJo0EKaUFswa +2dnP/u0bn+VksBUM7ywW9LJSXh4mN+tpzdeJtxEObKwX1I0dQxSPWmjd2++wMr9q +Unre5fCrDToy2H7C2VKSpuOCT2/Kv4JDQRWwI4KxQOpn0UknAGNmfBoTtpIZ3LEb +77oBUJdMQD7tQBBLL0a6f1TdK0dHVprWWawJ+gGFMiMQXqAqblHcxFKWuHv9bQID +AQAB +-----END PUBLIC KEY----- From c0b627ef6d996ed1f5f90be758762ef08a9ca61c Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 14:58:51 +0800 Subject: [PATCH 08/66] Add CHANGES entry for CVE-2023-6237 --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 9a1c3e5dc..b59f8621f 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,8 @@ *) 修复CVE-2023-6129 + *) 修复CVE-2023-6237 + *) 增加SM2两方门限解密算法 *) 增加SM2两方门限签名算法 [with work originated from FullyRobert] From 3b4c5ab9fa0ee3c15bea044770f8eeb89dd162fc Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 17:50:33 +0800 Subject: [PATCH 09/66] ossl_dh_check_priv_key: Do not fail on private keys without q Fixes #18098 Reviewed-by: Shane Lontis Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/18099) --- crypto/dh/dh_check.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c index ab31d1285..dd1ccfaed 100644 --- a/crypto/dh/dh_check.c +++ b/crypto/dh/dh_check.c @@ -282,22 +282,43 @@ int ossl_dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret) two_powN = BN_new(); if (two_powN == NULL) return 0; - if (dh->params.q == NULL) - goto err; - upper = dh->params.q; + + if (dh->params.q != NULL) { + upper = dh->params.q; +#ifndef FIPS_MODULE + } else if (dh->params.p != NULL) { + /* + * We do not have q so we just check the key is within some + * reasonable range, or the number of bits is equal to dh->length. + */ + int length = dh->length; + + if (length == 0) { + length = BN_num_bits(dh->params.p) - 1; + if (BN_num_bits(priv_key) <= length + && BN_num_bits(priv_key) > 1) + ok = 1; + } else if (BN_num_bits(priv_key) == length) { + ok = 1; + } + goto end; +#endif + } else { + goto end; + } /* Is it from an approved Safe prime group ?*/ if (DH_get_nid((DH *)dh) != NID_undef && dh->length != 0) { if (!BN_lshift(two_powN, BN_value_one(), dh->length)) - goto err; + goto end; if (BN_cmp(two_powN, dh->params.q) < 0) upper = two_powN; } if (!ossl_ffc_validate_private_key(upper, priv_key, ret)) - goto err; + goto end; ok = 1; -err: +end: BN_free(two_powN); return ok; } From ea1e4bd8c72732a149c2e99d65d7cdbcc01705db Mon Sep 17 00:00:00 2001 From: Nagha Abirami Date: Mon, 18 Mar 2024 14:48:21 -0400 Subject: [PATCH 10/66] Fix sm2 init failure. Babassl ticket: https://github.com/Tongsuo-Project/Tongsuo/issues/589 --- crypto/evp/ec_ctrl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crypto/evp/ec_ctrl.c b/crypto/evp/ec_ctrl.c index 404358ab9..514b45f94 100644 --- a/crypto/evp/ec_ctrl.c +++ b/crypto/evp/ec_ctrl.c @@ -283,7 +283,8 @@ int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm) */ int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid) { - return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_TYPE_GEN, + int keytype = nid == EVP_PKEY_SM2 ? EVP_PKEY_SM2 : EVP_PKEY_EC; + return EVP_PKEY_CTX_ctrl(ctx, keytype, EVP_PKEY_OP_TYPE_GEN, EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL); } From 3f18eac4e8052821b965a2fbd93796bdaea3462a Mon Sep 17 00:00:00 2001 From: K1 Date: Mon, 18 Mar 2024 11:47:48 +0800 Subject: [PATCH 11/66] Fix ASLR to be smaller during asan/tsan/ubsan runs Recently asan/tsan/ubsan runs have been failing randomly. It appears that a recent runner update may have led to the Address Space Layout Randomization setting in the linux kernel of ubuntu-latest runner getting set to too high a value (it defaults to 30). Such a setting leads to the possibility that a given application will have memory mapped to an address space that the sanitizer code typically uses to do its job. Lowering this value allows a/t/ubsan to work consistently again Reviewed-by: Tim Hudson Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23842) --- .github/workflows/ci.yml | 48 ++++++++++++++++++++----- .github/workflows/fuzz-checker.yml | 7 ++-- .github/workflows/run-checker-merge.yml | 6 +++- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 374aef26b..5c40b7209 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -113,7 +113,11 @@ jobs: non-caching: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Adjust ASLR for sanitizer + run: | + sudo cat /proc/sys/vm/mmap_rnd_bits + sudo sysctl -w vm.mmap_rnd_bits=28 - name: config run: ./config --banner=Configured --debug enable-asan enable-ubsan no-cached-fetch no-fips no-dtls no-tls1 no-tls1-method no-tls1_1 no-tls1_1-method no-async && perl configdata.pm --dump - name: make @@ -124,7 +128,11 @@ jobs: address_ub_sanitizer: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Adjust ASLR for sanitizer + run: | + sudo cat /proc/sys/vm/mmap_rnd_bits + sudo sysctl -w vm.mmap_rnd_bits=28 - name: config run: ./config --banner=Configured --debug enable-asan enable-ubsan enable-rc5 enable-ec_nistp_64_gcc_128 enable-fips enable-cert-compression enable-bn-method enable-delegated-credential -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION && perl configdata.pm --dump - name: make @@ -135,7 +143,11 @@ jobs: ntls_address_ub_sanitizer: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Adjust ASLR for sanitizer + run: | + sudo cat /proc/sys/vm/mmap_rnd_bits + sudo sysctl -w vm.mmap_rnd_bits=28 - name: config run: ./config --banner=Configured --debug enable-asan enable-ubsan enable-rc5 enable-ec_nistp_64_gcc_128 enable-ec_sm2p_64_gcc_128 enable-ntls -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION && perl configdata.pm --dump - name: make @@ -146,7 +158,11 @@ jobs: memory_sanitizer: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Adjust ASLR for sanitizer + run: | + sudo cat /proc/sys/vm/mmap_rnd_bits + sudo sysctl -w vm.mmap_rnd_bits=28 - name: config # --debug -O1 is to produce a debug build that runs in a reasonable amount of time run: CC=clang ./config --banner=Configured --debug -O1 -fsanitize=memory -DOSSL_SANITIZE_MEMORY -fno-optimize-sibling-calls enable-rc5 enable-ec_nistp_64_gcc_128 enable-fips enable-cert-compression enable-delegated-credential enable-bn-method && perl configdata.pm --dump @@ -158,7 +174,11 @@ jobs: ntls_memory_sanitizer: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Adjust ASLR for sanitizer + run: | + sudo cat /proc/sys/vm/mmap_rnd_bits + sudo sysctl -w vm.mmap_rnd_bits=28 - name: config # --debug -O1 is to produce a debug build that runs in a reasonable amount of time run: CC=clang ./config --banner=Configured --debug -O1 -fsanitize=memory -DOSSL_SANITIZE_MEMORY -fno-optimize-sibling-calls enable-rc5 enable-ec_nistp_64_gcc_128 enable-ec_sm2p_64_gcc_128 enable-ntls && perl configdata.pm --dump @@ -170,7 +190,11 @@ jobs: threads_sanitizer: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Adjust ASLR for sanitizer + run: | + sudo cat /proc/sys/vm/mmap_rnd_bits + sudo sysctl -w vm.mmap_rnd_bits=28 - name: config run: CC=clang ./config --banner=Configured no-fips --strict-warnings -fsanitize=thread && perl configdata.pm --dump - name: make @@ -268,7 +292,11 @@ jobs: EC_POINTs_api_test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Adjust ASLR for sanitizer + run: | + sudo cat /proc/sys/vm/mmap_rnd_bits + sudo sysctl -w vm.mmap_rnd_bits=28 - name: config run: ./config --strict-warnings --debug --api=1.1.1 enable-asan enable-ubsan enable-ssl-trace enable-zlib enable-zlib-dynamic no-fips enable-engine enable-dynamic-engine no-deprecated && perl configdata.pm --dump - name: make @@ -394,7 +422,11 @@ jobs: sm2-threshold-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Adjust ASLR for sanitizer + run: | + sudo cat /proc/sys/vm/mmap_rnd_bits + sudo sysctl -w vm.mmap_rnd_bits=28 - name: config run: CC=clang ./config --strict-warnings --debug -O1 -fsanitize=memory -DOSSL_SANITIZE_MEMORY enable-sm2_threshold && perl configdata.pm --dump - name: make diff --git a/.github/workflows/fuzz-checker.yml b/.github/workflows/fuzz-checker.yml index e583e26ba..bc9a5bdb5 100644 --- a/.github/workflows/fuzz-checker.yml +++ b/.github/workflows/fuzz-checker.yml @@ -45,8 +45,11 @@ jobs: run: | sudo apt-get update sudo apt-get -yq --force-yes install ${{ matrix.fuzzy.install }} - - uses: actions/checkout@v2 - + - name: Adjust ASLR for sanitizer + run: | + sudo cat /proc/sys/vm/mmap_rnd_bits + sudo sysctl -w vm.mmap_rnd_bits=28 + - uses: actions/checkout@v4 - name: config run: | CC=${{ matrix.fuzzy.cc }} ./config --banner=Configured no-shared \ diff --git a/.github/workflows/run-checker-merge.yml b/.github/workflows/run-checker-merge.yml index 124343507..c5e0c3853 100644 --- a/.github/workflows/run-checker-merge.yml +++ b/.github/workflows/run-checker-merge.yml @@ -32,7 +32,11 @@ jobs: ] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - name: Adjust ASLR for sanitizer + run: | + sudo cat /proc/sys/vm/mmap_rnd_bits + sudo sysctl -w vm.mmap_rnd_bits=28 + - uses: actions/checkout@v4 - name: config run: CC=clang ./config --banner=Configured --strict-warnings ${{ matrix.opt }} - name: config dump From 28971b766508aff89e6fba613bfeff15719be586 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 17:08:34 +0800 Subject: [PATCH 12/66] Add support for mac-less password-base PKCS12 files to PKCS12_parse API. Fixes openssl#17720. Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/17882) --- crypto/pkcs12/p12_kiss.c | 37 ++++---- test/build.info | 6 +- test/pkcs12_api_test.c | 169 ++++++++++++++++++++++++++++++++++ test/recipes/80-test_pkcs12.t | 65 ++++++++++++- 4 files changed, 257 insertions(+), 20 deletions(-) create mode 100644 test/pkcs12_api_test.c diff --git a/crypto/pkcs12/p12_kiss.c b/crypto/pkcs12/p12_kiss.c index 229b34cf6..1d3985593 100644 --- a/crypto/pkcs12/p12_kiss.c +++ b/crypto/pkcs12/p12_kiss.c @@ -49,27 +49,28 @@ int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, } /* Check the mac */ - - /* - * If password is zero length or NULL then try verifying both cases to - * determine which password is correct. The reason for this is that under - * PKCS#12 password based encryption no password and a zero length - * password are two different things... - */ - - if (pass == NULL || *pass == '\0') { - if (!PKCS12_mac_present(p12) - || PKCS12_verify_mac(p12, NULL, 0)) - pass = NULL; - else if (PKCS12_verify_mac(p12, "", 0)) - pass = ""; - else { + if (PKCS12_mac_present(p12)) { + /* + * If password is zero length or NULL then try verifying both cases to + * determine which password is correct. The reason for this is that under + * PKCS#12 password based encryption no password and a zero length + * password are two different things... + */ + if (pass == NULL || *pass == '\0') { + if (PKCS12_verify_mac(p12, NULL, 0)) + pass = NULL; + else if (PKCS12_verify_mac(p12, "", 0)) + pass = ""; + else { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE); + goto err; + } + } else if (!PKCS12_verify_mac(p12, pass, -1)) { ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE); goto err; } - } else if (!PKCS12_verify_mac(p12, pass, -1)) { - ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE); - goto err; + } else if (pass == NULL || *pass == '\0') { + pass = NULL; } /* If needed, allocate stack for other certificates */ diff --git a/test/build.info b/test/build.info index b0b915caf..6d53ee12f 100644 --- a/test/build.info +++ b/test/build.info @@ -30,7 +30,7 @@ IF[{- !$disabled{tests} -}] PROGRAMS{noinst}= \ confdump \ versions \ - aborttest test_test pkcs12_format_test \ + aborttest test_test pkcs12_format_test pkcs12_api_test \ sanitytest rsa_complex exdatatest bntest \ ecstresstest gmdifftest pbelutest \ destest sha_test \ @@ -278,6 +278,10 @@ IF[{- !$disabled{tests} -}] INCLUDE[pkcs12_format_test]=../include ../apps/include DEPEND[pkcs12_format_test]=../libcrypto libtestutil.a + SOURCE[pkcs12_api_test]=pkcs12_api_test.c helpers/pkcs12.c + INCLUDE[pkcs12_api_test]=../include ../apps/include + DEPEND[pkcs12_api_test]=../libcrypto libtestutil.a + SOURCE[pkcs7_test]=pkcs7_test.c INCLUDE[pkcs7_test]=../include ../apps/include DEPEND[pkcs7_test]=../libcrypto libtestutil.a diff --git a/test/pkcs12_api_test.c b/test/pkcs12_api_test.c new file mode 100644 index 000000000..f3648706f --- /dev/null +++ b/test/pkcs12_api_test.c @@ -0,0 +1,169 @@ +/* + * Copyright 2022 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 +#include +#include + +#include "internal/nelem.h" + +#include +#include +#include +#include + +#include "testutil.h" +#include "helpers/pkcs12.h" + +static OSSL_LIB_CTX *testctx = NULL; +static OSSL_PROVIDER *nullprov = NULL; +static OSSL_PROVIDER *deflprov = NULL; + +static int test_null_args(void) +{ + return TEST_false(PKCS12_parse(NULL, NULL, NULL, NULL, NULL)); +} + +static PKCS12 *PKCS12_load(const char *fpath) +{ + BIO *bio = NULL; + PKCS12 *p12 = NULL; + + bio = BIO_new_file(fpath, "r"); + if (!TEST_ptr(bio)) + goto err; + + p12 = PKCS12_init(NID_pkcs7_data); + if (!TEST_ptr(p12)) + goto err; + + if (!TEST_true(p12 == d2i_PKCS12_bio(bio, &p12))) + goto err; + + BIO_free(bio); + + return p12; + +err: + BIO_free(bio); + PKCS12_free(p12); + return NULL; +} + +static const char *in_file = NULL; +static const char *in_pass = ""; +static int has_key = 0; +static int has_cert = 0; +static int has_ca = 0; +static int pkcs12_parse_test(void) +{ + int ret = 0; + PKCS12 *p12 = NULL; + EVP_PKEY *key = NULL; + X509 *cert = NULL; + STACK_OF(X509) *ca = NULL; + + if (in_file != NULL) { + p12 = PKCS12_load(in_file); + if (!TEST_ptr(p12)) + goto err; + + if (!TEST_true(PKCS12_parse(p12, in_pass, &key, &cert, &ca))) + goto err; + + if ((has_key && !TEST_ptr(key)) || (!has_key && !TEST_ptr_null(key))) + goto err; + if ((has_cert && !TEST_ptr(cert)) || (!has_cert && !TEST_ptr_null(cert))) + goto err; + if ((has_ca && !TEST_ptr(ca)) || (!has_ca && !TEST_ptr_null(ca))) + goto err; + } + + ret = 1; +err: + PKCS12_free(p12); + EVP_PKEY_free(key); + X509_free(cert); + OSSL_STACK_OF_X509_free(ca); + return TEST_true(ret); +} + +typedef enum OPTION_choice { + OPT_ERR = -1, + OPT_EOF = 0, + OPT_IN_FILE, + OPT_IN_PASS, + OPT_IN_HAS_KEY, + OPT_IN_HAS_CERT, + OPT_IN_HAS_CA, + OPT_LEGACY, + OPT_TEST_ENUM +} OPTION_CHOICE; + +const OPTIONS *test_get_options(void) +{ + static const OPTIONS options[] = { + OPT_TEST_OPTIONS_DEFAULT_USAGE, + { "in", OPT_IN_FILE, '<', "PKCS12 input file" }, + { "pass", OPT_IN_PASS, 's', "PKCS12 input file password" }, + { "has-key", OPT_IN_HAS_KEY, 'n', "Whether the input file does contain an user key" }, + { "has-cert", OPT_IN_HAS_CERT, 'n', "Whether the input file does contain an user certificate" }, + { "has-ca", OPT_IN_HAS_CA, 'n', "Whether the input file does contain other certificate" }, + { "legacy", OPT_LEGACY, '-', "Test the legacy APIs" }, + { NULL } + }; + return options; +} + +int setup_tests(void) +{ + OPTION_CHOICE o; + + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_IN_FILE: + in_file = opt_arg(); + break; + case OPT_IN_PASS: + in_pass = opt_arg(); + break; + case OPT_LEGACY: + break; + case OPT_IN_HAS_KEY: + has_key = opt_int_arg(); + break; + case OPT_IN_HAS_CERT: + has_cert = opt_int_arg(); + break; + case OPT_IN_HAS_CA: + has_ca = opt_int_arg(); + break; + case OPT_TEST_CASES: + break; + default: + return 0; + } + } + + deflprov = OSSL_PROVIDER_load(testctx, "default"); + if (!TEST_ptr(deflprov)) + return 0; + + ADD_TEST(test_null_args); + ADD_TEST(pkcs12_parse_test); + + return 1; +} + +void cleanup_tests(void) +{ + OSSL_PROVIDER_unload(nullprov); + OSSL_PROVIDER_unload(deflprov); + OSSL_LIB_CTX_free(testctx); +} diff --git a/test/recipes/80-test_pkcs12.t b/test/recipes/80-test_pkcs12.t index 8afd61269..eebbfe8ef 100644 --- a/test/recipes/80-test_pkcs12.t +++ b/test/recipes/80-test_pkcs12.t @@ -54,7 +54,7 @@ if (eval { require Win32::API; 1; }) { } $ENV{OPENSSL_WIN32_UTF8}=1; -plan tests => 12; +plan tests => 21; # Test different PKCS#12 formats ok(run(test(["pkcs12_format_test"])), "test pkcs12 formats"); @@ -75,6 +75,7 @@ my $outfile2 = "out2.p12"; my $outfile3 = "out3.p12"; my $outfile4 = "out4.p12"; my $outfile5 = "out5.p12"; +my $outfile6 = "out6.p12"; # Test the -chain option with -untrusted ok(run(app(["openssl", "pkcs12", "-export", "-chain", @@ -130,4 +131,66 @@ ok(grep(/subject=CN = server.example/, @pkcs12info) == 1, # Test that the expected friendly name is present in the output ok(grep(/testname/, @pkcs12info) == 1, "test friendly name in output"); +# Test export of PEM file with both cert and key, without password. +# -nomac necessary to avoid legacy provider requirement +{ + ok(run(app(["openssl", "pkcs12", "-export", + "-inkey", srctop_file(@path, "cert-key-cert.pem"), + "-in", srctop_file(@path, "cert-key-cert.pem"), + "-passout", "pass:", + "-nomac", "-out", $outfile6], stderr => "outerr6.txt")), + "test_export_pkcs12_cert_key_cert_no_pass"); + open DATA, "outerr6.txt"; + my @match = grep /:error:/, ; + close DATA; + ok(scalar @match > 0 ? 0 : 1, "test_export_pkcs12_outerr6_empty"); +} + +# Tests for pkcs12_parse +ok(run(test(["pkcs12_api_test", + "-in", $outfile1, + "-has-ca", 1, + ])), "Test pkcs12_parse()"); + +SKIP: { + skip "Skipping PKCS#12 parse test because DES is disabled in this build", 1 + if disabled("des"); + ok(run(test(["pkcs12_api_test", + "-in", $outfile2, + "-pass", "v3-certs", + "-has-ca", 1, + ])), "Test pkcs12_parse()"); +} + +SKIP: { + skip "Skipping PKCS#12 parse test because the required algorithms are disabled", 1 + if disabled("des") || disabled("rc2") || disabled("legacy"); + ok(run(test(["pkcs12_api_test", + "-in", $outfile3, + "-pass", "v3-certs", + "-has-ca", 1, + ])), "Test pkcs12_parse()"); +} + +ok(run(test(["pkcs12_api_test", + "-in", $outfile4, + "-pass", "v3-certs", + "-has-ca", 1, + "-has-key", 1, + "-has-cert", 1, + ])), "Test pkcs12_parse()"); + +ok(run(test(["pkcs12_api_test", + "-in", $outfile5, + "-has-ca", 1, + ])), "Test pkcs12_parse()"); + +ok(run(test(["pkcs12_api_test", + "-in", $outfile6, + "-pass", "", + "-has-ca", 1, + "-has-key", 1, + "-has-cert", 1, + ])), "Test pkcs12_parse()"); + SetConsoleOutputCP($savedcp) if (defined($savedcp)); From ae783f3198d9965fac547e07e5490f29bde73ee5 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 17:09:10 +0800 Subject: [PATCH 13/66] test/pkcs12_api_test.c: fix failure on MinGW Use binary mode when opening a file. Partially fixes #18017. Reviewed-by: Kurt Roeckx Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/19117) --- test/pkcs12_api_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pkcs12_api_test.c b/test/pkcs12_api_test.c index f3648706f..51976edea 100644 --- a/test/pkcs12_api_test.c +++ b/test/pkcs12_api_test.c @@ -35,7 +35,7 @@ static PKCS12 *PKCS12_load(const char *fpath) BIO *bio = NULL; PKCS12 *p12 = NULL; - bio = BIO_new_file(fpath, "r"); + bio = BIO_new_file(fpath, "rb"); if (!TEST_ptr(bio)) goto err; From 3c67904c362cc0433fe6547b93f28a5e2edf7a03 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 17:28:19 +0800 Subject: [PATCH 14/66] Allow PKCS12 export to set arbitrary bag attributes Reviewed-by: Dmitry Belyavskiy Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/19025) --- apps/openssl.cnf | 7 ++ apps/pkcs12.c | 74 ++++++++++++++- crypto/err/openssl.txt | 1 + crypto/objects/obj_dat.h | 20 +++- crypto/objects/obj_mac.num | 2 + crypto/objects/objects.txt | 6 ++ crypto/pkcs12/p12_attr.c | 8 ++ crypto/pkcs12/p12_crt.c | 68 ++++++++++++-- crypto/pkcs12/pk12err.c | 3 +- doc/man3/PKCS12_SAFEBAG_set0_attrs.pod | 32 +++++++ fuzz/oids.txt | 2 + include/crypto/pkcs12err.h | 2 +- include/openssl/obj_mac.h | 10 ++ include/openssl/pkcs12.h.in | 7 ++ include/openssl/pkcs12err.h | 3 +- test/helpers/pkcs12.c | 14 ++- test/helpers/pkcs12.h | 1 + test/pkcs12_api_test.c | 94 ++++++++++++++++++- test/pkcs12_format_test.c | 93 ++++++++++++++++++ test/recipes/80-test_pkcs12.t | 24 ++++- .../80-test_pkcs12_data/jdk_trusted.cnf | 8 ++ util/libcrypto.num | 2 + util/other.syms | 1 + 23 files changed, 459 insertions(+), 23 deletions(-) create mode 100644 doc/man3/PKCS12_SAFEBAG_set0_attrs.pod create mode 100644 test/recipes/80-test_pkcs12_data/jdk_trusted.cnf diff --git a/apps/openssl.cnf b/apps/openssl.cnf index e58082c8a..05faefadf 100644 --- a/apps/openssl.cnf +++ b/apps/openssl.cnf @@ -399,3 +399,10 @@ oldcert = $insta::certout # insta.cert.pem # Certificate revocation cmd = rr oldcert = $insta::certout # insta.cert.pem + +[pkcs12] +certBagAttr = cb_attr + +# Uncomment this if you need Java compatible PKCS12 files +[cb_attr] +#jdkTrustedKeyUsage = anyExtendedKeyUsage diff --git a/apps/pkcs12.c b/apps/pkcs12.c index 8ad93d36a..257dda403 100644 --- a/apps/pkcs12.c +++ b/apps/pkcs12.c @@ -14,6 +14,8 @@ #include #include "apps.h" #include "progs.h" +#include +#include #include #include #include @@ -53,6 +55,7 @@ void hex_prin(BIO *out, unsigned char *buf, int len); static int alg_print(const X509_ALGOR *alg); int cert_load(BIO *in, STACK_OF(X509) *sk); static int set_pbe(int *ppbe, const char *str); +static int jdk_trust(PKCS12_SAFEBAG *bag, void *cbarg); typedef enum OPTION_choice { OPT_COMMON, @@ -512,6 +515,11 @@ int pkcs12_main(int argc, char **argv) EVP_MD *macmd = NULL; unsigned char *catmp = NULL; int i; + CONF *conf = NULL; + ASN1_OBJECT *obj = NULL; + STACK_OF(CONF_VALUE) *cb_sk = NULL; + const char *cb_attr = NULL; + const CONF_VALUE *val = NULL; if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) { BIO_printf(bio_err, "Nothing to export due to -noout or -nocerts and -nokeys\n"); @@ -656,9 +664,30 @@ int pkcs12_main(int argc, char **argv) if (!twopass) OPENSSL_strlcpy(macpass, pass, sizeof(macpass)); - p12 = PKCS12_create_ex(cpass, name, key, ee_cert, certs, - key_pbe, cert_pbe, iter, -1, keytype, - app_get0_libctx(), app_get0_propq()); + /* Load the config file */ + if ((conf = app_load_config(default_config_file)) == NULL) + goto export_end; + if (!app_load_modules(conf)) + goto export_end; + /* Find the cert bag section */ + if ((cb_attr = NCONF_get_string(conf, "pkcs12", "certBagAttr")) != NULL) { + if ((cb_sk = NCONF_get_section(conf, cb_attr)) != NULL) { + for (i = 0; i < sk_CONF_VALUE_num(cb_sk); i++) { + val = sk_CONF_VALUE_value(cb_sk, i); + if (strcmp(val->name, "jdkTrustedKeyUsage") == 0) + obj = OBJ_txt2obj(val->value, 0); + } + } else { + ERR_clear_error(); + } + } else { + ERR_clear_error(); + } + + p12 = PKCS12_create_ex2(cpass, name, key, ee_cert, certs, + key_pbe, cert_pbe, iter, -1, keytype, + app_get0_libctx(), app_get0_propq(), + jdk_trust, (void*)obj); if (p12 == NULL) { BIO_printf(bio_err, "Error creating PKCS12 structure for %s\n", @@ -695,7 +724,8 @@ int pkcs12_main(int argc, char **argv) sk_X509_pop_free(certs, X509_free); sk_X509_pop_free(untrusted_certs, X509_free); X509_free(ee_cert); - + NCONF_free(conf); + ASN1_OBJECT_free(obj); ERR_print_errors(bio_err); goto end; @@ -825,6 +855,31 @@ int pkcs12_main(int argc, char **argv) return ret; } +static int jdk_trust(PKCS12_SAFEBAG *bag, void *cbarg) +{ + STACK_OF(X509_ATTRIBUTE) *attrs = NULL; + X509_ATTRIBUTE *attr = NULL; + + /* Nothing to do */ + if (cbarg == NULL) + return 1; + + /* Get the current attrs */ + attrs = (STACK_OF(X509_ATTRIBUTE)*)PKCS12_SAFEBAG_get0_attrs(bag); + + /* Create a new attr for the JDK Trusted Usage and add it */ + attr = X509_ATTRIBUTE_create(NID_oracle_jdk_trustedkeyusage, V_ASN1_OBJECT, (ASN1_OBJECT*)cbarg); + + /* Add the new attr, if attrs is NULL, it'll be initialised */ + X509at_add1_attr(&attrs, attr); + + /* Set the bag attrs */ + PKCS12_SAFEBAG_set0_attrs(bag, attrs); + + X509_ATTRIBUTE_free(attr); + return 1; +} + int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, const char *pass, int passlen, int options, char *pempass, const EVP_CIPHER *enc) @@ -1124,6 +1179,8 @@ int cert_load(BIO *in, STACK_OF(X509) *sk) void print_attribute(BIO *out, const ASN1_TYPE *av) { char *value; + const char *ln; + char objbuf[80]; switch (av->type) { case V_ASN1_BMPSTRING: @@ -1150,6 +1207,15 @@ void print_attribute(BIO *out, const ASN1_TYPE *av) BIO_printf(out, "\n"); break; + case V_ASN1_OBJECT: + ln = OBJ_nid2ln(OBJ_obj2nid(av->value.object)); + if (!ln) + ln = ""; + OBJ_obj2txt(objbuf, sizeof(objbuf), av->value.object, 1); + BIO_printf(out, "%s (%s)", ln, objbuf); + BIO_printf(out, "\n"); + break; + default: BIO_printf(out, "\n", av->type); break; diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index bfe7a985e..bd9bd818d 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -888,6 +888,7 @@ PEM_R_UNSUPPORTED_CIPHER:113:unsupported cipher PEM_R_UNSUPPORTED_ENCRYPTION:114:unsupported encryption PEM_R_UNSUPPORTED_KEY_COMPONENTS:126:unsupported key components PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE:110:unsupported public key type +PKCS12_R_CALLBACK_FAILED:115:callback failed PKCS12_R_CANT_PACK_STRUCTURE:100:cant pack structure PKCS12_R_CONTENT_TYPE_NOT_DATA:121:content type not data PKCS12_R_DECODE_ERROR:101:decode error diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h index 16bf5d227..afcfc7890 100644 --- a/crypto/objects/obj_dat.h +++ b/crypto/objects/obj_dat.h @@ -10,7 +10,7 @@ */ /* Serialized OID's */ -static const unsigned char so[6609] = { +static const unsigned char so[6628] = { 0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05, /* [ 13] OBJ_md5 */ @@ -929,9 +929,11 @@ static const unsigned char so[6609] = { 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x86,0x22, /* [ 6581] OBJ_zuc_128_eia3 */ 0x2B,0x06,0x01,0x04,0x01,0x82,0xDA,0x4B,0x2C, /* [ 6589] OBJ_delegation_usage */ 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x11,0x03,0x01, /* [ 6598] OBJ_hmacWithSM3 */ + 0x60,0x86,0x48,0x01,0x86,0xF9,0x66, /* [ 6608] OBJ_oracle */ + 0x60,0x86,0x48,0x01,0x86,0xF9,0x66,0xAD,0xCA,0x7B,0x01,0x01, /* [ 6615] OBJ_oracle_jdk_trustedkeyusage */ }; -#define NUM_NID 1258 +#define NUM_NID 1260 static const ASN1_OBJECT nid_objs[NUM_NID] = { {"UNDEF", "undefined", NID_undef}, {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]}, @@ -2191,9 +2193,11 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = { {"ZUC-128-EIA3", "zuc-128-eia3", NID_zuc_128_eia3, 8, &so[6581]}, {"delegationUsage", "X509v3 Delegation Usage", NID_delegation_usage, 9, &so[6589]}, {"hmacWithSM3", "hmacWithSM3", NID_hmacWithSM3, 10, &so[6598]}, + {"oracle-organization", "Oracle organization", NID_oracle, 7, &so[6608]}, + {"oracle-jdk-trustedkeyusage", "Trusted key usage (Oracle)", NID_oracle_jdk_trustedkeyusage, 12, &so[6615]}, }; -#define NUM_SN 1008 +#define NUM_SN 1010 static const unsigned int sn_objs[NUM_SN] = { 364, /* "AD_DVCS" */ 419, /* "AES-128-CBC" */ @@ -2883,6 +2887,8 @@ static const unsigned int sn_objs[NUM_SN] = { 139, /* "nsSGC" */ 77, /* "nsSslServerName" */ 681, /* "onBasis" */ + 1259, /* "oracle-jdk-trustedkeyusage" */ + 1258, /* "oracle-organization" */ 1089, /* "organizationIdentifier" */ 491, /* "organizationalStatus" */ 1141, /* "oscca" */ @@ -3205,7 +3211,7 @@ static const unsigned int sn_objs[NUM_SN] = { 1093, /* "x509ExtAdmission" */ }; -#define NUM_LN 1008 +#define NUM_LN 1010 static const unsigned int ln_objs[NUM_LN] = { 363, /* "AD Time Stamping" */ 405, /* "ANSI X9.62" */ @@ -3305,6 +3311,7 @@ static const unsigned int ln_objs[NUM_LN] = { 366, /* "OCSP Nonce" */ 371, /* "OCSP Service Locator" */ 180, /* "OCSP Signing" */ + 1258, /* "Oracle organization" */ 161, /* "PBES2" */ 69, /* "PBKDF2" */ 162, /* "PBMAC1" */ @@ -3348,6 +3355,7 @@ static const unsigned int ln_objs[NUM_LN] = { 129, /* "TLS Web Server Authentication" */ 133, /* "Time Stamping" */ 375, /* "Trust Root" */ + 1259, /* "Trusted key usage (Oracle)" */ 1034, /* "X25519" */ 1035, /* "X448" */ 12, /* "X509" */ @@ -4217,7 +4225,7 @@ static const unsigned int ln_objs[NUM_LN] = { 1255, /* "zuc-128-eia3" */ }; -#define NUM_OBJ 924 +#define NUM_OBJ 926 static const unsigned int obj_objs[NUM_OBJ] = { 0, /* OBJ_undef 0 */ 181, /* OBJ_iso 1 */ @@ -4591,6 +4599,7 @@ static const unsigned int obj_objs[NUM_OBJ] = { 507, /* OBJ_id_hex_partial_message 1 3 6 1 7 1 1 1 */ 508, /* OBJ_id_hex_multipart_message 1 3 6 1 7 1 1 2 */ 57, /* OBJ_netscape 2 16 840 1 113730 */ + 1258, /* OBJ_oracle 2 16 840 1 113894 */ 437, /* OBJ_pilot 0 9 2342 19200300 100 */ 1133, /* OBJ_sm4_ecb 1 2 156 10197 1 104 1 */ 1134, /* OBJ_sm4_cbc 1 2 156 10197 1 104 2 */ @@ -5132,6 +5141,7 @@ static const unsigned int obj_objs[NUM_OBJ] = { 955, /* OBJ_jurisdictionLocalityName 1 3 6 1 4 1 311 60 2 1 1 */ 956, /* OBJ_jurisdictionStateOrProvinceName 1 3 6 1 4 1 311 60 2 1 2 */ 957, /* OBJ_jurisdictionCountryName 1 3 6 1 4 1 311 60 2 1 3 */ + 1259, /* OBJ_oracle_jdk_trustedkeyusage 2 16 840 1 113894 746875 1 1 */ 1159, /* OBJ_dstu4145be 1 2 804 2 1 1 1 1 3 1 1 1 1 */ 1160, /* OBJ_uacurve0 1 2 804 2 1 1 1 1 3 1 1 2 0 */ 1161, /* OBJ_uacurve1 1 2 804 2 1 1 1 1 3 1 1 2 1 */ diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num index d9aeee93a..5e222b3f7 100644 --- a/crypto/objects/obj_mac.num +++ b/crypto/objects/obj_mac.num @@ -1025,3 +1025,5 @@ auth_sm2 1254 zuc_128_eia3 1255 delegation_usage 1256 hmacWithSM3 1257 +oracle 1258 +oracle_jdk_trustedkeyusage 1259 diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt index 4e461fb0f..9aede25bd 100644 --- a/crypto/objects/objects.txt +++ b/crypto/objects/objects.txt @@ -1410,3 +1410,9 @@ dstu4145le 2 9 : uacurve9 : DSTU curve 9 : AES-128-SIV : aes-128-siv : AES-192-SIV : aes-192-siv : AES-256-SIV : aes-256-siv + + +!Cname oracle +joint-iso-itu-t 16 840 1 113894 : oracle-organization : Oracle organization +# Jdk trustedKeyUsage attribute +oracle 746875 1 1 : oracle-jdk-trustedkeyusage : Trusted key usage (Oracle) diff --git a/crypto/pkcs12/p12_attr.c b/crypto/pkcs12/p12_attr.c index da228336e..991d6f445 100644 --- a/crypto/pkcs12/p12_attr.c +++ b/crypto/pkcs12/p12_attr.c @@ -119,3 +119,11 @@ PKCS12_SAFEBAG_get0_attrs(const PKCS12_SAFEBAG *bag) { return bag->attrib; } + +void PKCS12_SAFEBAG_set0_attrs(PKCS12_SAFEBAG *bag, const STACK_OF(X509_ATTRIBUTE) *attrs) +{ + if (bag->attrib != attrs) + sk_X509_ATTRIBUTE_free(bag->attrib); + + bag->attrib = (STACK_OF(X509_ATTRIBUTE*))attrs; +} diff --git a/crypto/pkcs12/p12_crt.c b/crypto/pkcs12/p12_crt.c index f0190761e..32ca3b1c4 100644 --- a/crypto/pkcs12/p12_crt.c +++ b/crypto/pkcs12/p12_crt.c @@ -14,6 +14,8 @@ static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, PKCS12_SAFEBAG *bag); +static int pkcs12_remove_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, + PKCS12_SAFEBAG *bag); static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid) { @@ -28,16 +30,17 @@ static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid) return 1; } -PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey, - X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, - int iter, int mac_iter, int keytype, - OSSL_LIB_CTX *ctx, const char *propq) +PKCS12 *PKCS12_create_ex2(const char *pass, const char *name, EVP_PKEY *pkey, + X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, + int iter, int mac_iter, int keytype, + OSSL_LIB_CTX *ctx, const char *propq, + PKCS12_create_cb *cb, void *cbarg) { PKCS12 *p12 = NULL; STACK_OF(PKCS7) *safes = NULL; STACK_OF(PKCS12_SAFEBAG) *bags = NULL; PKCS12_SAFEBAG *bag = NULL; - int i; + int i, cbret; unsigned char keyid[EVP_MAX_MD_SIZE]; unsigned int keyidlen = 0; @@ -69,12 +72,30 @@ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey, goto err; if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) goto err; + if (cb != NULL) { + cbret = cb(bag, cbarg); + if (cbret == -1) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CALLBACK_FAILED); + goto err; + } else if (cbret == 0) { + pkcs12_remove_bag(&bags, bag); + } + } } /* Add all other certificates */ for (i = 0; i < sk_X509_num(ca); i++) { - if (!PKCS12_add_cert(&bags, sk_X509_value(ca, i))) + if ((bag = PKCS12_add_cert(&bags, sk_X509_value(ca, i))) == NULL) goto err; + if (cb != NULL) { + cbret = cb(bag, cbarg); + if (cbret == -1) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CALLBACK_FAILED); + goto err; + } else if (cbret == 0) { + pkcs12_remove_bag(&bags, bag); + } + } } if (bags && !PKCS12_add_safe_ex(&safes, bags, nid_cert, iter, pass, @@ -100,6 +121,15 @@ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey, goto err; if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) goto err; + if (cb != NULL) { + cbret = cb(bag, cbarg); + if (cbret == -1) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CALLBACK_FAILED); + goto err; + } else if (cbret == 0) { + pkcs12_remove_bag(&bags, bag); + } + } } if (bags && !PKCS12_add_safe(&safes, bags, -1, 0, NULL)) @@ -131,6 +161,16 @@ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey, } +PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert, + STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, + int mac_iter, int keytype, + OSSL_LIB_CTX *ctx, const char *propq) +{ + return PKCS12_create_ex2(pass, name, pkey, cert, ca, nid_key, nid_cert, + iter, mac_iter, keytype, ctx, propq, + NULL, NULL); +} + PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, int mac_iter, int keytype) @@ -281,6 +321,22 @@ int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags, return PKCS12_add_safe_ex(psafes, bags, nid_safe, iter, pass, NULL, NULL); } + +static int pkcs12_remove_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, + PKCS12_SAFEBAG *bag) +{ + PKCS12_SAFEBAG *tmp; + + if (pbags == NULL || bag == NULL) + return 1; + + if ((tmp = sk_PKCS12_SAFEBAG_delete_ptr(*pbags, bag)) == NULL) + return 0; + + PKCS12_SAFEBAG_free(tmp); + return 1; +} + static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, PKCS12_SAFEBAG *bag) { diff --git a/crypto/pkcs12/pk12err.c b/crypto/pkcs12/pk12err.c index 6e3ec78cd..b53b0e0d0 100644 --- a/crypto/pkcs12/pk12err.c +++ b/crypto/pkcs12/pk12err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 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 @@ -15,6 +15,7 @@ #ifndef OPENSSL_NO_ERR static const ERR_STRING_DATA PKCS12_str_reasons[] = { + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_CALLBACK_FAILED), "callback failed"}, {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_CANT_PACK_STRUCTURE), "cant pack structure"}, {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_CONTENT_TYPE_NOT_DATA), diff --git a/doc/man3/PKCS12_SAFEBAG_set0_attrs.pod b/doc/man3/PKCS12_SAFEBAG_set0_attrs.pod new file mode 100644 index 000000000..98e212a9b --- /dev/null +++ b/doc/man3/PKCS12_SAFEBAG_set0_attrs.pod @@ -0,0 +1,32 @@ +=pod + +=head1 NAME + +PKCS12_SAFEBAG_set0_attrs +- Set attributes for a PKCS#12 safeBag + +=head1 SYNOPSIS + + #include + + void PKCS12_SAFEBAG_set0_attrs(PKCS12_SAFEBAG *bag, const STACK_OF(X509_ATTRIBUTE) *attrs); + +=head1 DESCRIPTION + +PKCS12_SAFEBAG_set0_attrs() assigns the stack of Bs to a +PKCS#12 safeBag. I is the B to assign the attributes to. + +=head1 RETURN VALUES + +PKCS12_SAFEBAG_set0_attrs() does not return a value. + +=head1 COPYRIGHT + +Copyright 2019-2022 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 +L. + +=cut diff --git a/fuzz/oids.txt b/fuzz/oids.txt index 813a0dc9e..250a696b4 100644 --- a/fuzz/oids.txt +++ b/fuzz/oids.txt @@ -925,3 +925,5 @@ OBJ_sm4_ccm="\x2A\x81\x1C\xCF\x55\x01\x68\x09" OBJ_zuc_128_eia3="\x2A\x81\x1C\xCF\x55\x01\x86\x22" OBJ_delegation_usage="\x2B\x06\x01\x04\x01\x82\xDA\x4B\x2C" OBJ_hmacWithSM3="\x2A\x81\x1C\xCF\x55\x01\x83\x11\x03\x01" +OBJ_oracle="\x60\x86\x48\x01\x86\xF9\x66" +OBJ_oracle_jdk_trustedkeyusage="\x60\x86\x48\x01\x86\xF9\x66\xAD\xCA\x7B\x01\x01" diff --git a/include/crypto/pkcs12err.h b/include/crypto/pkcs12err.h index 662f412e9..114971c60 100644 --- a/include/crypto/pkcs12err.h +++ b/include/crypto/pkcs12err.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2022 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 diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h index 1b89df7c4..6af577a66 100644 --- a/include/openssl/obj_mac.h +++ b/include/openssl/obj_mac.h @@ -4401,4 +4401,14 @@ #define LN_aes_256_siv "aes-256-siv" #define NID_aes_256_siv 1200 +#define SN_oracle "oracle-organization" +#define LN_oracle "Oracle organization" +#define NID_oracle 1258 +#define OBJ_oracle OBJ_joint_iso_itu_t,16L,840L,1L,113894L + +#define SN_oracle_jdk_trustedkeyusage "oracle-jdk-trustedkeyusage" +#define LN_oracle_jdk_trustedkeyusage "Trusted key usage (Oracle)" +#define NID_oracle_jdk_trustedkeyusage 1259 +#define OBJ_oracle_jdk_trustedkeyusage OBJ_oracle,746875L,1L,1L + #endif /* OPENSSL_OBJ_MAC_H */ diff --git a/include/openssl/pkcs12.h.in b/include/openssl/pkcs12.h.in index c98eebfb3..201dbd054 100644 --- a/include/openssl/pkcs12.h.in +++ b/include/openssl/pkcs12.h.in @@ -195,6 +195,7 @@ ASN1_TYPE *PKCS12_get_attr_gen(const STACK_OF(X509_ATTRIBUTE) *attrs, char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag); const STACK_OF(X509_ATTRIBUTE) * PKCS12_SAFEBAG_get0_attrs(const PKCS12_SAFEBAG *bag); +void PKCS12_SAFEBAG_set0_attrs(PKCS12_SAFEBAG *bag, const STACK_OF(X509_ATTRIBUTE) *attrs); unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor, const char *pass, int passlen, const unsigned char *in, int inlen, @@ -282,6 +283,7 @@ DECLARE_ASN1_ITEM(PKCS12_AUTHSAFES) void PKCS12_PBE_add(void); int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca); +typedef int PKCS12_create_cb(PKCS12_SAFEBAG *bag, void *cbarg); PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, int mac_iter, int keytype); @@ -289,6 +291,11 @@ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, int mac_iter, int keytype, OSSL_LIB_CTX *ctx, const char *propq); +PKCS12 *PKCS12_create_ex2(const char *pass, const char *name, EVP_PKEY *pkey, + X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, + int iter, int mac_iter, int keytype, + OSSL_LIB_CTX *ctx, const char *propq, + PKCS12_create_cb *cb, void *cbarg); PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert); PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, diff --git a/include/openssl/pkcs12err.h b/include/openssl/pkcs12err.h index 933c83299..abce37362 100644 --- a/include/openssl/pkcs12err.h +++ b/include/openssl/pkcs12err.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 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 @@ -21,6 +21,7 @@ /* * PKCS12 reason codes. */ +# define PKCS12_R_CALLBACK_FAILED 115 # define PKCS12_R_CANT_PACK_STRUCTURE 100 # define PKCS12_R_CONTENT_TYPE_NOT_DATA 121 # define PKCS12_R_DECODE_ERROR 101 diff --git a/test/helpers/pkcs12.c b/test/helpers/pkcs12.c index a87683dc9..a5ea0d33e 100644 --- a/test/helpers/pkcs12.c +++ b/test/helpers/pkcs12.c @@ -338,13 +338,15 @@ static STACK_OF(PKCS12_SAFEBAG) *decode_contentinfo(STACK_OF(PKCS7) *safes, int * PKCS12 safeBag/attribute builder */ -static int add_attributes(PKCS12_SAFEBAG *bag, const PKCS12_ATTR *attrs) +static int add_attributes(PKCS12_SAFEBAG *bag, const PKCS12_ATTR *attr) { int ret = 0; int attr_nid; - const PKCS12_ATTR *p_attr = attrs; + const PKCS12_ATTR *p_attr = attr; + STACK_OF(X509_ATTRIBUTE)* attrs = NULL; + X509_ATTRIBUTE *x509_attr = NULL; - if (attrs == NULL) + if (attr == NULL) return 1; while (p_attr->oid != NULL) { @@ -358,6 +360,12 @@ static int add_attributes(PKCS12_SAFEBAG *bag, const PKCS12_ATTR *attrs) if (!TEST_true(PKCS12_add_localkeyid(bag, (unsigned char *)p_attr->value, strlen(p_attr->value)))) goto err; + } else if (attr_nid == NID_oracle_jdk_trustedkeyusage) { + attrs = (STACK_OF(X509_ATTRIBUTE)*)PKCS12_SAFEBAG_get0_attrs(bag); + x509_attr = X509_ATTRIBUTE_create(attr_nid, V_ASN1_OBJECT, OBJ_txt2obj(p_attr->value, 0)); + X509at_add1_attr(&attrs, x509_attr); + PKCS12_SAFEBAG_set0_attrs(bag, attrs); + X509_ATTRIBUTE_free(x509_attr); } else { /* Custom attribute values limited to ASCII in these tests */ if (!TEST_true(PKCS12_add1_attr_by_txt(bag, p_attr->oid, MBSTRING_ASC, diff --git a/test/helpers/pkcs12.h b/test/helpers/pkcs12.h index d1a3b93d3..f09013222 100644 --- a/test/helpers/pkcs12.h +++ b/test/helpers/pkcs12.h @@ -82,6 +82,7 @@ void add_keybag(PKCS12_BUILDER *pb, const unsigned char *bytes, int len, const PKCS12_ATTR *attrs, const PKCS12_ENC *enc); void add_secretbag(PKCS12_BUILDER *pb, int secret_nid, const char *secret, const PKCS12_ATTR *attrs); +void add_extra_attr(PKCS12_BUILDER *pb); /* Decode/check functions */ void start_check_pkcs12(PKCS12_BUILDER *pb); diff --git a/test/pkcs12_api_test.c b/test/pkcs12_api_test.c index 51976edea..eebd78827 100644 --- a/test/pkcs12_api_test.c +++ b/test/pkcs12_api_test.c @@ -94,6 +94,98 @@ static int pkcs12_parse_test(void) return TEST_true(ret); } +static int pkcs12_create_cb(PKCS12_SAFEBAG *bag, void *cbarg) +{ + int cb_ret = *((int*)cbarg); + return cb_ret; +} + +static PKCS12 *pkcs12_create_ex2_setup(EVP_PKEY **key, X509 **cert, STACK_OF(X509) **ca) +{ + PKCS12 *p12 = NULL; + p12 = PKCS12_load("out6.p12"); + if (!TEST_ptr(p12)) + goto err; + + if (!TEST_true(PKCS12_parse(p12, "", key, cert, ca))) + goto err; + + return p12; +err: + PKCS12_free(p12); + return NULL; +} + +static int pkcs12_create_ex2_test(int test) +{ + int ret = 0, cb_ret = 0; + PKCS12 *ptr = NULL, *p12 = NULL; + EVP_PKEY *key = NULL; + X509 *cert = NULL; + STACK_OF(X509) *ca = NULL; + + p12 = pkcs12_create_ex2_setup(&key, &cert, &ca); + if (!TEST_ptr(p12)) + goto err; + + if (test == 0) { + /* Confirm PKCS12_create_ex2 returns NULL */ + ptr = PKCS12_create_ex2(NULL, NULL, NULL, + NULL, NULL, NID_undef, NID_undef, + 0, 0, 0, + NULL, NULL, + NULL, NULL); + if (TEST_ptr(ptr)) + goto err; + + /* Can't proceed without a valid cert at least */ + if (!TEST_ptr(cert)) + goto err; + + /* Specified call back called - return success */ + cb_ret = 1; + ptr = PKCS12_create_ex2(NULL, NULL, NULL, + cert, NULL, NID_undef, NID_undef, + 0, 0, 0, + NULL, NULL, + pkcs12_create_cb, (void*)&cb_ret); + /* PKCS12 successfully created */ + if (!TEST_ptr(ptr)) + goto err; + } else if (test == 1) { + /* Specified call back called - return error*/ + cb_ret = -1; + ptr = PKCS12_create_ex2(NULL, NULL, NULL, + cert, NULL, NID_undef, NID_undef, + 0, 0, 0, + NULL, NULL, + pkcs12_create_cb, (void*)&cb_ret); + /* PKCS12 not created */ + if (TEST_ptr(ptr)) + goto err; + } else if (test == 2) { + /* Specified call back called - return failure */ + cb_ret = 0; + ptr = PKCS12_create_ex2(NULL, NULL, NULL, + cert, NULL, NID_undef, NID_undef, + 0, 0, 0, + NULL, NULL, + pkcs12_create_cb, (void*)&cb_ret); + /* PKCS12 successfully created */ + if (!TEST_ptr(ptr)) + goto err; + } + + ret = 1; +err: + PKCS12_free(p12); + PKCS12_free(ptr); + EVP_PKEY_free(key); + X509_free(cert); + OSSL_STACK_OF_X509_free(ca); + return TEST_true(ret); +} + typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, @@ -157,7 +249,7 @@ int setup_tests(void) ADD_TEST(test_null_args); ADD_TEST(pkcs12_parse_test); - + ADD_ALL_TESTS(pkcs12_create_ex2_test, 3); return 1; } diff --git a/test/pkcs12_format_test.c b/test/pkcs12_format_test.c index 7315b16b3..258a78d80 100644 --- a/test/pkcs12_format_test.c +++ b/test/pkcs12_format_test.c @@ -205,6 +205,19 @@ static const PKCS12_ATTR ATTRS2[] = { { NULL, NULL } }; +static const PKCS12_ATTR ATTRS3[] = { + { "friendlyName", "wildduk" }, + { "localKeyID", "1122334455" }, + { "oracle-jdk-trustedkeyusage", "anyExtendedKeyUsage" }, + { NULL, NULL } +}; + +static const PKCS12_ATTR ATTRS4[] = { + { "friendlyName", "wildduk" }, + { "localKeyID", "1122334455" }, + { NULL, NULL } +}; + static const PKCS12_ENC enc_default = { #ifndef OPENSSL_NO_DES NID_pbe_WithSHA1And3_Key_TripleDES_CBC, @@ -688,6 +701,84 @@ static int test_multiple_contents(void) return end_pkcs12_builder(pb); } +static int test_jdk_trusted_attr(void) +{ + PKCS12_BUILDER *pb = new_pkcs12_builder("jdk_trusted.p12"); + + /* Generate/encode */ + start_pkcs12(pb); + + start_contentinfo(pb); + + add_certbag(pb, CERT1, sizeof(CERT1), ATTRS3); + + end_contentinfo(pb); + + end_pkcs12_with_mac(pb, &mac_default); + + /* Read/decode */ + start_check_pkcs12_with_mac(pb, &mac_default); + + start_check_contentinfo(pb); + + check_certbag(pb, CERT1, sizeof(CERT1), ATTRS3); + + end_check_contentinfo(pb); + + end_check_pkcs12(pb); + + return end_pkcs12_builder(pb); +} + +static int test_set0_attrs(void) +{ + PKCS12_BUILDER *pb = new_pkcs12_builder("attrs.p12"); + PKCS12_SAFEBAG *bag = NULL; + STACK_OF(X509_ATTRIBUTE) *attrs = NULL; + X509_ATTRIBUTE *attr = NULL; + + start_pkcs12(pb); + + start_contentinfo(pb); + + /* Add cert and attrs (name/locakkey only) */ + add_certbag(pb, CERT1, sizeof(CERT1), ATTRS4); + + bag = sk_PKCS12_SAFEBAG_value(pb->bags, 0); + attrs = (STACK_OF(X509_ATTRIBUTE)*)PKCS12_SAFEBAG_get0_attrs(bag); + + /* Create new attr, add to list and confirm return attrs is not NULL */ + attr = X509_ATTRIBUTE_create(NID_oracle_jdk_trustedkeyusage, V_ASN1_OBJECT, OBJ_txt2obj("anyExtendedKeyUsage", 0)); + X509at_add1_attr(&attrs, attr); + PKCS12_SAFEBAG_set0_attrs(bag, attrs); + attrs = (STACK_OF(X509_ATTRIBUTE)*)PKCS12_SAFEBAG_get0_attrs(bag); + X509_ATTRIBUTE_free(attr); + if(!TEST_ptr(attrs)) { + goto err; + } + + end_contentinfo(pb); + + end_pkcs12(pb); + + /* Read/decode */ + start_check_pkcs12(pb); + + start_check_contentinfo(pb); + + /* Use existing check functionality to confirm cert bag attrs identical to ATTRS3 */ + check_certbag(pb, CERT1, sizeof(CERT1), ATTRS3); + + end_check_contentinfo(pb); + + end_check_pkcs12(pb); + + return end_pkcs12_builder(pb); + +err: + return 0; +} + #ifndef OPENSSL_NO_DES static int pkcs12_create_test(void) { @@ -863,6 +954,8 @@ int setup_tests(void) ADD_TEST(test_cert_key_encrypted_content); ADD_TEST(test_single_secret_encrypted_content); ADD_TEST(test_multiple_contents); + ADD_TEST(test_jdk_trusted_attr); + ADD_TEST(test_set0_attrs); return 1; } diff --git a/test/recipes/80-test_pkcs12.t b/test/recipes/80-test_pkcs12.t index eebbfe8ef..0f42602cc 100644 --- a/test/recipes/80-test_pkcs12.t +++ b/test/recipes/80-test_pkcs12.t @@ -54,7 +54,7 @@ if (eval { require Win32::API; 1; }) { } $ENV{OPENSSL_WIN32_UTF8}=1; -plan tests => 21; +plan tests => 24; # Test different PKCS#12 formats ok(run(test(["pkcs12_format_test"])), "test pkcs12 formats"); @@ -76,6 +76,7 @@ my $outfile3 = "out3.p12"; my $outfile4 = "out4.p12"; my $outfile5 = "out5.p12"; my $outfile6 = "out6.p12"; +my $outfile7 = "out7.p12"; # Test the -chain option with -untrusted ok(run(app(["openssl", "pkcs12", "-export", "-chain", @@ -128,9 +129,14 @@ my @pkcs12info = run(app(["openssl", "pkcs12", "-info", "-in", $outfile5, # Test that with one input certificate, we get one output certificate ok(grep(/subject=CN = server.example/, @pkcs12info) == 1, "test one cert in output"); + # Test that the expected friendly name is present in the output ok(grep(/testname/, @pkcs12info) == 1, "test friendly name in output"); +# Test there's no Oracle Trusted Key Usage bag attribute +ok(grep(/Trusted key usage (Oracle)/, @pkcs12info) == 0, + "test no oracle trusted key usage"); + # Test export of PEM file with both cert and key, without password. # -nomac necessary to avoid legacy provider requirement { @@ -146,6 +152,22 @@ ok(grep(/testname/, @pkcs12info) == 1, "test friendly name in output"); ok(scalar @match > 0 ? 0 : 1, "test_export_pkcs12_outerr6_empty"); } +# Test with Oracle Trusted Key Usage specified in openssl.cnf +{ + $ENV{OPENSSL_CONF} = srctop_file("test", "recipes", "80-test_pkcs12_data", "jdk_trusted.cnf"); + ok(run(app(["openssl", "pkcs12", "-export", "-out", $outfile7, + "-in", srctop_file(@path, "ee-cert.pem"), + "-nokeys", "-passout", "pass:", "-certpbe", "NONE"])), + "test nokeys single cert"); + + my @pkcs12info = run(app(["openssl", "pkcs12", "-info", "-in", $outfile7, + "-passin", "pass:"]), capture => 1); + ok(grep(/Trusted key usage \(Oracle\): Any Extended Key Usage \(2.5.29.37.0\)/, @pkcs12info) == 1, + "test oracle trusted key usage is set"); + + delete $ENV{OPENSSL_CONF} +} + # Tests for pkcs12_parse ok(run(test(["pkcs12_api_test", "-in", $outfile1, diff --git a/test/recipes/80-test_pkcs12_data/jdk_trusted.cnf b/test/recipes/80-test_pkcs12_data/jdk_trusted.cnf new file mode 100644 index 000000000..57d11fccf --- /dev/null +++ b/test/recipes/80-test_pkcs12_data/jdk_trusted.cnf @@ -0,0 +1,8 @@ +# +[pkcs12] +certBagAttr = cb_attr + +# Uncomment this if you need Java compatible PKCS12 files +[cb_attr] +jdkTrustedKeyUsage = anyExtendedKeyUsage + diff --git a/util/libcrypto.num b/util/libcrypto.num index 8a538ff70..3bbe2eb22 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5638,3 +5638,5 @@ SM2_THRESHOLD_sign3 5953 3_0_3 EXIST::FUNCTION:SM2_THRESHOLD SM2_THRESHOLD_decrypt1 5954 3_0_3 EXIST::FUNCTION:SM2_THRESHOLD SM2_THRESHOLD_decrypt2 5955 3_0_3 EXIST::FUNCTION:SM2_THRESHOLD SM2_THRESHOLD_decrypt3 5956 3_0_3 EXIST::FUNCTION:SM2_THRESHOLD +PKCS12_SAFEBAG_set0_attrs 5957 3_0_3 EXIST::FUNCTION: +PKCS12_create_ex2 5958 3_0_3 EXIST::FUNCTION: diff --git a/util/other.syms b/util/other.syms index 4eb499750..d643f5cad 100644 --- a/util/other.syms +++ b/util/other.syms @@ -137,6 +137,7 @@ custom_ext_free_cb datatype custom_ext_parse_cb datatype pem_password_cb datatype ssl_ct_validation_cb datatype +PKCS12_create_cb datatype # ASN1_BIT_STRING_digest define BIO_append_filename define From 82444f64dd4ac8fdbc11082ee9c25157db2c4bdd Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 17:34:27 +0800 Subject: [PATCH 15/66] PKCS12 - Add additional libctx and propq support. Fixes #19718 Fixes #19716 Added PKCS12_SAFEBAG_get1_cert_ex(), PKCS12_SAFEBAG_get1_crl_ex() and ASN1_item_unpack_ex(). parse_bag and parse_bags now use the libctx/propq stored in the P7_CTX. PKCS12_free() needed to be manually constructed in order to free the propq. pkcs12_api_test.c changed so that it actually tests the libctx, propq. Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/19942) --- crypto/asn1/asn_pack.c | 13 +++++++++++++ crypto/objects/obj_dat.h | 2 +- crypto/objects/obj_xref.h | 2 +- crypto/pkcs12/p12_add.c | 12 +++++++++--- crypto/pkcs12/p12_asn.c | 17 ++++++++++++++++- crypto/pkcs12/p12_init.c | 6 ++++++ crypto/pkcs12/p12_kiss.c | 30 +++++++++++++++++++----------- crypto/pkcs12/p12_local.h | 2 ++ crypto/pkcs12/p12_sbag.c | 37 +++++++++++++++++++++++++++++++++++++ crypto/pkcs12/p12_utl.c | 28 ++++++++++++++++++++++++++-- fuzz/oids.txt | 2 +- include/openssl/asn1.h.in | 2 ++ include/openssl/obj_mac.h | 2 +- include/openssl/pkcs12.h.in | 2 ++ test/pkcs12_api_test.c | 20 ++++++++++---------- util/libcrypto.num | 3 +++ 16 files changed, 149 insertions(+), 31 deletions(-) diff --git a/crypto/asn1/asn_pack.c b/crypto/asn1/asn_pack.c index 292e6d817..bdddc7ccb 100644 --- a/crypto/asn1/asn_pack.c +++ b/crypto/asn1/asn_pack.c @@ -60,3 +60,16 @@ void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it) ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR); return ret; } + +void *ASN1_item_unpack_ex(const ASN1_STRING *oct, const ASN1_ITEM *it, + OSSL_LIB_CTX *libctx, const char *propq) +{ + const unsigned char *p; + void *ret; + + p = oct->data; + if ((ret = ASN1_item_d2i_ex(NULL, &p, oct->length, it,\ + libctx, propq)) == NULL) + ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR); + return ret; +} diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h index afcfc7890..0228fd0b7 100644 --- a/crypto/objects/obj_dat.h +++ b/crypto/objects/obj_dat.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by crypto/objects/obj_dat.pl * - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 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 diff --git a/crypto/objects/obj_xref.h b/crypto/objects/obj_xref.h index cb6c67986..468766a34 100644 --- a/crypto/objects/obj_xref.h +++ b/crypto/objects/obj_xref.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by objxref.pl * - * Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2024 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 diff --git a/crypto/pkcs12/p12_add.c b/crypto/pkcs12/p12_add.c index 6fd4184af..d905c7d9f 100644 --- a/crypto/pkcs12/p12_add.c +++ b/crypto/pkcs12/p12_add.c @@ -78,7 +78,9 @@ STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7) ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CONTENT_TYPE_NOT_DATA); return NULL; } - return ASN1_item_unpack(p7->d.data, ASN1_ITEM_rptr(PKCS12_SAFEBAGS)); + return ASN1_item_unpack_ex(p7->d.data, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), + ossl_pkcs7_ctx_get0_libctx(&p7->ctx), + ossl_pkcs7_ctx_get0_propq(&p7->ctx)); } /* Turn a stack of SAFEBAGS into a PKCS#7 encrypted data ContentInfo */ @@ -181,6 +183,7 @@ int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes) STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12) { STACK_OF(PKCS7) *p7s; + PKCS7_CTX *p7ctx; PKCS7 *p7; int i; @@ -188,8 +191,11 @@ STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12) ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CONTENT_TYPE_NOT_DATA); return NULL; } - p7s = ASN1_item_unpack(p12->authsafes->d.data, - ASN1_ITEM_rptr(PKCS12_AUTHSAFES)); + p7ctx = &p12->authsafes->ctx; + p7s = ASN1_item_unpack_ex(p12->authsafes->d.data, + ASN1_ITEM_rptr(PKCS12_AUTHSAFES), + ossl_pkcs7_ctx_get0_libctx(p7ctx), + ossl_pkcs7_ctx_get0_propq(p7ctx)); if (p7s != NULL) { for (i = 0; i < sk_PKCS7_num(p7s); i++) { p7 = sk_PKCS7_value(p7s, i); diff --git a/crypto/pkcs12/p12_asn.c b/crypto/pkcs12/p12_asn.c index aabbd38ee..caae639f8 100644 --- a/crypto/pkcs12/p12_asn.c +++ b/crypto/pkcs12/p12_asn.c @@ -12,6 +12,7 @@ #include #include #include "p12_local.h" +#include "crypto/pkcs7.h" /* PKCS#12 ASN1 module */ @@ -21,7 +22,21 @@ ASN1_SEQUENCE(PKCS12) = { ASN1_OPT(PKCS12, mac, PKCS12_MAC_DATA) } ASN1_SEQUENCE_END(PKCS12) -IMPLEMENT_ASN1_FUNCTIONS(PKCS12) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(PKCS12, PKCS12, PKCS12) + +PKCS12 *PKCS12_new(void) +{ + return (PKCS12 *)ASN1_item_new(ASN1_ITEM_rptr(PKCS12)); +} + +void PKCS12_free(PKCS12 *p12) +{ + if (p12 != NULL && p12->authsafes != NULL) { + OPENSSL_free(p12->authsafes->ctx.propq); + p12->authsafes->ctx.propq = NULL; + } + ASN1_item_free((ASN1_VALUE *)p12, ASN1_ITEM_rptr(PKCS12)); +} ASN1_SEQUENCE(PKCS12_MAC_DATA) = { ASN1_SIMPLE(PKCS12_MAC_DATA, dinfo, X509_SIG), diff --git a/crypto/pkcs12/p12_init.c b/crypto/pkcs12/p12_init.c index 45aa2f915..366f9ec7d 100644 --- a/crypto/pkcs12/p12_init.c +++ b/crypto/pkcs12/p12_init.c @@ -56,3 +56,9 @@ PKCS12 *PKCS12_init(int mode) return PKCS12_init_ex(mode, NULL, NULL); } +const PKCS7_CTX *ossl_pkcs12_get0_pkcs7ctx(const PKCS12 *p12) +{ + if (p12 == NULL || p12->authsafes == NULL) + return NULL; + return &p12->authsafes->ctx; +} diff --git a/crypto/pkcs12/p12_kiss.c b/crypto/pkcs12/p12_kiss.c index 1d3985593..a17a49e51 100644 --- a/crypto/pkcs12/p12_kiss.c +++ b/crypto/pkcs12/p12_kiss.c @@ -18,10 +18,12 @@ static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts); static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, - int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts); + int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts, + OSSL_LIB_CTX *libctx, const char *propq); static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, - EVP_PKEY **pkey, STACK_OF(X509) *ocerts); + EVP_PKEY **pkey, STACK_OF(X509) *ocerts, + OSSL_LIB_CTX *libctx, const char *propq); /* * Parse and decrypt a PKCS#12 structure returning user key, user cert and @@ -157,7 +159,8 @@ static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; } - if (!parse_bags(bags, pass, passlen, pkey, ocerts)) { + if (!parse_bags(bags, pass, passlen, pkey, ocerts, + p7->ctx.libctx, p7->ctx.propq)) { sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; @@ -170,12 +173,14 @@ static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, /* pkey and/or ocerts may be NULL */ static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, - int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts) + int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts, + OSSL_LIB_CTX *libctx, const char *propq) { int i; for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { if (!parse_bag(sk_PKCS12_SAFEBAG_value(bags, i), - pass, passlen, pkey, ocerts)) + pass, passlen, pkey, ocerts, + libctx, propq)) return 0; } return 1; @@ -183,7 +188,8 @@ static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, /* pkey and/or ocerts may be NULL */ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, - EVP_PKEY **pkey, STACK_OF(X509) *ocerts) + EVP_PKEY **pkey, STACK_OF(X509) *ocerts, + OSSL_LIB_CTX *libctx, const char *propq) { PKCS8_PRIV_KEY_INFO *p8; X509 *x509; @@ -201,7 +207,8 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, case NID_keyBag: if (pkey == NULL || *pkey != NULL) return 1; - *pkey = EVP_PKCS82PKEY(PKCS12_SAFEBAG_get0_p8inf(bag)); + *pkey = EVP_PKCS82PKEY_ex(PKCS12_SAFEBAG_get0_p8inf(bag), + libctx, propq); if (*pkey == NULL) return 0; break; @@ -209,9 +216,10 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, case NID_pkcs8ShroudedKeyBag: if (pkey == NULL || *pkey != NULL) return 1; - if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL) + if ((p8 = PKCS12_decrypt_skey_ex(bag, pass, passlen, + libctx, propq)) == NULL) return 0; - *pkey = EVP_PKCS82PKEY(p8); + *pkey = EVP_PKCS82PKEY_ex(p8, libctx, propq); PKCS8_PRIV_KEY_INFO_free(p8); if (!(*pkey)) return 0; @@ -221,7 +229,7 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, if (ocerts == NULL || PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate) return 1; - if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL) + if ((x509 = PKCS12_SAFEBAG_get1_cert_ex(bag, libctx, propq)) == NULL) return 0; if (lkid && !X509_keyid_set1(x509, lkid->data, lkid->length)) { X509_free(x509); @@ -251,7 +259,7 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, case NID_safeContentsBag: return parse_bags(PKCS12_SAFEBAG_get0_safes(bag), pass, passlen, pkey, - ocerts); + ocerts, libctx, propq); default: return 1; diff --git a/crypto/pkcs12/p12_local.h b/crypto/pkcs12/p12_local.h index acaa27b19..97697922b 100644 --- a/crypto/pkcs12/p12_local.h +++ b/crypto/pkcs12/p12_local.h @@ -41,3 +41,5 @@ struct pkcs12_bag_st { ASN1_TYPE *other; /* Secret or other bag */ } value; }; + +const PKCS7_CTX *ossl_pkcs12_get0_pkcs7ctx(const PKCS12 *p12); diff --git a/crypto/pkcs12/p12_sbag.c b/crypto/pkcs12/p12_sbag.c index 7574c5412..823c696ff 100644 --- a/crypto/pkcs12/p12_sbag.c +++ b/crypto/pkcs12/p12_sbag.c @@ -11,6 +11,7 @@ #include "internal/cryptlib.h" #include #include "p12_local.h" +#include "crypto/x509.h" #ifndef OPENSSL_NO_DEPRECATED_1_1_0 ASN1_TYPE *PKCS12_get_attr(const PKCS12_SAFEBAG *bag, int attr_nid) @@ -101,6 +102,42 @@ X509_CRL *PKCS12_SAFEBAG_get1_crl(const PKCS12_SAFEBAG *bag) ASN1_ITEM_rptr(X509_CRL)); } +X509 *PKCS12_SAFEBAG_get1_cert_ex(const PKCS12_SAFEBAG *bag, + OSSL_LIB_CTX *libctx, const char *propq) +{ + X509 *ret = NULL; + + if (PKCS12_SAFEBAG_get_nid(bag) != NID_certBag) + return NULL; + if (OBJ_obj2nid(bag->value.bag->type) != NID_x509Certificate) + return NULL; + ret = ASN1_item_unpack_ex(bag->value.bag->value.octet, + ASN1_ITEM_rptr(X509), libctx, propq); + if (!ossl_x509_set0_libctx(ret, libctx, propq)) { + X509_free(ret); + return NULL; + } + return ret; +} + +X509_CRL *PKCS12_SAFEBAG_get1_crl_ex(const PKCS12_SAFEBAG *bag, + OSSL_LIB_CTX *libctx, const char *propq) +{ + X509_CRL *ret = NULL; + + if (PKCS12_SAFEBAG_get_nid(bag) != NID_crlBag) + return NULL; + if (OBJ_obj2nid(bag->value.bag->type) != NID_x509Crl) + return NULL; + ret = ASN1_item_unpack_ex(bag->value.bag->value.octet, + ASN1_ITEM_rptr(X509_CRL), libctx, propq); + if (!ossl_x509_crl_set0_libctx(ret, libctx, propq)) { + X509_CRL_free(ret); + return NULL; + } + return ret; +} + PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_cert(X509 *x509) { return PKCS12_item_pack_safebag(x509, ASN1_ITEM_rptr(X509), diff --git a/crypto/pkcs12/p12_utl.c b/crypto/pkcs12/p12_utl.c index 3afc8b2f1..2fa2cfdc3 100644 --- a/crypto/pkcs12/p12_utl.c +++ b/crypto/pkcs12/p12_utl.c @@ -10,6 +10,8 @@ #include #include "internal/cryptlib.h" #include +#include "p12_local.h" +#include "crypto/pkcs7/pk7_local.h" /* Cheap and nasty Unicode stuff */ @@ -238,12 +240,34 @@ int i2d_PKCS12_fp(FILE *fp, const PKCS12 *p12) PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12) { - return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS12), bp, p12); + OSSL_LIB_CTX *libctx = NULL; + const char *propq = NULL; + const PKCS7_CTX *p7ctx = NULL; + + if (p12 != NULL) { + p7ctx = ossl_pkcs12_get0_pkcs7ctx(*p12); + if (p7ctx != NULL) { + libctx = ossl_pkcs7_ctx_get0_libctx(p7ctx); + propq = ossl_pkcs7_ctx_get0_propq(p7ctx); + } + } + return ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(PKCS12), bp, p12, libctx, propq); } #ifndef OPENSSL_NO_STDIO PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12) { - return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS12), fp, p12); + OSSL_LIB_CTX *libctx = NULL; + const char *propq = NULL; + const PKCS7_CTX *p7ctx = NULL; + + if (p12 != NULL) { + p7ctx = ossl_pkcs12_get0_pkcs7ctx(*p12); + if (p7ctx != NULL) { + libctx = ossl_pkcs7_ctx_get0_libctx(p7ctx); + propq = ossl_pkcs7_ctx_get0_propq(p7ctx); + } + } + return ASN1_item_d2i_fp_ex(ASN1_ITEM_rptr(PKCS12), fp, p12, libctx, propq); } #endif diff --git a/fuzz/oids.txt b/fuzz/oids.txt index 250a696b4..093446094 100644 --- a/fuzz/oids.txt +++ b/fuzz/oids.txt @@ -1,7 +1,7 @@ # WARNING: do not edit! # Generated by fuzz/mkfuzzoids.pl # -# Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2020-2024 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 diff --git a/include/openssl/asn1.h.in b/include/openssl/asn1.h.in index dcd3500f5..494a36391 100644 --- a/include/openssl/asn1.h.in +++ b/include/openssl/asn1.h.in @@ -840,6 +840,8 @@ int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num, unsigned char *data, int max_len); void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it); +void *ASN1_item_unpack_ex(const ASN1_STRING *oct, const ASN1_ITEM *it, + OSSL_LIB_CTX *libctx, const char *propq); ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct); diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h index 6af577a66..242d7b933 100644 --- a/include/openssl/obj_mac.h +++ b/include/openssl/obj_mac.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by crypto/objects/objects.pl * - * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2024 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 diff --git a/include/openssl/pkcs12.h.in b/include/openssl/pkcs12.h.in index 201dbd054..b97b980ae 100644 --- a/include/openssl/pkcs12.h.in +++ b/include/openssl/pkcs12.h.in @@ -107,7 +107,9 @@ int PKCS12_SAFEBAG_get_bag_nid(const PKCS12_SAFEBAG *bag); const ASN1_TYPE *PKCS12_SAFEBAG_get0_bag_obj(const PKCS12_SAFEBAG *bag); const ASN1_OBJECT *PKCS12_SAFEBAG_get0_bag_type(const PKCS12_SAFEBAG *bag); +X509 *PKCS12_SAFEBAG_get1_cert_ex(const PKCS12_SAFEBAG *bag, OSSL_LIB_CTX *libctx, const char *propq); X509 *PKCS12_SAFEBAG_get1_cert(const PKCS12_SAFEBAG *bag); +X509_CRL *PKCS12_SAFEBAG_get1_crl_ex(const PKCS12_SAFEBAG *bag, OSSL_LIB_CTX *libctx, const char *propq); X509_CRL *PKCS12_SAFEBAG_get1_crl(const PKCS12_SAFEBAG *bag); const STACK_OF(PKCS12_SAFEBAG) * PKCS12_SAFEBAG_get0_safes(const PKCS12_SAFEBAG *bag); diff --git a/test/pkcs12_api_test.c b/test/pkcs12_api_test.c index eebd78827..718678446 100644 --- a/test/pkcs12_api_test.c +++ b/test/pkcs12_api_test.c @@ -23,7 +23,6 @@ static OSSL_LIB_CTX *testctx = NULL; static OSSL_PROVIDER *nullprov = NULL; -static OSSL_PROVIDER *deflprov = NULL; static int test_null_args(void) { @@ -39,7 +38,7 @@ static PKCS12 *PKCS12_load(const char *fpath) if (!TEST_ptr(bio)) goto err; - p12 = PKCS12_init(NID_pkcs7_data); + p12 = PKCS12_init_ex(NID_pkcs7_data, testctx, "provider=default"); if (!TEST_ptr(p12)) goto err; @@ -133,7 +132,7 @@ static int pkcs12_create_ex2_test(int test) ptr = PKCS12_create_ex2(NULL, NULL, NULL, NULL, NULL, NID_undef, NID_undef, 0, 0, 0, - NULL, NULL, + testctx, NULL, NULL, NULL); if (TEST_ptr(ptr)) goto err; @@ -147,7 +146,7 @@ static int pkcs12_create_ex2_test(int test) ptr = PKCS12_create_ex2(NULL, NULL, NULL, cert, NULL, NID_undef, NID_undef, 0, 0, 0, - NULL, NULL, + testctx, NULL, pkcs12_create_cb, (void*)&cb_ret); /* PKCS12 successfully created */ if (!TEST_ptr(ptr)) @@ -158,7 +157,7 @@ static int pkcs12_create_ex2_test(int test) ptr = PKCS12_create_ex2(NULL, NULL, NULL, cert, NULL, NID_undef, NID_undef, 0, 0, 0, - NULL, NULL, + testctx, NULL, pkcs12_create_cb, (void*)&cb_ret); /* PKCS12 not created */ if (TEST_ptr(ptr)) @@ -169,7 +168,7 @@ static int pkcs12_create_ex2_test(int test) ptr = PKCS12_create_ex2(NULL, NULL, NULL, cert, NULL, NID_undef, NID_undef, 0, 0, 0, - NULL, NULL, + testctx, NULL, pkcs12_create_cb, (void*)&cb_ret); /* PKCS12 successfully created */ if (!TEST_ptr(ptr)) @@ -243,9 +242,11 @@ int setup_tests(void) } } - deflprov = OSSL_PROVIDER_load(testctx, "default"); - if (!TEST_ptr(deflprov)) + if (!test_get_libctx(&testctx, &nullprov, NULL, NULL, NULL)) { + OSSL_LIB_CTX_free(testctx); + testctx = NULL; return 0; + } ADD_TEST(test_null_args); ADD_TEST(pkcs12_parse_test); @@ -255,7 +256,6 @@ int setup_tests(void) void cleanup_tests(void) { - OSSL_PROVIDER_unload(nullprov); - OSSL_PROVIDER_unload(deflprov); OSSL_LIB_CTX_free(testctx); + OSSL_PROVIDER_unload(nullprov); } diff --git a/util/libcrypto.num b/util/libcrypto.num index 3bbe2eb22..68c6edbf5 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5640,3 +5640,6 @@ SM2_THRESHOLD_decrypt2 5955 3_0_3 EXIST::FUNCTION:SM2_THRESHOLD SM2_THRESHOLD_decrypt3 5956 3_0_3 EXIST::FUNCTION:SM2_THRESHOLD PKCS12_SAFEBAG_set0_attrs 5957 3_0_3 EXIST::FUNCTION: PKCS12_create_ex2 5958 3_0_3 EXIST::FUNCTION: +ASN1_item_unpack_ex 5960 3_0_3 EXIST::FUNCTION: +PKCS12_SAFEBAG_get1_cert_ex 5961 3_0_3 EXIST::FUNCTION: +PKCS12_SAFEBAG_get1_crl_ex 5962 3_0_3 EXIST::FUNCTION: From d865b99d7963163678c44ee718ec9a52274661de Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 17:36:30 +0800 Subject: [PATCH 16/66] Fix PKCS12_newpass() to work with PBES2. Fixes #19092 The code looks like it was written to work with PBES1. As it had no tests, this would of then broken when PBES2 was introduced at a later point. Also added libctx and propq support. This affects the shroudedkeybag object. Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/20134) --- crypto/pkcs12/p12_npas.c | 145 +++++++++++++++++++++++++++++---------- test/pkcs12_api_test.c | 43 +++++++++++- 2 files changed, 151 insertions(+), 37 deletions(-) diff --git a/crypto/pkcs12/p12_npas.c b/crypto/pkcs12/p12_npas.c index 62230bc61..90139100c 100644 --- a/crypto/pkcs12/p12_npas.c +++ b/crypto/pkcs12/p12_npas.c @@ -19,11 +19,13 @@ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass); static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass, - const char *newpass); + const char *newpass, + OSSL_LIB_CTX *libctx, const char *propq); static int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass, - const char *newpass); + const char *newpass, + OSSL_LIB_CTX *libctx, const char *propq); static int alg_get(const X509_ALGOR *alg, int *pnid, int *piter, - int *psaltlen); + int *psaltlen, int *cipherid); /* * Change the password on a PKCS#12 structure. @@ -39,12 +41,12 @@ int PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass) } /* Check the mac */ - - if (!PKCS12_verify_mac(p12, oldpass, -1)) { - ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE); - return 0; + if (p12->mac != NULL) { + if (!PKCS12_verify_mac(p12, oldpass, -1)) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE); + return 0; + } } - if (!newpass_p12(p12, oldpass, newpass)) { ERR_raise(ERR_LIB_PKCS12, PKCS12_R_PARSE_ERROR); return 0; @@ -59,7 +61,7 @@ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) { STACK_OF(PKCS7) *asafes = NULL, *newsafes = NULL; STACK_OF(PKCS12_SAFEBAG) *bags = NULL; - int i, bagnid, pbe_nid = 0, pbe_iter = 0, pbe_saltlen = 0; + int i, bagnid, pbe_nid = 0, pbe_iter = 0, pbe_saltlen = 0, cipherid = NID_undef; PKCS7 *p7, *p7new; ASN1_OCTET_STRING *p12_data_tmp = NULL, *macoct = NULL; unsigned char mac[EVP_MAX_MD_SIZE]; @@ -72,27 +74,30 @@ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) goto err; for (i = 0; i < sk_PKCS7_num(asafes); i++) { p7 = sk_PKCS7_value(asafes, i); + bagnid = OBJ_obj2nid(p7->type); if (bagnid == NID_pkcs7_data) { bags = PKCS12_unpack_p7data(p7); } else if (bagnid == NID_pkcs7_encrypted) { bags = PKCS12_unpack_p7encdata(p7, oldpass, -1); if (!alg_get(p7->d.encrypted->enc_data->algorithm, - &pbe_nid, &pbe_iter, &pbe_saltlen)) + &pbe_nid, &pbe_iter, &pbe_saltlen, &cipherid)) goto err; } else { continue; } if (bags == NULL) goto err; - if (!newpass_bags(bags, oldpass, newpass)) + if (!newpass_bags(bags, oldpass, newpass, + p7->ctx.libctx, p7->ctx.propq)) goto err; /* Repack bag in same form with new password */ if (bagnid == NID_pkcs7_data) p7new = PKCS12_pack_p7data(bags); else - p7new = PKCS12_pack_p7encdata(pbe_nid, newpass, -1, NULL, - pbe_saltlen, pbe_iter, bags); + p7new = PKCS12_pack_p7encdata_ex(pbe_nid, newpass, -1, NULL, + pbe_saltlen, pbe_iter, bags, + p7->ctx.libctx, p7->ctx.propq); if (p7new == NULL || !sk_PKCS7_push(newsafes, p7new)) goto err; sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); @@ -107,11 +112,13 @@ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) if (!PKCS12_pack_authsafes(p12, newsafes)) goto err; - if (!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen)) - goto err; - X509_SIG_getm(p12->mac->dinfo, NULL, &macoct); - if (!ASN1_OCTET_STRING_set(macoct, mac, maclen)) - goto err; + if (p12->mac != NULL) { + if (!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen)) + goto err; + X509_SIG_getm(p12->mac->dinfo, NULL, &macoct); + if (!ASN1_OCTET_STRING_set(macoct, mac, maclen)) + goto err; + } rv = 1; @@ -130,11 +137,13 @@ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) } static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass, - const char *newpass) + const char *newpass, + OSSL_LIB_CTX *libctx, const char *propq) { int i; for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { - if (!newpass_bag(sk_PKCS12_SAFEBAG_value(bags, i), oldpass, newpass)) + if (!newpass_bag(sk_PKCS12_SAFEBAG_value(bags, i), oldpass, newpass, + libctx, propq)) return 0; } return 1; @@ -143,26 +152,37 @@ static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass, /* Change password of safebag: only needs handle shrouded keybags */ static int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass, - const char *newpass) + const char *newpass, + OSSL_LIB_CTX *libctx, const char *propq) { + EVP_CIPHER *cipher = NULL; PKCS8_PRIV_KEY_INFO *p8; X509_SIG *p8new; - int p8_nid, p8_saltlen, p8_iter; + int p8_nid, p8_saltlen, p8_iter, cipherid = 0; const X509_ALGOR *shalg; if (PKCS12_SAFEBAG_get_nid(bag) != NID_pkcs8ShroudedKeyBag) return 1; - if ((p8 = PKCS8_decrypt(bag->value.shkeybag, oldpass, -1)) == NULL) + if ((p8 = PKCS8_decrypt_ex(bag->value.shkeybag, oldpass, -1, + libctx, propq)) == NULL) return 0; X509_SIG_get0(bag->value.shkeybag, &shalg, NULL); - if (!alg_get(shalg, &p8_nid, &p8_iter, &p8_saltlen)) { + if (!alg_get(shalg, &p8_nid, &p8_iter, &p8_saltlen, &cipherid)) { PKCS8_PRIV_KEY_INFO_free(p8); return 0; } - p8new = PKCS8_encrypt(p8_nid, NULL, newpass, -1, NULL, p8_saltlen, - p8_iter, p8); + if (cipherid != NID_undef) { + cipher = EVP_CIPHER_fetch(libctx, OBJ_nid2sn(cipherid), propq); + if (cipher == NULL) { + PKCS8_PRIV_KEY_INFO_free(p8); + return 0; + } + } + p8new = PKCS8_encrypt_ex(p8_nid, cipher, newpass, -1, NULL, p8_saltlen, + p8_iter, p8, libctx, propq); PKCS8_PRIV_KEY_INFO_free(p8); + EVP_CIPHER_free(cipher); if (p8new == NULL) return 0; X509_SIG_free(bag->value.shkeybag); @@ -171,16 +191,69 @@ static int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass, } static int alg_get(const X509_ALGOR *alg, int *pnid, int *piter, - int *psaltlen) + int *psaltlen, int *cipherid) { - PBEPARAM *pbe; + int ret = 0, pbenid, aparamtype; + int encnid, prfnid; + const ASN1_OBJECT *aoid; + const void *aparam; + PBEPARAM *pbe = NULL; + PBE2PARAM *pbe2 = NULL; + PBKDF2PARAM *kdf = NULL; - pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), alg->parameter); - if (pbe == NULL) - return 0; - *pnid = OBJ_obj2nid(alg->algorithm); - *piter = ASN1_INTEGER_get(pbe->iter); - *psaltlen = pbe->salt->length; - PBEPARAM_free(pbe); - return 1; + X509_ALGOR_get0(&aoid, &aparamtype, &aparam, alg); + pbenid = OBJ_obj2nid(aoid); + + switch (pbenid) { + case NID_pbes2: + if (aparamtype == V_ASN1_SEQUENCE) + pbe2 = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBE2PARAM)); + if (pbe2 == NULL) + goto done; + + X509_ALGOR_get0(&aoid, &aparamtype, &aparam, pbe2->keyfunc); + pbenid = OBJ_obj2nid(aoid); + X509_ALGOR_get0(&aoid, NULL, NULL, pbe2->encryption); + encnid = OBJ_obj2nid(aoid); + + if (aparamtype == V_ASN1_SEQUENCE) + kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBKDF2PARAM)); + if (kdf == NULL) + goto done; + + /* Only OCTET_STRING is supported */ + if (kdf->salt->type != V_ASN1_OCTET_STRING) + goto done; + + if (kdf->prf == NULL) { + prfnid = NID_hmacWithSHA1; + } else { + X509_ALGOR_get0(&aoid, NULL, NULL, kdf->prf); + prfnid = OBJ_obj2nid(aoid); + } + *psaltlen = kdf->salt->value.octet_string->length; + *piter = ASN1_INTEGER_get(kdf->iter); + *pnid = prfnid; + *cipherid = encnid; + break; + default: + pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), alg->parameter); + if (pbe == NULL) + goto done; + *pnid = OBJ_obj2nid(alg->algorithm); + *piter = ASN1_INTEGER_get(pbe->iter); + *psaltlen = pbe->salt->length; + *cipherid = NID_undef; + ret = 1; + break; + } + ret = 1; +done: + if (kdf != NULL) + PBKDF2PARAM_free(kdf); + if (pbe2 != NULL) + PBE2PARAM_free(pbe2); + if (pbe != NULL) + PBEPARAM_free(pbe); + return ret; } diff --git a/test/pkcs12_api_test.c b/test/pkcs12_api_test.c index 718678446..da023f364 100644 --- a/test/pkcs12_api_test.c +++ b/test/pkcs12_api_test.c @@ -60,6 +60,46 @@ static const char *in_pass = ""; static int has_key = 0; static int has_cert = 0; static int has_ca = 0; + +static int changepass(PKCS12 *p12, EVP_PKEY *key, X509 *cert, STACK_OF(X509) *ca) +{ + int ret = 0; + PKCS12 *p12new = NULL; + EVP_PKEY *key2 = NULL; + X509 *cert2 = NULL; + STACK_OF(X509) *ca2 = NULL; + BIO *bio = NULL; + + if (!TEST_true(PKCS12_newpass(p12, in_pass, "NEWPASS"))) + goto err; + if (!TEST_ptr(bio = BIO_new(BIO_s_mem()))) + goto err; + if (!TEST_true(i2d_PKCS12_bio(bio, p12))) + goto err; + if (!TEST_ptr(p12new = PKCS12_init_ex(NID_pkcs7_data, testctx, "provider=default"))) + goto err; + if (!TEST_ptr(d2i_PKCS12_bio(bio, &p12new))) + goto err; + if (!TEST_true(PKCS12_parse(p12new, "NEWPASS", &key2, &cert2, &ca2))) + goto err; + if (has_key) { + if (!TEST_ptr(key2) || !TEST_int_eq(EVP_PKEY_eq(key, key2), 1)) + goto err; + } + if (has_cert) { + if (!TEST_ptr(cert2) || !TEST_int_eq(X509_cmp(cert, cert2), 0)) + goto err; + } + ret = 1; +err: + BIO_free(bio); + PKCS12_free(p12new); + EVP_PKEY_free(key2); + X509_free(cert2); + OSSL_STACK_OF_X509_free(ca2); + return ret; +} + static int pkcs12_parse_test(void) { int ret = 0; @@ -82,8 +122,9 @@ static int pkcs12_parse_test(void) goto err; if ((has_ca && !TEST_ptr(ca)) || (!has_ca && !TEST_ptr_null(ca))) goto err; + if (has_key && !changepass(p12, key, cert, ca)) + goto err; } - ret = 1; err: PKCS12_free(p12); From 54d2844545b21fe62bffbbac7d64fc9f355845a9 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 17:36:51 +0800 Subject: [PATCH 17/66] Add NULL checks where ContentInfo data can be NULL PKCS12 structures contain PKCS7 ContentInfo fields. These fields are optional and can be NULL even if the "type" is a valid value. OpenSSL was not properly accounting for this and a NULL dereference can occur causing a crash. CVE-2024-0727 Reviewed-by: Tomas Mraz Reviewed-by: Hugo Landau Reviewed-by: Neil Horman (Merged from https://github.com/openssl/openssl/pull/23361) --- crypto/pkcs12/p12_add.c | 18 ++++++++++++++++++ crypto/pkcs12/p12_mutl.c | 5 +++++ crypto/pkcs12/p12_npas.c | 5 +++-- crypto/pkcs7/pk7_mime.c | 7 +++++-- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/crypto/pkcs12/p12_add.c b/crypto/pkcs12/p12_add.c index d905c7d9f..7ef5dca67 100644 --- a/crypto/pkcs12/p12_add.c +++ b/crypto/pkcs12/p12_add.c @@ -78,6 +78,12 @@ STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7) ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CONTENT_TYPE_NOT_DATA); return NULL; } + + if (p7->d.data == NULL) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_DECODE_ERROR); + return NULL; + } + return ASN1_item_unpack_ex(p7->d.data, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), ossl_pkcs7_ctx_get0_libctx(&p7->ctx), ossl_pkcs7_ctx_get0_propq(&p7->ctx)); @@ -152,6 +158,12 @@ STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass, { if (!PKCS7_type_is_encrypted(p7)) return NULL; + + if (p7->d.encrypted == NULL) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_DECODE_ERROR); + return NULL; + } + return PKCS12_item_decrypt_d2i_ex(p7->d.encrypted->enc_data->algorithm, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), pass, passlen, @@ -191,6 +203,12 @@ STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12) ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CONTENT_TYPE_NOT_DATA); return NULL; } + + if (p12->authsafes->d.data == NULL) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_DECODE_ERROR); + return NULL; + } + p7ctx = &p12->authsafes->ctx; p7s = ASN1_item_unpack_ex(p12->authsafes->d.data, ASN1_ITEM_rptr(PKCS12_AUTHSAFES), diff --git a/crypto/pkcs12/p12_mutl.c b/crypto/pkcs12/p12_mutl.c index 118d598ea..28cb210ea 100644 --- a/crypto/pkcs12/p12_mutl.c +++ b/crypto/pkcs12/p12_mutl.c @@ -75,6 +75,11 @@ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen, return 0; } + if (p12->authsafes->d.data == NULL) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_DECODE_ERROR); + return 0; + } + salt = p12->mac->salt->data; saltlen = p12->mac->salt->length; if (p12->mac->iter == NULL) diff --git a/crypto/pkcs12/p12_npas.c b/crypto/pkcs12/p12_npas.c index 90139100c..007b171dc 100644 --- a/crypto/pkcs12/p12_npas.c +++ b/crypto/pkcs12/p12_npas.c @@ -80,8 +80,9 @@ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) bags = PKCS12_unpack_p7data(p7); } else if (bagnid == NID_pkcs7_encrypted) { bags = PKCS12_unpack_p7encdata(p7, oldpass, -1); - if (!alg_get(p7->d.encrypted->enc_data->algorithm, - &pbe_nid, &pbe_iter, &pbe_saltlen, &cipherid)) + if (p7->d.encrypted == NULL + || !alg_get(p7->d.encrypted->enc_data->algorithm, + &pbe_nid, &pbe_iter, &pbe_saltlen, &cipherid)) goto err; } else { continue; diff --git a/crypto/pkcs7/pk7_mime.c b/crypto/pkcs7/pk7_mime.c index 49a0da5f8..8228315ee 100644 --- a/crypto/pkcs7/pk7_mime.c +++ b/crypto/pkcs7/pk7_mime.c @@ -33,10 +33,13 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags) int ctype_nid = OBJ_obj2nid(p7->type); const PKCS7_CTX *ctx = ossl_pkcs7_get0_ctx(p7); - if (ctype_nid == NID_pkcs7_signed) + if (ctype_nid == NID_pkcs7_signed) { + if (p7->d.sign == NULL) + return 0; mdalgs = p7->d.sign->md_algs; - else + } else { mdalgs = NULL; + } flags ^= SMIME_OLDMIME; From 6d2c1428968db7058c7cb74149e7d9b71c2032a8 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 17:37:19 +0800 Subject: [PATCH 18/66] Add some tests for various PKCS12 files with NULL ContentInfo PKCS7 ContentInfo fields held within a PKCS12 file can be NULL, even if the type has been set to a valid value. CVE-2024-0727 is a result of OpenSSL attempting to dereference the NULL pointer as a result of this. We add test for various instances of this problem. Reviewed-by: Tomas Mraz Reviewed-by: Hugo Landau Reviewed-by: Neil Horman (Merged from https://github.com/openssl/openssl/pull/23361) --- test/recipes/80-test_pkcs12.t | 25 ++++++++++++++++++++-- test/recipes/80-test_pkcs12_data/bad1.p12 | Bin 0 -> 85 bytes test/recipes/80-test_pkcs12_data/bad2.p12 | Bin 0 -> 104 bytes test/recipes/80-test_pkcs12_data/bad3.p12 | Bin 0 -> 104 bytes 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 test/recipes/80-test_pkcs12_data/bad1.p12 create mode 100644 test/recipes/80-test_pkcs12_data/bad2.p12 create mode 100644 test/recipes/80-test_pkcs12_data/bad3.p12 diff --git a/test/recipes/80-test_pkcs12.t b/test/recipes/80-test_pkcs12.t index 0f42602cc..fe8d43fd2 100644 --- a/test/recipes/80-test_pkcs12.t +++ b/test/recipes/80-test_pkcs12.t @@ -9,7 +9,7 @@ use strict; use warnings; -use OpenSSL::Test qw/:DEFAULT srctop_file/; +use OpenSSL::Test qw/:DEFAULT srctop_file with/; use OpenSSL::Test::Utils; use Encode; @@ -54,7 +54,7 @@ if (eval { require Win32::API; 1; }) { } $ENV{OPENSSL_WIN32_UTF8}=1; -plan tests => 24; +plan tests => 28; # Test different PKCS#12 formats ok(run(test(["pkcs12_format_test"])), "test pkcs12 formats"); @@ -152,6 +152,27 @@ ok(grep(/Trusted key usage (Oracle)/, @pkcs12info) == 0, ok(scalar @match > 0 ? 0 : 1, "test_export_pkcs12_outerr6_empty"); } +# Test some bad pkcs12 files +my $bad1 = srctop_file("test", "recipes", "80-test_pkcs12_data", "bad1.p12"); +my $bad2 = srctop_file("test", "recipes", "80-test_pkcs12_data", "bad2.p12"); +my $bad3 = srctop_file("test", "recipes", "80-test_pkcs12_data", "bad3.p12"); + +with({ exit_checker => sub { return shift == 1; } }, + sub { + ok(run(app(["openssl", "pkcs12", "-in", $bad1, "-password", "pass:"])), + "test bad pkcs12 file 1"); + + ok(run(app(["openssl", "pkcs12", "-in", $bad1, "-password", "pass:", + "-nomacver"])), + "test bad pkcs12 file 1 (nomacver)"); + + ok(run(app(["openssl", "pkcs12", "-in", $bad2, "-password", "pass:"])), + "test bad pkcs12 file 2"); + + ok(run(app(["openssl", "pkcs12", "-in", $bad3, "-password", "pass:"])), + "test bad pkcs12 file 3"); + }); + # Test with Oracle Trusted Key Usage specified in openssl.cnf { $ENV{OPENSSL_CONF} = srctop_file("test", "recipes", "80-test_pkcs12_data", "jdk_trusted.cnf"); diff --git a/test/recipes/80-test_pkcs12_data/bad1.p12 b/test/recipes/80-test_pkcs12_data/bad1.p12 new file mode 100644 index 0000000000000000000000000000000000000000..8f3387c7e356e4aa374729f3f3939343557b9c09 GIT binary patch literal 85 zcmV-b0IL5mQvv}4Fbf6=Duzgg_YDCD0Wd)@F)$4V31Egu0c8UO0s#d81R(r{)waiY rfR=Py6XX#<$m7-wj)xrauuD`}hF=Ng9=0`~S~)@=J%OiUaM0Oze6 AD*ylh literal 0 HcmV?d00001 diff --git a/test/recipes/80-test_pkcs12_data/bad3.p12 b/test/recipes/80-test_pkcs12_data/bad3.p12 new file mode 100644 index 0000000000000000000000000000000000000000..ef86a1d86fb0bc09471ca2596d82e7d521d973a4 GIT binary patch literal 104 zcmXp=V`5}BkYnT2YV&CO&dbQoxImDF-+oA$5$MVJL*60=F*5iN*C_e&wD%dwCM*q{=+OBX|Z+F7XSHN#>B+I003La BAqM~e literal 0 HcmV?d00001 From 7a527cb65a5982d882e8ce1e3632d552959aaf51 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 17:37:58 +0800 Subject: [PATCH 19/66] Add CHANGES entry for CVE-2024-0727 --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index b59f8621f..60551db8e 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,8 @@ *) 修复CVE-2023-6237 + *) 修复CVE-2024-0727 + *) 增加SM2两方门限解密算法 *) 增加SM2两方门限签名算法 [with work originated from FullyRobert] From cd2a7c31001075f6eb53b0eabeab13ddde846918 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 18:06:46 +0800 Subject: [PATCH 20/66] Fix compile error, OSSL_STACK_OF_X509_free undefined --- test/pkcs12_api_test.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/pkcs12_api_test.c b/test/pkcs12_api_test.c index da023f364..7f5fec030 100644 --- a/test/pkcs12_api_test.c +++ b/test/pkcs12_api_test.c @@ -96,7 +96,7 @@ static int changepass(PKCS12 *p12, EVP_PKEY *key, X509 *cert, STACK_OF(X509) *ca PKCS12_free(p12new); EVP_PKEY_free(key2); X509_free(cert2); - OSSL_STACK_OF_X509_free(ca2); + sk_X509_pop_free(ca2, X509_free); return ret; } @@ -130,7 +130,7 @@ static int pkcs12_parse_test(void) PKCS12_free(p12); EVP_PKEY_free(key); X509_free(cert); - OSSL_STACK_OF_X509_free(ca); + sk_X509_pop_free(ca, X509_free); return TEST_true(ret); } @@ -222,7 +222,7 @@ static int pkcs12_create_ex2_test(int test) PKCS12_free(ptr); EVP_PKEY_free(key); X509_free(cert); - OSSL_STACK_OF_X509_free(ca); + sk_X509_pop_free(ca, X509_free); return TEST_true(ret); } From ae26cb70bf1445442a013dfcddb162197825b458 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 8 Mar 2024 19:37:19 +0800 Subject: [PATCH 21/66] Fix test failed, remove rc2 test cases --- test/recipes/80-test_pkcs12.t | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/test/recipes/80-test_pkcs12.t b/test/recipes/80-test_pkcs12.t index fe8d43fd2..f95e69488 100644 --- a/test/recipes/80-test_pkcs12.t +++ b/test/recipes/80-test_pkcs12.t @@ -54,7 +54,7 @@ if (eval { require Win32::API; 1; }) { } $ENV{OPENSSL_WIN32_UTF8}=1; -plan tests => 28; +plan tests => 26; # Test different PKCS#12 formats ok(run(test(["pkcs12_format_test"])), "test pkcs12 formats"); @@ -72,7 +72,6 @@ ok(run(app(["openssl", "pkcs12", "-noout", my @path = qw(test certs); my $outfile1 = "out1.p12"; my $outfile2 = "out2.p12"; -my $outfile3 = "out3.p12"; my $outfile4 = "out4.p12"; my $outfile5 = "out5.p12"; my $outfile6 = "out6.p12"; @@ -205,16 +204,6 @@ SKIP: { ])), "Test pkcs12_parse()"); } -SKIP: { - skip "Skipping PKCS#12 parse test because the required algorithms are disabled", 1 - if disabled("des") || disabled("rc2") || disabled("legacy"); - ok(run(test(["pkcs12_api_test", - "-in", $outfile3, - "-pass", "v3-certs", - "-has-ca", 1, - ])), "Test pkcs12_parse()"); -} - ok(run(test(["pkcs12_api_test", "-in", $outfile4, "-pass", "v3-certs", From fb7795ae8aaaa8ea75140a72cfb7ab3022661746 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 15 Mar 2024 09:38:52 +0800 Subject: [PATCH 22/66] Remove doc --- doc/man3/PKCS12_SAFEBAG_set0_attrs.pod | 32 -------------------------- 1 file changed, 32 deletions(-) delete mode 100644 doc/man3/PKCS12_SAFEBAG_set0_attrs.pod diff --git a/doc/man3/PKCS12_SAFEBAG_set0_attrs.pod b/doc/man3/PKCS12_SAFEBAG_set0_attrs.pod deleted file mode 100644 index 98e212a9b..000000000 --- a/doc/man3/PKCS12_SAFEBAG_set0_attrs.pod +++ /dev/null @@ -1,32 +0,0 @@ -=pod - -=head1 NAME - -PKCS12_SAFEBAG_set0_attrs -- Set attributes for a PKCS#12 safeBag - -=head1 SYNOPSIS - - #include - - void PKCS12_SAFEBAG_set0_attrs(PKCS12_SAFEBAG *bag, const STACK_OF(X509_ATTRIBUTE) *attrs); - -=head1 DESCRIPTION - -PKCS12_SAFEBAG_set0_attrs() assigns the stack of Bs to a -PKCS#12 safeBag. I is the B to assign the attributes to. - -=head1 RETURN VALUES - -PKCS12_SAFEBAG_set0_attrs() does not return a value. - -=head1 COPYRIGHT - -Copyright 2019-2022 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 -L. - -=cut From 26b66f232d327c10c0626a6503bfc1ce6f59b0b0 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 26 Apr 2024 20:13:18 +0800 Subject: [PATCH 23/66] Add a test for session cache handling Repeatedly create sessions to be added to the cache and ensure we never exceed the expected size. Related to CVE-2024-2511 Reviewed-by: Neil Horman Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24042) --- test/sslapitest.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/test/sslapitest.c b/test/sslapitest.c index 4cd8855cf..5597b5886 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -10017,6 +10017,97 @@ static int test_tls_cert_compression_api(int tst) } #endif +/* + * Test multiple resumptions and cache size handling + * Test 0: TLSv1.3 (max_early_data set) + * Test 1: TLSv1.3 (SSL_OP_NO_TICKET set) + * Test 2: TLSv1.3 (max_early_data and SSL_OP_NO_TICKET set) + * Test 3: TLSv1.2 + */ +static int test_multi_resume(int idx) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl = NULL, *clientssl = NULL; + SSL_SESSION *sess = NULL; + int max_version = TLS1_3_VERSION; + int i, testresult = 0; + + if (idx == 3) + max_version = TLS1_2_VERSION; + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), TLS1_VERSION, + max_version, &sctx, &cctx, cert, + privkey))) + goto end; + + /* + * TLSv1.3 only uses a session cache if either max_early_data > 0 (used for + * replay protection), or if SSL_OP_NO_TICKET is in use + */ + if (idx == 0 || idx == 2) { + if (!TEST_true(SSL_CTX_set_max_early_data(sctx, 1024))) + goto end; + } + if (idx == 1 || idx == 2) + SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET); + + SSL_CTX_sess_set_cache_size(sctx, 5); + + for (i = 0; i < 30; i++) { + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL)) + || !TEST_true(SSL_set_session(clientssl, sess))) + goto end; + + /* + * Recreate a bug where dynamically changing the max_early_data value + * can cause sessions in the session cache which cannot be deleted. + */ + if ((idx == 0 || idx == 2) && (i % 3) == 2) + SSL_set_max_early_data(serverssl, 0); + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + if (sess == NULL || (idx == 0 && (i % 3) == 2)) { + if (!TEST_false(SSL_session_reused(clientssl))) + goto end; + } else { + if (!TEST_true(SSL_session_reused(clientssl))) + goto end; + } + SSL_SESSION_free(sess); + + /* Do a full handshake, followed by two resumptions */ + if ((i % 3) == 2) { + sess = NULL; + } else { + if (!TEST_ptr((sess = SSL_get1_session(clientssl)))) + goto end; + } + + SSL_shutdown(clientssl); + SSL_shutdown(serverssl); + SSL_free(serverssl); + SSL_free(clientssl); + serverssl = clientssl = NULL; + } + + /* We should never exceed the session cache size limit */ + if (!TEST_long_le(SSL_CTX_sess_number(sctx), 5)) + goto end; + + testresult = 1; + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + SSL_SESSION_free(sess); + return testresult; +} + OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile provider config dhfile\n") int setup_tests(void) @@ -10285,6 +10376,7 @@ int setup_tests(void) ADD_TEST(test_set_verify_cert_store_ssl); ADD_ALL_TESTS(test_session_timeout, 1); ADD_TEST(test_load_dhfile); + ADD_ALL_TESTS(test_multi_resume, 4); return 1; err: From 734feea3be60f2f54c85f1ec5437a4122d3d36fd Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 26 Apr 2024 20:26:59 +0800 Subject: [PATCH 24/66] Extend the multi_resume test for simultaneous resumptions Test what happens if the same session gets resumed multiple times at the same time - and one of them gets marked as not_resumable. Related to CVE-2024-2511 Reviewed-by: Neil Horman Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24042) --- test/sslapitest.c | 88 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 4 deletions(-) diff --git a/test/sslapitest.c b/test/sslapitest.c index 5597b5886..909de4d3b 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -10017,12 +10017,62 @@ static int test_tls_cert_compression_api(int tst) } #endif +struct resume_servername_cb_data { + int i; + SSL_CTX *cctx; + SSL_CTX *sctx; + SSL_SESSION *sess; + int recurse; +}; + +/* + * Servername callback. We use it here to run another complete handshake using + * the same session - and mark the session as not_resuamble at the end + */ +static int resume_servername_cb(SSL *s, int *ad, void *arg) +{ + struct resume_servername_cb_data *cbdata = arg; + SSL *serverssl = NULL, *clientssl = NULL; + int ret = SSL_TLSEXT_ERR_ALERT_FATAL; + + if (cbdata->recurse) + return SSL_TLSEXT_ERR_ALERT_FATAL; + + if ((cbdata->i % 3) != 1) + return SSL_TLSEXT_ERR_OK; + + cbdata->recurse = 1; + + if (!TEST_true(create_ssl_objects(cbdata->sctx, cbdata->cctx, &serverssl, + &clientssl, NULL, NULL)) + || !TEST_true(SSL_set_session(clientssl, cbdata->sess))) + goto end; + + ERR_set_mark(); + /* + * We expect this to fail - because the servername cb will fail. This will + * mark the session as not_resumable. + */ + if (!TEST_false(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) { + ERR_clear_last_mark(); + goto end; + } + ERR_pop_to_mark(); + + ret = SSL_TLSEXT_ERR_OK; + end: + SSL_free(serverssl); + SSL_free(clientssl); + cbdata->recurse = 0; + return ret; +} /* * Test multiple resumptions and cache size handling * Test 0: TLSv1.3 (max_early_data set) * Test 1: TLSv1.3 (SSL_OP_NO_TICKET set) * Test 2: TLSv1.3 (max_early_data and SSL_OP_NO_TICKET set) - * Test 3: TLSv1.2 + * Test 3: TLSv1.3 (SSL_OP_NO_TICKET, simultaneous resumes) + * Test 4: TLSv1.2 */ static int test_multi_resume(int idx) { @@ -10031,9 +10081,19 @@ static int test_multi_resume(int idx) SSL_SESSION *sess = NULL; int max_version = TLS1_3_VERSION; int i, testresult = 0; + struct resume_servername_cb_data cbdata; - if (idx == 3) +#if defined(OPENSSL_NO_TLS1_2) + if (idx == 4) + return TEST_skip("TLSv1.2 is disabled in this build"); +#else + if (idx == 4) max_version = TLS1_2_VERSION; +#endif +#if defined(OSSL_NO_USABLE_TLS1_3) + if (idx != 4) + return TEST_skip("No usable TLSv1.3 in this build"); +#endif if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), TLS_client_method(), TLS1_VERSION, @@ -10049,17 +10109,37 @@ static int test_multi_resume(int idx) if (!TEST_true(SSL_CTX_set_max_early_data(sctx, 1024))) goto end; } - if (idx == 1 || idx == 2) + if (idx == 1 || idx == 2 || idx == 3) SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET); SSL_CTX_sess_set_cache_size(sctx, 5); + if (idx == 3) { + SSL_CTX_set_tlsext_servername_callback(sctx, resume_servername_cb); + SSL_CTX_set_tlsext_servername_arg(sctx, &cbdata); + cbdata.cctx = cctx; + cbdata.sctx = sctx; + cbdata.recurse = 0; + } + for (i = 0; i < 30; i++) { if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) || !TEST_true(SSL_set_session(clientssl, sess))) goto end; + /* + * Check simultaneous resumes. We pause the connection part way through + * the handshake by (mis)using the servername_cb. The pause occurs after + * session resumption has already occurred, but before any session + * tickets have been issued. While paused we run another complete + * handshake resuming the same session. + */ + if (idx == 3) { + cbdata.i = i; + cbdata.sess = sess; + } + /* * Recreate a bug where dynamically changing the max_early_data value * can cause sessions in the session cache which cannot be deleted. @@ -10376,7 +10456,7 @@ int setup_tests(void) ADD_TEST(test_set_verify_cert_store_ssl); ADD_ALL_TESTS(test_session_timeout, 1); ADD_TEST(test_load_dhfile); - ADD_ALL_TESTS(test_multi_resume, 4); + ADD_ALL_TESTS(test_multi_resume, 5); return 1; err: From 0f18e85a75e40110c3dde193d156118d2b496b25 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 26 Apr 2024 20:41:32 +0800 Subject: [PATCH 25/66] Fix unconstrained session cache growth in TLSv1.3 In TLSv1.3 we create a new session object for each ticket that we send. We do this by duplicating the original session. If SSL_OP_NO_TICKET is in use then the new session will be added to the session cache. However, if early data is not in use (and therefore anti-replay protection is being used), then multiple threads could be resuming from the same session simultaneously. If this happens and a problem occurs on one of the threads, then the original session object could be marked as not_resumable. When we duplicate the session object this not_resumable status gets copied into the new session object. The new session object is then added to the session cache even though it is not_resumable. Subsequently, another bug means that the session_id_length is set to 0 for sessions that are marked as not_resumable - even though that session is still in the cache. Once this happens the session can never be removed from the cache. When that object gets to be the session cache tail object the cache never shrinks again and grows indefinitely. CVE-2024-2511 Reviewed-by: Neil Horman Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24042) --- ssl/ssl_lib.c | 5 +++-- ssl/ssl_sess.c | 28 ++++++++++++++++++++++------ ssl/statem/statem_srvr.c | 5 ++--- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index a442bb8ef..03f2f051f 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -3840,9 +3840,10 @@ void ssl_update_cache(SSL *s, int mode) /* * If the session_id_length is 0, we are not supposed to cache it, and it - * would be rather hard to do anyway :-) + * would be rather hard to do anyway :-). Also if the session has already + * been marked as not_resumable we should not cache it for later reuse. */ - if (s->session->session_id_length == 0) + if (s->session->session_id_length == 0 || s->session->not_resumable) return; /* diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 6bbd27d4e..0e51276bb 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -157,16 +157,11 @@ SSL_SESSION *SSL_SESSION_new(void) return ss; } -SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src) -{ - return ssl_session_dup(src, 1); -} - /* * Create a new SSL_SESSION and duplicate the contents of |src| into it. If * ticket == 0 then no ticket information is duplicated, otherwise it is. */ -SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket) +static SSL_SESSION *ssl_session_dup_intern(const SSL_SESSION *src, int ticket) { SSL_SESSION *dest; @@ -310,6 +305,27 @@ SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket) return NULL; } +SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src) +{ + return ssl_session_dup_intern(src, 1); +} + +/* + * Used internally when duplicating a session which might be already shared. + * We will have resumed the original session. Subsequently we might have marked + * it as non-resumable (e.g. in another thread) - but this copy should be ok to + * resume from. + */ +SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket) +{ + SSL_SESSION *sess = ssl_session_dup_intern(src, ticket); + + if (sess != NULL) + sess->not_resumable = 0; + + return sess; +} + const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) { if (len) diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 4422bffa9..11d3566bd 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -2522,9 +2522,8 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt) * so the following won't overwrite an ID that we're supposed * to send back. */ - if (s->session->not_resumable || - (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) - && !s->hit)) + if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) + && !s->hit) s->session->session_id_length = 0; if (usetls13) { From 5b518cd6a156ce233efe8856e3bb4d9c08664c74 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 26 Apr 2024 20:43:54 +0800 Subject: [PATCH 26/66] Hardening around not_resumable sessions Make sure we can't inadvertently use a not_resumable session Related to CVE-2024-2511 Reviewed-by: Neil Horman Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24042) --- ssl/ssl_sess.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 0e51276bb..cbb94d57b 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -579,6 +579,12 @@ SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id, #endif if (ret != NULL) { + if (ret->not_resumable) { + /* If its not resumable then ignore this session */ + if (!copy) + SSL_SESSION_free(ret); + return NULL; + } ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_cb_hit); From 337e6b46719fa859922bc46d58e859802e522e10 Mon Sep 17 00:00:00 2001 From: Xudong Guo Date: Sun, 28 Apr 2024 15:52:56 +0800 Subject: [PATCH 27/66] update README and add new badges --- README.md | 21 +++++++++++++++++++-- atom-logo.svg | 16 ++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 atom-logo.svg diff --git a/README.md b/README.md index ef572cb38..ab0bb0710 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ -概述 + OpenAtom 铜锁/Tongsuo ========================= [![tongsuo logo]][www.tongsuo.net] [![github actions ci badge]][github actions ci] [![Coverage Status](https://coveralls.io/repos/github/Tongsuo-Project/Tongsuo/badge.svg?branch=master)](https://coveralls.io/github/Tongsuo-Project/Tongsuo?branch=master) +![GitHub Release][github release] +[![GitHub Downloads (all assets, all releases)][github downloads]](https://github.com/Tongsuo-Project/Tongsuo/releases) 铜锁/Tongsuo是一个提供现代密码学算法和安全通信协议的开源基础密码库,为存储、网络、密钥管理、隐私计算等诸多业务场景提供底层的密码学基础能力,实现数据在传输、使用、存储等过程中的私密性、完整性和可认证性,为数据生命周期中的隐私和安全提供保护能力。 @@ -124,7 +126,7 @@ make install_programs 文档 ========================= -铜锁的相关文档组织在 [铜锁文档网站](https://yuque.com/tsdoc) 上。 +铜锁的相关文档组织在 [铜锁文档网站](https://www.tongsuo.net/docs) 上。 交流合作 ========================= @@ -135,6 +137,13 @@ make install_programs ![tongsuo public qr](tongsuo-public-qr.jpg) +声明 +========================= + +铜锁/Tongsuo 是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目。 + +![OpenAtom Foundation](atom-logo.svg) + 报告安全缺陷 ========================= @@ -163,3 +172,11 @@ make install_programs [github actions ci]: "GitHub Actions CI" + +[github release]: + + "GitHub Release" + +[github downloads]: + + "GitHub Downloads" \ No newline at end of file diff --git a/atom-logo.svg b/atom-logo.svg new file mode 100644 index 000000000..0cce03d03 --- /dev/null +++ b/atom-logo.svg @@ -0,0 +1,16 @@ + + + 开放原子开源基金会 + + + + + + + + + + \ No newline at end of file From d73be302e46fa2699425ad6566cddc32fa9e5ebf Mon Sep 17 00:00:00 2001 From: Xudong Guo Date: Tue, 7 May 2024 11:00:46 +0800 Subject: [PATCH 28/66] fix & update README image --- README.md | 6 ++++-- atom-logo.svg | 17 +---------------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index ab0bb0710..c78eb40ee 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,9 @@ 铜锁获得了国家密码管理局商用密码检测中心颁发的商用密码产品认证证书,助力用户在国密改造、密评、等保等过程中,更加严谨地满足我国商用密码技术合规的要求。可在[此处](https://www.yuque.com/tsdoc/misc/st247r05s8b5dtct)下载资质原始文件。 - +
+ +
特性 @@ -142,7 +144,7 @@ make install_programs 铜锁/Tongsuo 是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目。 -![OpenAtom Foundation](atom-logo.svg) +OpenAtom Foundation 报告安全缺陷 ========================= diff --git a/atom-logo.svg b/atom-logo.svg index 0cce03d03..b6c28be66 100644 --- a/atom-logo.svg +++ b/atom-logo.svg @@ -1,16 +1 @@ - - - 开放原子开源基金会 - - - - - - - - - - \ No newline at end of file + \ No newline at end of file From 4fa7f74b9620b4a8d37a7ec70ffdc677bed949e4 Mon Sep 17 00:00:00 2001 From: K1 Date: Thu, 9 May 2024 09:48:40 +0800 Subject: [PATCH 29/66] Add a test for session cache overflow Test sessions behave as we expect even in the case that an overflow occurs when adding a new session into the session cache. Related to CVE-2024-2511 Reviewed-by: Neil Horman Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24044) (cherry picked from commit ddead0935d77ba9b771d632ace61b145d7153f18) --- test/sslapitest.c | 124 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) diff --git a/test/sslapitest.c b/test/sslapitest.c index 909de4d3b..17fb5c258 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -2210,7 +2210,6 @@ static int test_session_wo_ca_names(void) #endif } - #ifndef OSSL_NO_USABLE_TLS1_3 static SSL_SESSION *sesscache[6]; static int do_cache; @@ -8596,6 +8595,126 @@ static int test_session_timeout(int test) return testresult; } +/* + * Test that a session cache overflow works as expected + * Test 0: TLSv1.3, timeout on new session later than old session + * Test 1: TLSv1.2, timeout on new session later than old session + * Test 2: TLSv1.3, timeout on new session earlier than old session + * Test 3: TLSv1.2, timeout on new session earlier than old session + */ +#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) +static int test_session_cache_overflow(int idx) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl = NULL, *clientssl = NULL; + int testresult = 0; + SSL_SESSION *sess = NULL; + +#ifdef OSSL_NO_USABLE_TLS1_3 + /* If no TLSv1.3 available then do nothing in this case */ + if (idx % 2 == 0) + return TEST_skip("No TLSv1.3 available"); +#endif +#ifdef OPENSSL_NO_TLS1_2 + /* If no TLSv1.2 available then do nothing in this case */ + if (idx % 2 == 1) + return TEST_skip("No TLSv1.2 available"); +#endif + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), TLS1_VERSION, + (idx % 2 == 0) ? TLS1_3_VERSION + : TLS1_2_VERSION, + &sctx, &cctx, cert, privkey)) + || !TEST_true(SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET))) + goto end; + + SSL_CTX_sess_set_get_cb(sctx, get_session_cb); + get_sess_val = NULL; + + SSL_CTX_sess_set_cache_size(sctx, 1); + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + if (idx > 1) { + sess = SSL_get_session(serverssl); + if (!TEST_ptr(sess)) + goto end; + + /* + * Cause this session to have a longer timeout than the next session to + * be added. + */ + if (!TEST_true(SSL_SESSION_set_timeout(sess, LONG_MAX / 2))) { + sess = NULL; + goto end; + } + sess = NULL; + } + + SSL_shutdown(serverssl); + SSL_shutdown(clientssl); + SSL_free(serverssl); + SSL_free(clientssl); + serverssl = clientssl = NULL; + + /* + * Session cache size is 1 and we already populated the cache with a session + * so the next connection should cause an overflow. + */ + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + /* + * The session we just negotiated may have been already removed from the + * internal cache - but we will return it anyway from our external cache. + */ + get_sess_val = SSL_get_session(serverssl); + if (!TEST_ptr(get_sess_val)) + goto end; + sess = SSL_get1_session(clientssl); + if (!TEST_ptr(sess)) + goto end; + + SSL_shutdown(serverssl); + SSL_shutdown(clientssl); + SSL_free(serverssl); + SSL_free(clientssl); + serverssl = clientssl = NULL; + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + if (!TEST_true(SSL_set_session(clientssl, sess))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + testresult = 1; + + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + SSL_SESSION_free(sess); + + return testresult; +} +#endif /* !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) */ + /* * Test 0: Client sets servername and server acknowledges it (TLSv1.2) * Test 1: Client sets servername and server does not acknowledge it (TLSv1.2) @@ -10455,6 +10574,9 @@ int setup_tests(void) ADD_TEST(test_set_verify_cert_store_ssl_ctx); ADD_TEST(test_set_verify_cert_store_ssl); ADD_ALL_TESTS(test_session_timeout, 1); +#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) + ADD_ALL_TESTS(test_session_cache_overflow, 4); +#endif ADD_TEST(test_load_dhfile); ADD_ALL_TESTS(test_multi_resume, 5); return 1; From 820c0f572b7acd75c07465d541dcd5bb0a6f9f6b Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 26 Apr 2024 21:22:13 +0800 Subject: [PATCH 30/66] Add a CHANGES entry for CVE-2024-2511 --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 60551db8e..647362367 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,8 @@ Changes between 8.4.0 and 8.5.0 [xx XXX xxxx] + *) 修复CVE-2024-2511 + *) 修复CVE-2023-6129 *) 修复CVE-2023-6237 From e3c7c24dd7b424e3ac9585c6b0021c193dfeddcd Mon Sep 17 00:00:00 2001 From: K1 Date: Wed, 8 May 2024 22:14:32 +0800 Subject: [PATCH 31/66] Free up space in the session cache before adding. Fixes #18690 In some circumstances, it's possible that when using an external database for the session cache, that pulling in an entry from that cache to the internal cache will cause the newly added entry to be deleted from the internal cache. This is likely to happen when the internal cache is set to have a small size, and the newly added entry's timeout places it at the end of the cache list. This could be fixed by updating the timestamp of the session (via `SSL_SESSION_set_time()` or `SSL_SESSION_set_timeout()`) before adding to the cache. But that may not be desireable. Reviewed-by: Viktor Dukhovni Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/18905) --- ssl/ssl_sess.c | 26 +++++++++++++++----------- test/sslapitest.c | 26 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index cbb94d57b..de1386c02 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -846,25 +846,17 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) c->time = time(NULL); ssl_session_calculate_timeout(c); } - SSL_SESSION_list_add(ctx, c); - if (s != NULL) { - /* - * existing cache entry -- decrement previously incremented reference - * count because it already takes into account the cache - */ - - SSL_SESSION_free(s); /* s == c */ - ret = 0; - } else { + if (s == NULL) { /* * new cache entry -- remove old ones if cache has become too large + * delete cache entry *before* add, so we don't remove the one we're adding! */ ret = 1; if (SSL_CTX_sess_get_cache_size(ctx) > 0) { - while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { + while (SSL_CTX_sess_number(ctx) >= SSL_CTX_sess_get_cache_size(ctx)) { if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) break; else @@ -872,6 +864,18 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) } } } + + SSL_SESSION_list_add(ctx, c); + + if (s != NULL) { + /* + * existing cache entry -- decrement previously incremented reference + * count because it already takes into account the cache + */ + + SSL_SESSION_free(s); /* s == c */ + ret = 0; + } CRYPTO_THREAD_unlock(ctx->lock); return ret; } diff --git a/test/sslapitest.c b/test/sslapitest.c index 17fb5c258..f891e646d 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -2133,6 +2133,32 @@ static int execute_test_session(int maxprot, int use_int_cache, goto end; } } + /* + * Make a small cache, force out all other sessions but + * sess2, try to add sess1, which should succeed. Then + * make sure it's there by checking the owners. Despite + * the timeouts, sess1 should have kicked out sess2 + */ + + /* Make sess1 expire before sess2 */ + if (!TEST_long_gt(SSL_SESSION_set_time(sess1, 1000), 0) + || !TEST_long_gt(SSL_SESSION_set_timeout(sess1, 1000), 0) + || !TEST_long_gt(SSL_SESSION_set_time(sess2, 2000), 0) + || !TEST_long_gt(SSL_SESSION_set_timeout(sess2, 2000), 0)) + goto end; + + if (!TEST_long_ne(SSL_CTX_sess_set_cache_size(sctx, 1), 0)) + goto end; + + /* Don't care about results - cache should only be sess2 at end */ + SSL_CTX_add_session(sctx, sess1); + SSL_CTX_add_session(sctx, sess2); + + /* Now add sess1, and make sure it remains, despite timeout */ + if (!TEST_true(SSL_CTX_add_session(sctx, sess1)) + || !TEST_ptr(sess1->owner) + || !TEST_ptr_null(sess2->owner)) + goto end; testresult = 1; From 0e9dd804717a394415fa48a411748f5adf567c97 Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 18 Jun 2024 20:11:50 +0800 Subject: [PATCH 32/66] Fix coverity issues, use of an uninitialized variable CID: 471247, 370239, 364178, 351779, 351777, 278417, 25398, 25379 --- crypto/evp/e_des.c | 3 ++- crypto/evp/e_des3.c | 3 ++- providers/implementations/ciphers/cipher_des_hw.c | 3 ++- providers/implementations/ciphers/cipher_tdes_default_hw.c | 3 ++- providers/smtc/self_test_rand.c | 2 +- test/evp_fetch_prov_test.c | 4 ++-- test/siphash_internal_test.c | 2 +- 7 files changed, 12 insertions(+), 8 deletions(-) diff --git a/crypto/evp/e_des.c b/crypto/evp/e_des.c index 653a9bf94..84c1d51c7 100644 --- a/crypto/evp/e_des.c +++ b/crypto/evp/e_des.c @@ -135,7 +135,8 @@ static int des_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) { size_t n, chunk = EVP_MAXCHUNK / 8; - unsigned char c[1], d[1]; + unsigned char c[1]; + unsigned char d[1] = { 0 }; if (inl < chunk) chunk = inl; diff --git a/crypto/evp/e_des3.c b/crypto/evp/e_des3.c index 1a109d11a..cf64174d7 100644 --- a/crypto/evp/e_des3.c +++ b/crypto/evp/e_des3.c @@ -151,7 +151,8 @@ static int des_ede3_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) { size_t n; - unsigned char c[1], d[1]; + unsigned char c[1]; + unsigned char d[1] = { 0 }; if (!EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) inl *= 8; diff --git a/providers/implementations/ciphers/cipher_des_hw.c b/providers/implementations/ciphers/cipher_des_hw.c index a77fcc681..a2d54b46b 100644 --- a/providers/implementations/ciphers/cipher_des_hw.c +++ b/providers/implementations/ciphers/cipher_des_hw.c @@ -136,7 +136,8 @@ static int cipher_hw_des_cfb1_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out, { size_t n, chunk = MAXCHUNK / 8; DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks); - unsigned char c[1], d[1]; + unsigned char c[1]; + unsigned char d[1] = { 0 }; if (inl < chunk) chunk = inl; diff --git a/providers/implementations/ciphers/cipher_tdes_default_hw.c b/providers/implementations/ciphers/cipher_tdes_default_hw.c index 53cbbad57..ccdf3941c 100644 --- a/providers/implementations/ciphers/cipher_tdes_default_hw.c +++ b/providers/implementations/ciphers/cipher_tdes_default_hw.c @@ -99,7 +99,8 @@ static int ossl_cipher_hw_tdes_cfb1(PROV_CIPHER_CTX *ctx, unsigned char *out, { PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx; size_t n; - unsigned char c[1], d[1]; + unsigned char c[1]; + unsigned char d[1] = { 0 }; if (ctx->use_bits == 0) inl *= 8; diff --git a/providers/smtc/self_test_rand.c b/providers/smtc/self_test_rand.c index a35fd965c..01878bcb0 100644 --- a/providers/smtc/self_test_rand.c +++ b/providers/smtc/self_test_rand.c @@ -1956,7 +1956,7 @@ int smtc_randomness_test_poweron(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) { int nbit = 1000000; unsigned char buf[nbit / 8]; - int fail[15]; + int fail[15] = {0}; size_t i = 0, j, k; int retry = 1, res = 0; diff --git a/test/evp_fetch_prov_test.c b/test/evp_fetch_prov_test.c index d237082bd..422665d31 100644 --- a/test/evp_fetch_prov_test.c +++ b/test/evp_fetch_prov_test.c @@ -212,7 +212,7 @@ static int test_explicit_EVP_MD_fetch_by_X509_ALGOR(int idx) int ret = 0; X509_ALGOR *algor = make_algor(NID_sha256); const ASN1_OBJECT *obj; - char id[OSSL_MAX_NAME_SIZE]; + char id[OSSL_MAX_NAME_SIZE] = { 0 }; if (algor == NULL) return 0; @@ -328,7 +328,7 @@ static int test_explicit_EVP_CIPHER_fetch_by_X509_ALGOR(int idx) int ret = 0; X509_ALGOR *algor = make_algor(NID_aes_128_cbc); const ASN1_OBJECT *obj; - char id[OSSL_MAX_NAME_SIZE]; + char id[OSSL_MAX_NAME_SIZE] = { 0 }; if (algor == NULL) return 0; diff --git a/test/siphash_internal_test.c b/test/siphash_internal_test.c index 76ae5ecab..3ab1677d2 100644 --- a/test/siphash_internal_test.c +++ b/test/siphash_internal_test.c @@ -257,7 +257,7 @@ static int test_siphash(int idx) static int test_siphash_basic(void) { SIPHASH siphash = { 0, }; - unsigned char key[SIPHASH_KEY_SIZE]; + static const unsigned char key[SIPHASH_KEY_SIZE] = {0}; unsigned char output[SIPHASH_MAX_DIGEST_SIZE]; /* Use invalid hash size */ From 16b352675cfdab6154403fd3d559e6c694d96dc8 Mon Sep 17 00:00:00 2001 From: K1 Date: Thu, 20 Jun 2024 17:53:29 +0800 Subject: [PATCH 33/66] Fix coverity issues, CID 471315 and 356192 471315, EC_POINTS_new: Reads target of a freed pointer 356192, pkey_dh_derive: Out-of-bounds access to a buffer --- crypto/dh/dh_pmeth.c | 2 +- crypto/ec/ec_lib.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c index 1ad50b850..ea344fbb0 100644 --- a/crypto/dh/dh_pmeth.c +++ b/crypto/dh/dh_pmeth.c @@ -432,7 +432,7 @@ static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) { unsigned char *Z = NULL; - size_t Zlen = 0; + int Zlen = 0; if (!dctx->kdf_outlen || !dctx->kdf_oid) return 0; if (key == NULL) { diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c index e92f582db..62d3b5d56 100644 --- a/crypto/ec/ec_lib.c +++ b/crypto/ec/ec_lib.c @@ -795,8 +795,10 @@ EC_POINTS *EC_POINTS_new(const EC_GROUP *group, int count) for (i = 0; i < count; i++) { point = EC_POINT_new(group); - if (point == NULL) + if (point == NULL) { EC_POINTS_free(ret); + return NULL; + } ret->items[i] = point; } From 45fc71167063bc3b9cfdc3c160430c15cec39a96 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 21 Jun 2024 12:08:34 +0800 Subject: [PATCH 34/66] Fix coverity issues; Delete unused TLSEXT code in NTLS. Fix cid:471326, 471309, 471255, 356194, 356186, 356175. Delete unused TLSEXT code in NTLS. --- crypto/packet.c | 6 +- include/internal/packet.h | 37 +- ssl/statem/extensions_clnt.c | 5 +- ssl/statem/extensions_srvr.c | 19 +- ssl/statem_ntls/ntls_extensions.c | 214 +----- ssl/statem_ntls/ntls_extensions_clnt.c | 797 --------------------- ssl/statem_ntls/ntls_extensions_srvr.c | 950 ------------------------- ssl/statem_ntls/ntls_statem_local.h | 49 -- 8 files changed, 60 insertions(+), 2017 deletions(-) diff --git a/crypto/packet.c b/crypto/packet.c index 09f6a9cea..a9eb1ec4e 100644 --- a/crypto/packet.c +++ b/crypto/packet.c @@ -207,7 +207,7 @@ int WPACKET_set_flags(WPACKET *pkt, unsigned int flags) } /* Store the |value| of length |len| at location |data| */ -static int put_value(unsigned char *data, size_t value, size_t len) +static int put_value(unsigned char *data, uint64_t value, size_t len) { if (data == NULL) return 1; @@ -379,12 +379,12 @@ int WPACKET_start_sub_packet(WPACKET *pkt) return WPACKET_start_sub_packet_len__(pkt, 0); } -int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t size) +int WPACKET_put_bytes__(WPACKET *pkt, uint64_t val, size_t size) { unsigned char *data; /* Internal API, so should not fail */ - if (!ossl_assert(size <= sizeof(unsigned int)) + if (!ossl_assert(size <= sizeof(uint64_t)) || !WPACKET_allocate_bytes(pkt, size, &data) || !put_value(data, val, size)) return 0; diff --git a/include/internal/packet.h b/include/internal/packet.h index 170997db6..b7bb59d7a 100644 --- a/include/internal/packet.h +++ b/include/internal/packet.h @@ -228,6 +228,28 @@ __owur static ossl_inline int PACKET_peek_net_4(const PACKET *pkt, return 1; } +/* + * Peek ahead at 8 bytes in network order from |pkt| and store the value in + * |*data| + */ +__owur static ossl_inline int PACKET_peek_net_8(const PACKET *pkt, + uint64_t *data) +{ + if (PACKET_remaining(pkt) < 8) + return 0; + + *data = ((uint64_t)(*pkt->curr)) << 56; + *data |= ((uint64_t)(*(pkt->curr + 1))) << 48; + *data |= ((uint64_t)(*(pkt->curr + 2))) << 40; + *data |= ((uint64_t)(*(pkt->curr + 3))) << 32; + *data |= ((uint64_t)(*(pkt->curr + 4))) << 24; + *data |= ((uint64_t)(*(pkt->curr + 5))) << 16; + *data |= ((uint64_t)(*(pkt->curr + 6))) << 8; + *data |= *(pkt->curr + 7); + + 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) @@ -252,6 +274,17 @@ __owur static ossl_inline int PACKET_get_net_4_len(PACKET *pkt, size_t *data) return ret; } +/* Get 8 bytes in network order from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_get_net_8(PACKET *pkt, uint64_t *data) +{ + if (!PACKET_peek_net_8(pkt, data)) + return 0; + + packet_forward(pkt, 8); + + return 1; +} + /* 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) @@ -833,7 +866,7 @@ int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len, * 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); +int WPACKET_put_bytes__(WPACKET *pkt, uint64_t val, size_t bytes); /* * Convenience macros for calling WPACKET_put_bytes with different @@ -847,6 +880,8 @@ int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t bytes); WPACKET_put_bytes__((pkt), (val), 3) #define WPACKET_put_bytes_u32(pkt, val) \ WPACKET_put_bytes__((pkt), (val), 4) +#define WPACKET_put_bytes_u64(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 8) /* Set a maximum size that we will not allow the WPACKET to grow beyond */ int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize); diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index 2bc61eb6f..3f914dba5 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -1038,7 +1038,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { #ifndef OPENSSL_NO_TLS1_3 - uint32_t now, agesec, agems = 0; + uint32_t agesec, agems = 0; size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen; unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL; const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL; @@ -1094,8 +1094,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, * this in multiple places in the code, so portability shouldn't be an * issue. */ - now = (uint32_t)time(NULL); - agesec = now - (uint32_t)s->session->time; + agesec = (uint32_t)(time(NULL) - s->session->time); /* * We calculate the age in seconds but the server may work in ms. Due to * rounding errors we could overestimate the age by up to 1s. It is diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c index a025c1313..84bc87f2e 100644 --- a/ssl/statem/extensions_srvr.c +++ b/ssl/statem/extensions_srvr.c @@ -12,16 +12,16 @@ #include "statem_local.h" #include "internal/cryptlib.h" -#define COOKIE_STATE_FORMAT_VERSION 0 +#define COOKIE_STATE_FORMAT_VERSION 1 /* * 2 bytes for packet length, 2 bytes for format version, 2 bytes for * protocol version, 2 bytes for group id, 2 bytes for cipher id, 1 byte for - * key_share present flag, 4 bytes for timestamp, 2 bytes for the hashlen, + * key_share present flag, 8 bytes for timestamp, 2 bytes for the hashlen, * EVP_MAX_MD_SIZE for transcript hash, 1 byte for app cookie length, app cookie * length bytes, SHA256_DIGEST_LENGTH bytes for the HMAC of the whole thing. */ -#define MAX_COOKIE_SIZE (2 + 2 + 2 + 2 + 2 + 1 + 4 + 2 + EVP_MAX_MD_SIZE + 1 \ +#define MAX_COOKIE_SIZE (2 + 2 + 2 + 2 + 2 + 1 + 8 + 2 + EVP_MAX_MD_SIZE + 1 \ + SSL_COOKIE_LENGTH + SHA256_DIGEST_LENGTH) /* @@ -694,7 +694,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, unsigned char hmac[SHA256_DIGEST_LENGTH]; unsigned char hrr[MAX_HRR_SIZE]; size_t rawlen, hmaclen, hrrlen, ciphlen; - unsigned long tm, now; + uint64_t tm, now; /* Ignore any cookie if we're not set up to verify it */ if (s->ctx->verify_stateless_cookie_cb == NULL @@ -795,7 +795,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, } if (!PACKET_get_1(&cookie, &key_share) - || !PACKET_get_net_4(&cookie, &tm) + || !PACKET_get_net_8(&cookie, &tm) || !PACKET_get_length_prefixed_2(&cookie, &chhash) || !PACKET_get_length_prefixed_1(&cookie, &appcookie) || PACKET_remaining(&cookie) != SHA256_DIGEST_LENGTH) { @@ -804,7 +804,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, } /* We tolerate a cookie age of up to 10 minutes (= 60 * 10 seconds) */ - now = (unsigned long)time(NULL); + now = time(NULL); if (tm > now || (now - tm) > 600) { /* Cookie is stale. Ignore it */ return 1; @@ -1135,7 +1135,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, s->ext.early_data_ok = 1; s->ext.ticket_expected = 1; } else { - uint32_t ticket_age = 0, now, agesec, agems; + uint32_t ticket_age = 0, agesec, agems; int ret; /* @@ -1175,8 +1175,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, } ticket_age = (uint32_t)ticket_agel; - now = (uint32_t)time(NULL); - agesec = now - (uint32_t)sess->time; + agesec = (uint32_t)(time(NULL) - sess->time); agems = agesec * (uint32_t)1000; ticket_age -= sess->ext.tick_age_add; @@ -1856,7 +1855,7 @@ EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context, &ciphlen) /* Is there a key_share extension present in this HRR? */ || !WPACKET_put_bytes_u8(pkt, s->s3.peer_tmp == NULL) - || !WPACKET_put_bytes_u32(pkt, (unsigned int)time(NULL)) + || !WPACKET_put_bytes_u64(pkt, time(NULL)) || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &hashval1)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); diff --git a/ssl/statem_ntls/ntls_extensions.c b/ssl/statem_ntls/ntls_extensions.c index b7a77c404..cf5b3b393 100644 --- a/ssl/statem_ntls/ntls_extensions.c +++ b/ssl/statem_ntls/ntls_extensions.c @@ -29,29 +29,15 @@ static int init_alpn(SSL *s, unsigned int context); static int final_alpn(SSL *s, unsigned int context, int sent); static int init_sig_algs_cert(SSL *s, unsigned int context); static int init_sig_algs(SSL *s, unsigned int context); -static int init_certificate_authorities(SSL *s, unsigned int context); -static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt, - unsigned int context, - X509 *x, - size_t chainidx); -static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt, - unsigned int context, X509 *x, - size_t chainidx); - static int init_ec_point_formats(SSL *s, unsigned int context); static int init_etm(SSL *s, unsigned int context); static int init_ems(SSL *s, unsigned int context); static int final_ems(SSL *s, unsigned int context, int sent); -static int init_psk_kex_modes(SSL *s, unsigned int context); -static int final_key_share(SSL *s, unsigned int context, int sent); #ifndef OPENSSL_NO_SRTP static int init_srtp(SSL *s, unsigned int context); #endif static int final_sig_algs(SSL *s, unsigned int context, int sent); -static int final_early_data(SSL *s, unsigned int context, int sent); static int final_maxfragmentlen(SSL *s, unsigned int context, int sent); -static int init_post_handshake_auth(SSL *s, unsigned int context); -static int final_psk(SSL *s, unsigned int context, int sent); /* Structure to define a built-in extension */ typedef struct extensions_definition_st { @@ -267,14 +253,7 @@ static const EXTENSION_DEFINITION ext_defs[] = { /* We do not generate signature_algorithms_cert at present. */ NULL, NULL, NULL }, - { - TLSEXT_TYPE_post_handshake_auth, - SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ONLY, - init_post_handshake_auth, - tls_parse_ctos_post_handshake_auth_ntls, NULL, - NULL, tls_construct_ctos_post_handshake_auth_ntls, - NULL, - }, + INVALID_EXTENSION, /* TLSEXT_IDX_post_handshake_auth */ { TLSEXT_TYPE_signature_algorithms, SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, @@ -292,54 +271,14 @@ static const EXTENSION_DEFINITION ext_defs[] = { tls_construct_stoc_supported_versions_ntls, tls_construct_ctos_supported_versions_ntls, NULL }, - { - TLSEXT_TYPE_psk_kex_modes, - SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS_IMPLEMENTATION_ONLY - | SSL_EXT_TLS1_3_ONLY, - init_psk_kex_modes, tls_parse_ctos_psk_kex_modes_ntls, NULL, NULL, - tls_construct_ctos_psk_kex_modes_ntls, NULL - }, - { - /* - * Must be in this list after supported_groups. We need that to have - * been parsed before we do this one. - */ - TLSEXT_TYPE_key_share, - SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO - | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST | SSL_EXT_TLS_IMPLEMENTATION_ONLY - | SSL_EXT_TLS1_3_ONLY, - NULL, tls_parse_ctos_key_share_ntls, tls_parse_stoc_key_share_ntls, - tls_construct_stoc_key_share_ntls, tls_construct_ctos_key_share_ntls, - final_key_share - }, - { - /* Must be after key_share */ - TLSEXT_TYPE_cookie, - SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST - | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY, - NULL, tls_parse_ctos_cookie_ntls, tls_parse_stoc_cookie_ntls, - tls_construct_stoc_cookie_ntls, tls_construct_ctos_cookie_ntls, NULL - }, - { - TLSEXT_TYPE_early_data, - SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS - | SSL_EXT_TLS1_3_NEW_SESSION_TICKET | SSL_EXT_TLS1_3_ONLY, - NULL, tls_parse_ctos_early_data_ntls, tls_parse_stoc_early_data_ntls, - tls_construct_stoc_early_data_ntls, tls_construct_ctos_early_data_ntls, - final_early_data - }, - { - TLSEXT_TYPE_certificate_authorities, - SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST - | SSL_EXT_TLS1_3_ONLY, - init_certificate_authorities, - tls_parse_certificate_authorities, tls_parse_certificate_authorities, - tls_construct_certificate_authorities, - tls_construct_certificate_authorities, NULL, - }, - INVALID_EXTENSION, /* TLSEXT_TYPE_quic_transport_parameters_draft */ - INVALID_EXTENSION, /* TLSEXT_TYPE_quic_transport_parameters */ - INVALID_EXTENSION, /* TLSEXT_TYPE_compress_certificate */ + INVALID_EXTENSION, /* TLSEXT_IDX_psk_kex_modes */ + INVALID_EXTENSION, /* TLSEXT_IDX_key_share */ + INVALID_EXTENSION, /* TLSEXT_IDX_cookie */ + INVALID_EXTENSION, /* TLSEXT_IDX_early_data */ + INVALID_EXTENSION, /* TLSEXT_IDX_certificate_authorities */ + INVALID_EXTENSION, /* TLSEXT_IDX_quic_transport_params_draft */ + INVALID_EXTENSION, /* TLSEXT_IDX_quic_transport_params */ + INVALID_EXTENSION, /* TLSEXT_IDX_compress_certificate */ { /* Must be immediately before pre_shared_key */ TLSEXT_TYPE_padding, @@ -348,14 +287,7 @@ static const EXTENSION_DEFINITION ext_defs[] = { /* We send this, but don't read it */ NULL, NULL, NULL, tls_construct_ctos_padding_ntls, NULL }, - { - /* Required by the TLSv1.3 spec to always be the last extension */ - TLSEXT_TYPE_psk, - SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO - | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY, - NULL, tls_parse_ctos_psk_ntls, tls_parse_stoc_psk_ntls, tls_construct_stoc_psk_ntls, - tls_construct_ctos_psk_ntls, final_psk - } + INVALID_EXTENSION /* TLSEXT_IDX_psk */ }; /* Check whether an extension's context matches the current context */ @@ -1069,55 +1001,6 @@ static int final_ems(SSL *s, unsigned int context, int sent) return 1; } -static int init_certificate_authorities(SSL *s, unsigned int context) -{ - sk_X509_NAME_pop_free(s->s3.tmp.peer_ca_names, X509_NAME_free); - s->s3.tmp.peer_ca_names = NULL; - return 1; -} - -static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt, - unsigned int context, - X509 *x, - size_t chainidx) -{ - const STACK_OF(X509_NAME) *ca_sk = get_ca_names_ntls(s); - - if (ca_sk == NULL || sk_X509_NAME_num(ca_sk) == 0) - return EXT_RETURN_NOT_SENT; - - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_certificate_authorities) - || !WPACKET_start_sub_packet_u16(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - if (!construct_ca_names_ntls(s, ca_sk, pkt)) { - /* SSLfatal_ntls() already called */ - return EXT_RETURN_FAIL; - } - - if (!WPACKET_close(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - return EXT_RETURN_SENT; -} - -static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt, - unsigned int context, X509 *x, - size_t chainidx) -{ - if (!parse_ca_names_ntls(s, pkt)) - return 0; - if (PACKET_remaining(pkt) != 0) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); - return 0; - } - return 1; -} - #ifndef OPENSSL_NO_SRTP static int init_srtp(SSL *s, unsigned int context) { @@ -1133,17 +1016,6 @@ static int final_sig_algs(SSL *s, unsigned int context, int sent) return 1; } -static int final_key_share(SSL *s, unsigned int context, int sent) -{ - return 1; -} - -static int init_psk_kex_modes(SSL *s, unsigned int context) -{ - s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_NONE; - return 1; -} - int tls_psk_do_binder_ntls(SSL *s, const EVP_MD *md, const unsigned char *msgstart, size_t binderoffset, const unsigned char *binderin, unsigned char *binderout, SSL_SESSION *sess, int sign, @@ -1324,49 +1196,6 @@ int tls_psk_do_binder_ntls(SSL *s, const EVP_MD *md, const unsigned char *msgsta return ret; } -static int final_early_data(SSL *s, unsigned int context, int sent) -{ - if (!sent) - return 1; - - if (!s->server) { - if (context == SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS - && sent - && !s->ext.early_data_ok) { - /* - * If we get here then the server accepted our early_data but we - * later realised that it shouldn't have done (e.g. inconsistent - * ALPN) - */ - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_EARLY_DATA); - return 0; - } - - return 1; - } - - if (s->max_early_data == 0 - || !s->hit - || s->early_data_state != SSL_EARLY_DATA_ACCEPTING - || !s->ext.early_data_ok - || s->hello_retry_request != SSL_HRR_NONE - || (s->allow_early_data_cb != NULL - && !s->allow_early_data_cb(s, - s->allow_early_data_cb_data))) { - s->ext.early_data = SSL_EARLY_DATA_REJECTED; - } else { - s->ext.early_data = SSL_EARLY_DATA_ACCEPTED; - - if (!tls13_change_cipher_state(s, - SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_SERVER_READ)) { - /* SSLfatal_ntls() already called */ - return 0; - } - } - - return 1; -} - static int final_maxfragmentlen(SSL *s, unsigned int context, int sent) { /* @@ -1390,26 +1219,3 @@ static int final_maxfragmentlen(SSL *s, unsigned int context, int sent) return 1; } - -static int init_post_handshake_auth(SSL *s, ossl_unused unsigned int context) -{ - s->post_handshake_auth = SSL_PHA_NONE; - - return 1; -} - -/* - * If clients offer "pre_shared_key" without a "psk_key_exchange_modes" - * extension, servers MUST abort the handshake. - */ -static int final_psk(SSL *s, unsigned int context, int sent) -{ - if (s->server && sent && s->clienthello != NULL - && !s->clienthello->pre_proc_exts[TLSEXT_IDX_psk_kex_modes].present) { - SSLfatal(s, TLS13_AD_MISSING_EXTENSION, - SSL_R_MISSING_PSK_KEX_MODES_EXTENSION); - return 0; - } - - return 1; -} diff --git a/ssl/statem_ntls/ntls_extensions_clnt.c b/ssl/statem_ntls/ntls_extensions_clnt.c index a8872eaf5..75c0812f1 100644 --- a/ssl/statem_ntls/ntls_extensions_clnt.c +++ b/ssl/statem_ntls/ntls_extensions_clnt.c @@ -321,330 +321,6 @@ EXT_RETURN tls_construct_ctos_supported_versions_ntls(SSL *s, WPACKET *pkt, return EXT_RETURN_NOT_SENT; } -/* - * Construct a psk_kex_modes extension. - */ -EXT_RETURN tls_construct_ctos_psk_kex_modes_ntls(SSL *s, WPACKET *pkt, - unsigned int context, X509 *x, - size_t chainidx) -{ -#ifndef OPENSSL_NO_TLS1_3 - int nodhe = s->options & SSL_OP_ALLOW_NO_DHE_KEX; - - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk_kex_modes) - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_start_sub_packet_u8(pkt) - || !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE_DHE) - || (nodhe && !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE)) - || !WPACKET_close(pkt) - || !WPACKET_close(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_KE_DHE; - if (nodhe) - s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE; -#endif - - return EXT_RETURN_SENT; -} - -#ifndef OPENSSL_NO_TLS1_3 -static int add_key_share(SSL *s, WPACKET *pkt, unsigned int curve_id) -{ - unsigned char *encoded_point = NULL; - EVP_PKEY *key_share_key = NULL; - size_t encodedlen; - - if (s->s3.tmp.pkey != NULL) { - if (!ossl_assert(s->hello_retry_request == SSL_HRR_PENDING)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - /* - * Could happen if we got an HRR that wasn't requesting a new key_share - */ - key_share_key = s->s3.tmp.pkey; - } else { - key_share_key = ssl_generate_pkey_group(s, curve_id); - if (key_share_key == NULL) { - /* SSLfatal_ntls() already called */ - return 0; - } - } - - /* Encode the public key. */ - encodedlen = EVP_PKEY_get1_encoded_public_key(key_share_key, - &encoded_point); - if (encodedlen == 0) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_EC_LIB); - goto err; - } - - /* Create KeyShareEntry */ - if (!WPACKET_put_bytes_u16(pkt, curve_id) - || !WPACKET_sub_memcpy_u16(pkt, encoded_point, encodedlen)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - goto err; - } - - /* - * When changing to send more than one key_share we're - * going to need to be able to save more than one EVP_PKEY. For now - * we reuse the existing tmp.pkey - */ - s->s3.tmp.pkey = key_share_key; - s->s3.group_id = curve_id; - OPENSSL_free(encoded_point); - - return 1; - err: - if (s->s3.tmp.pkey == NULL) - EVP_PKEY_free(key_share_key); - OPENSSL_free(encoded_point); - return 0; -} -#endif - -EXT_RETURN tls_construct_ctos_key_share_ntls(SSL *s, WPACKET *pkt, - unsigned int context, X509 *x, - size_t chainidx) -{ -#ifndef OPENSSL_NO_TLS1_3 - size_t i, num_groups = 0; - const uint16_t *pgroups = NULL; - uint16_t curve_id = 0; - - /* key_share extension */ - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) - /* Extension data sub-packet */ - || !WPACKET_start_sub_packet_u16(pkt) - /* KeyShare list sub-packet */ - || !WPACKET_start_sub_packet_u16(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - tls1_get_supported_groups(s, &pgroups, &num_groups); - - /* - * Make the number of key_shares sent configurable. For - * now, we just send one - */ - if (s->s3.group_id != 0) { - curve_id = s->s3.group_id; - } else { - for (i = 0; i < num_groups; i++) { - - if (!tls_group_allowed(s, pgroups[i], SSL_SECOP_CURVE_SUPPORTED)) - continue; - - curve_id = pgroups[i]; - break; - } - } - - if (curve_id == 0) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_SUITABLE_KEY_SHARE); - return EXT_RETURN_FAIL; - } - - if (!add_key_share(s, pkt, curve_id)) { - /* SSLfatal_ntls() already called */ - return EXT_RETURN_FAIL; - } - - if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - return EXT_RETURN_SENT; -#else - return EXT_RETURN_NOT_SENT; -#endif -} - -EXT_RETURN tls_construct_ctos_cookie_ntls(SSL *s, WPACKET *pkt, unsigned int context, - X509 *x, size_t chainidx) -{ - EXT_RETURN ret = EXT_RETURN_FAIL; - - /* Should only be set if we've had an HRR */ - if (s->ext.tls13_cookie_len == 0) - return EXT_RETURN_NOT_SENT; - - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie) - /* Extension data sub-packet */ - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_sub_memcpy_u16(pkt, s->ext.tls13_cookie, - s->ext.tls13_cookie_len) - || !WPACKET_close(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - goto end; - } - - ret = EXT_RETURN_SENT; - end: - OPENSSL_free(s->ext.tls13_cookie); - s->ext.tls13_cookie = NULL; - s->ext.tls13_cookie_len = 0; - - return ret; -} - -EXT_RETURN tls_construct_ctos_early_data_ntls(SSL *s, WPACKET *pkt, - unsigned int context, X509 *x, - size_t chainidx) -{ -#ifndef OPENSSL_NO_PSK - char identity[PSK_MAX_IDENTITY_LEN + 1]; -#endif /* OPENSSL_NO_PSK */ - const unsigned char *id = NULL; - size_t idlen = 0; - SSL_SESSION *psksess = NULL; - SSL_SESSION *edsess = NULL; - const EVP_MD *handmd = NULL; - - if (s->hello_retry_request == SSL_HRR_PENDING) - handmd = ssl_handshake_md(s); - - if (s->psk_use_session_cb != NULL - && (!s->psk_use_session_cb(s, handmd, &id, &idlen, &psksess) - || (psksess != NULL - && psksess->ssl_version != TLS1_3_VERSION))) { - SSL_SESSION_free(psksess); - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_PSK); - return EXT_RETURN_FAIL; - } - -#ifndef OPENSSL_NO_PSK - if (psksess == NULL && s->psk_client_callback != NULL) { - unsigned char psk[PSK_MAX_PSK_LEN]; - size_t psklen = 0; - - memset(identity, 0, sizeof(identity)); - psklen = s->psk_client_callback(s, NULL, identity, sizeof(identity) - 1, - psk, sizeof(psk)); - - if (psklen > PSK_MAX_PSK_LEN) { - SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } else if (psklen > 0) { - const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 }; - const SSL_CIPHER *cipher; - - idlen = strlen(identity); - if (idlen > PSK_MAX_IDENTITY_LEN) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - id = (unsigned char *)identity; - - /* - * We found a PSK using an old style callback. We don't know - * the digest so we default to SHA256 as per the TLSv1.3 spec - */ - cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id); - if (cipher == NULL) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - psksess = SSL_SESSION_new(); - if (psksess == NULL - || !SSL_SESSION_set1_master_key(psksess, psk, psklen) - || !SSL_SESSION_set_cipher(psksess, cipher) - || !SSL_SESSION_set_protocol_version(psksess, TLS1_3_VERSION)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - OPENSSL_cleanse(psk, psklen); - return EXT_RETURN_FAIL; - } - OPENSSL_cleanse(psk, psklen); - } - } -#endif /* OPENSSL_NO_PSK */ - - SSL_SESSION_free(s->psksession); - s->psksession = psksess; - if (psksess != NULL) { - OPENSSL_free(s->psksession_id); - s->psksession_id = OPENSSL_memdup(id, idlen); - if (s->psksession_id == NULL) { - s->psksession_id_len = 0; - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - s->psksession_id_len = idlen; - } - - if (s->early_data_state != SSL_EARLY_DATA_CONNECTING - || (s->session->ext.max_early_data == 0 - && (psksess == NULL || psksess->ext.max_early_data == 0))) { - s->max_early_data = 0; - return EXT_RETURN_NOT_SENT; - } - edsess = s->session->ext.max_early_data != 0 ? s->session : psksess; - s->max_early_data = edsess->ext.max_early_data; - - if (edsess->ext.hostname != NULL) { - if (s->ext.hostname == NULL - || (s->ext.hostname != NULL - && strcmp(s->ext.hostname, edsess->ext.hostname) != 0)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, - SSL_R_INCONSISTENT_EARLY_DATA_SNI); - return EXT_RETURN_FAIL; - } - } - - if ((s->ext.alpn == NULL && edsess->ext.alpn_selected != NULL)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_R_INCONSISTENT_EARLY_DATA_ALPN); - return EXT_RETURN_FAIL; - } - - /* - * Verify that we are offering an ALPN protocol consistent with the early - * data. - */ - if (edsess->ext.alpn_selected != NULL) { - PACKET prots, alpnpkt; - int found = 0; - - if (!PACKET_buf_init(&prots, s->ext.alpn, s->ext.alpn_len)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - while (PACKET_get_length_prefixed_1(&prots, &alpnpkt)) { - if (PACKET_equal(&alpnpkt, edsess->ext.alpn_selected, - edsess->ext.alpn_selected_len)) { - found = 1; - break; - } - } - if (!found) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, - SSL_R_INCONSISTENT_EARLY_DATA_ALPN); - return EXT_RETURN_FAIL; - } - } - - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_close(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - /* - * We set this to rejected here. Later, if the server acknowledges the - * extension, we set it to accepted. - */ - s->ext.early_data = SSL_EARLY_DATA_REJECTED; - s->ext.early_data_ok = 1; - - return EXT_RETURN_SENT; -} - #define F5_WORKAROUND_MIN_MSG_LEN 0xff #define F5_WORKAROUND_MAX_MSG_LEN 0x200 @@ -728,232 +404,6 @@ EXT_RETURN tls_construct_ctos_padding_ntls(SSL *s, WPACKET *pkt, return EXT_RETURN_SENT; } -/* - * Construct the pre_shared_key extension - */ -EXT_RETURN tls_construct_ctos_psk_ntls(SSL *s, WPACKET *pkt, unsigned int context, - X509 *x, size_t chainidx) -{ -#ifndef OPENSSL_NO_TLS1_3 - uint32_t now, agesec, agems = 0; - size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen; - unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL; - const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL; - int dores = 0; - - s->ext.tick_identity = 0; - - /* - * Note: At this stage of the code we only support adding a single - * resumption PSK. If we add support for multiple PSKs then the length - * calculations in the padding extension will need to be adjusted. - */ - - /* - * If this is an incompatible or new session then we have nothing to resume - * so don't add this extension. - */ - if (s->session->ssl_version != TLS1_3_VERSION - || (s->session->ext.ticklen == 0 && s->psksession == NULL)) - return EXT_RETURN_NOT_SENT; - - if (s->hello_retry_request == SSL_HRR_PENDING) - handmd = ssl_handshake_md(s); - - if (s->session->ext.ticklen != 0) { - /* Get the digest associated with the ciphersuite in the session */ - if (s->session->cipher == NULL) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - mdres = ssl_md(s->ctx, s->session->cipher->algorithm2); - if (mdres == NULL) { - /* - * Don't recognize this cipher so we can't use the session. - * Ignore it - */ - goto dopsksess; - } - - if (s->hello_retry_request == SSL_HRR_PENDING && mdres != handmd) { - /* - * Selected ciphersuite hash does not match the hash for the session - * so we can't use it. - */ - goto dopsksess; - } - - /* - * Technically the C standard just says time() returns a time_t and says - * nothing about the encoding of that type. In practice most - * implementations follow POSIX which holds it as an integral type in - * seconds since epoch. We've already made the assumption that we can do - * this in multiple places in the code, so portability shouldn't be an - * issue. - */ - now = (uint32_t)time(NULL); - agesec = now - (uint32_t)s->session->time; - /* - * We calculate the age in seconds but the server may work in ms. Due to - * rounding errors we could overestimate the age by up to 1s. It is - * better to underestimate it. Otherwise, if the RTT is very short, when - * the server calculates the age reported by the client it could be - * bigger than the age calculated on the server - which should never - * happen. - */ - if (agesec > 0) - agesec--; - - if (s->session->ext.tick_lifetime_hint < agesec) { - /* Ticket is too old. Ignore it. */ - goto dopsksess; - } - - /* - * Calculate age in ms. We're just doing it to nearest second. Should be - * good enough. - */ - agems = agesec * (uint32_t)1000; - - if (agesec != 0 && agems / (uint32_t)1000 != agesec) { - /* - * Overflow. Shouldn't happen unless this is a *really* old session. - * If so we just ignore it. - */ - goto dopsksess; - } - - /* - * Obfuscate the age. Overflow here is fine, this addition is supposed - * to be mod 2^32. - */ - agems += s->session->ext.tick_age_add; - - reshashsize = EVP_MD_get_size(mdres); - s->ext.tick_identity++; - dores = 1; - } - - dopsksess: - if (!dores && s->psksession == NULL) - return EXT_RETURN_NOT_SENT; - - if (s->psksession != NULL) { - mdpsk = ssl_md(s->ctx, s->psksession->cipher->algorithm2); - if (mdpsk == NULL) { - /* - * Don't recognize this cipher so we can't use the session. - * If this happens it's an application bug. - */ - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_PSK); - return EXT_RETURN_FAIL; - } - - if (s->hello_retry_request == SSL_HRR_PENDING && mdpsk != handmd) { - /* - * Selected ciphersuite hash does not match the hash for the PSK - * session. This is an application bug. - */ - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_PSK); - return EXT_RETURN_FAIL; - } - - pskhashsize = EVP_MD_get_size(mdpsk); - } - - /* Create the extension, but skip over the binder for now */ - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk) - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_start_sub_packet_u16(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - if (dores) { - if (!WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick, - s->session->ext.ticklen) - || !WPACKET_put_bytes_u32(pkt, agems)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - } - - if (s->psksession != NULL) { - if (!WPACKET_sub_memcpy_u16(pkt, s->psksession_id, - s->psksession_id_len) - || !WPACKET_put_bytes_u32(pkt, 0)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - s->ext.tick_identity++; - } - - if (!WPACKET_close(pkt) - || !WPACKET_get_total_written(pkt, &binderoffset) - || !WPACKET_start_sub_packet_u16(pkt) - || (dores - && !WPACKET_sub_allocate_bytes_u8(pkt, reshashsize, &resbinder)) - || (s->psksession != NULL - && !WPACKET_sub_allocate_bytes_u8(pkt, pskhashsize, &pskbinder)) - || !WPACKET_close(pkt) - || !WPACKET_close(pkt) - || !WPACKET_get_total_written(pkt, &msglen) - /* - * We need to fill in all the sub-packet lengths now so we can - * calculate the HMAC of the message up to the binders - */ - || !WPACKET_fill_lengths(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - msgstart = WPACKET_get_curr(pkt) - msglen; - - if (dores - && tls_psk_do_binder_ntls(s, mdres, msgstart, binderoffset, NULL, - resbinder, s->session, 1, 0) != 1) { - /* SSLfatal_ntls() already called */ - return EXT_RETURN_FAIL; - } - - if (s->psksession != NULL - && tls_psk_do_binder_ntls(s, mdpsk, msgstart, binderoffset, NULL, - pskbinder, s->psksession, 1, 1) != 1) { - /* SSLfatal_ntls() already called */ - return EXT_RETURN_FAIL; - } - - return EXT_RETURN_SENT; -#else - return EXT_RETURN_NOT_SENT; -#endif -} - -EXT_RETURN tls_construct_ctos_post_handshake_auth_ntls(SSL *s, WPACKET *pkt, - ossl_unused unsigned int context, - ossl_unused X509 *x, - ossl_unused size_t chainidx) -{ -#ifndef OPENSSL_NO_TLS1_3 - if (!s->pha_enabled) - return EXT_RETURN_NOT_SENT; - - /* construct extension - 0 length, no contents */ - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_post_handshake_auth) - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_close(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - s->post_handshake_auth = SSL_PHA_EXT_SENT; - - return EXT_RETURN_SENT; -#else - return EXT_RETURN_NOT_SENT; -#endif -} - /* Parse the server's max fragment len extension packet */ int tls_parse_stoc_maxfragmentlen_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) @@ -1353,250 +803,3 @@ int tls_parse_stoc_supported_versions_ntls(SSL *s, PACKET *pkt, unsigned int con /* Ignore supported_versions */ return 1; } - -int tls_parse_stoc_key_share_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, - size_t chainidx) -{ -#ifndef OPENSSL_NO_TLS1_3 - unsigned int group_id; - PACKET encoded_pt; - EVP_PKEY *ckey = s->s3.tmp.pkey, *skey = NULL; - const TLS_GROUP_INFO *ginf = NULL; - - /* Sanity check */ - if (ckey == NULL || s->s3.peer_tmp != NULL) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - if (!PACKET_get_net_2(pkt, &group_id)) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); - return 0; - } - - if ((context & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0) { - const uint16_t *pgroups = NULL; - size_t i, num_groups; - - if (PACKET_remaining(pkt) != 0) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); - return 0; - } - - /* - * It is an error if the HelloRetryRequest wants a key_share that we - * already sent in the first ClientHello - */ - if (group_id == s->s3.group_id) { - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE); - return 0; - } - - /* Validate the selected group is one we support */ - tls1_get_supported_groups(s, &pgroups, &num_groups); - for (i = 0; i < num_groups; i++) { - if (group_id == pgroups[i]) - break; - } - if (i >= num_groups - || !tls_group_allowed(s, group_id, SSL_SECOP_CURVE_SUPPORTED)) { - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE); - return 0; - } - - s->s3.group_id = group_id; - EVP_PKEY_free(s->s3.tmp.pkey); - s->s3.tmp.pkey = NULL; - return 1; - } - - if (group_id != s->s3.group_id) { - /* - * This isn't for the group that we sent in the original - * key_share! - */ - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE); - return 0; - } - /* Retain this group in the SSL_SESSION */ - if (!s->hit) { - s->session->kex_group = group_id; - } else if (group_id != s->session->kex_group) { - /* - * If this is a resumption but changed what group was used, we need - * to record the new group in the session, but the session is not - * a new session and could be in use by other threads. So, make - * a copy of the session to record the new information so that it's - * useful for any sessions resumed from tickets issued on this - * connection. - */ - SSL_SESSION *new_sess; - - if ((new_sess = ssl_session_dup(s->session, 0)) == NULL) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); - return 0; - } - SSL_SESSION_free(s->session); - s->session = new_sess; - s->session->kex_group = group_id; - } - - if ((ginf = tls1_group_id_lookup(s->ctx, group_id)) == NULL) { - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE); - return 0; - } - - if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt) - || PACKET_remaining(&encoded_pt) == 0) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); - return 0; - } - - if (!ginf->is_kem) { - /* Regular KEX */ - skey = EVP_PKEY_new(); - if (skey == NULL || EVP_PKEY_copy_parameters(skey, ckey) <= 0) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_R_COPY_PARAMETERS_FAILED); - EVP_PKEY_free(skey); - return 0; - } - - if (tls13_set_encoded_pub_key(skey, PACKET_data(&encoded_pt), - PACKET_remaining(&encoded_pt)) <= 0) { - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_ECPOINT); - EVP_PKEY_free(skey); - return 0; - } - - if (ssl_derive(s, ckey, skey, 1) == 0) { - /* SSLfatal_ntls() already called */ - EVP_PKEY_free(skey); - return 0; - } - s->s3.peer_tmp = skey; - } else { - /* KEM Mode */ - const unsigned char *ct = PACKET_data(&encoded_pt); - size_t ctlen = PACKET_remaining(&encoded_pt); - - if (ssl_decapsulate(s, ckey, ct, ctlen, 1) == 0) { - /* SSLfatal_ntls() already called */ - return 0; - } - } - s->s3.did_kex = 1; -#endif - - return 1; -} - -int tls_parse_stoc_cookie_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, - size_t chainidx) -{ - PACKET cookie; - - if (!PACKET_as_length_prefixed_2(pkt, &cookie) - || !PACKET_memdup(&cookie, &s->ext.tls13_cookie, - &s->ext.tls13_cookie_len)) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); - return 0; - } - - return 1; -} - -int tls_parse_stoc_early_data_ntls(SSL *s, PACKET *pkt, unsigned int context, - X509 *x, size_t chainidx) -{ - if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) { - unsigned long max_early_data; - - if (!PACKET_get_net_4(pkt, &max_early_data) - || PACKET_remaining(pkt) != 0) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_INVALID_MAX_EARLY_DATA); - return 0; - } - - s->session->ext.max_early_data = max_early_data; - - return 1; - } - - if (PACKET_remaining(pkt) != 0) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); - return 0; - } - - if (!s->ext.early_data_ok - || !s->hit) { - /* - * If we get here then we didn't send early data, or we didn't resume - * using the first identity, or the SNI/ALPN is not consistent so the - * server should not be accepting it. - */ - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_EXTENSION); - return 0; - } - - s->ext.early_data = SSL_EARLY_DATA_ACCEPTED; - - return 1; -} - -int tls_parse_stoc_psk_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, - size_t chainidx) -{ -#ifndef OPENSSL_NO_TLS1_3 - unsigned int identity; - - if (!PACKET_get_net_2(pkt, &identity) || PACKET_remaining(pkt) != 0) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); - return 0; - } - - if (identity >= (unsigned int)s->ext.tick_identity) { - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_PSK_IDENTITY); - return 0; - } - - /* - * Session resumption tickets are always sent before PSK tickets. If the - * ticket index is 0 then it must be for a session resumption ticket if we - * sent two tickets, or if we didn't send a PSK ticket. - */ - if (identity == 0 && (s->psksession == NULL || s->ext.tick_identity == 2)) { - s->hit = 1; - SSL_SESSION_free(s->psksession); - s->psksession = NULL; - return 1; - } - - if (s->psksession == NULL) { - /* Should never happen */ - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - /* - * If we used the external PSK for sending early_data then s->early_secret - * is already set up, so don't overwrite it. Otherwise we copy the - * early_secret across that we generated earlier. - */ - if ((s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY - && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) - || s->session->ext.max_early_data > 0 - || s->psksession->ext.max_early_data == 0) - memcpy(s->early_secret, s->psksession->early_secret, EVP_MAX_MD_SIZE); - - SSL_SESSION_free(s->session); - s->session = s->psksession; - s->psksession = NULL; - s->hit = 1; - /* Early data is only allowed if we used the first ticket */ - if (identity != 0) - s->ext.early_data_ok = 0; -#endif - - return 1; -} - diff --git a/ssl/statem_ntls/ntls_extensions_srvr.c b/ssl/statem_ntls/ntls_extensions_srvr.c index 7d8aacde4..0c4e4d60d 100644 --- a/ssl/statem_ntls/ntls_extensions_srvr.c +++ b/ssl/statem_ntls/ntls_extensions_srvr.c @@ -438,357 +438,6 @@ int tls_parse_ctos_etm_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, return 1; } -/* - * Process a psk_kex_modes extension received in the ClientHello. |pkt| contains - * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. - */ -int tls_parse_ctos_psk_kex_modes_ntls(SSL *s, PACKET *pkt, unsigned int context, - X509 *x, size_t chainidx) -{ -#ifndef OPENSSL_NO_TLS1_3 - PACKET psk_kex_modes; - unsigned int mode; - - if (!PACKET_as_length_prefixed_1(pkt, &psk_kex_modes) - || PACKET_remaining(&psk_kex_modes) == 0) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); - return 0; - } - - while (PACKET_get_1(&psk_kex_modes, &mode)) { - if (mode == TLSEXT_KEX_MODE_KE_DHE) - s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE_DHE; - else if (mode == TLSEXT_KEX_MODE_KE - && (s->options & SSL_OP_ALLOW_NO_DHE_KEX) != 0) - s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE; - } -#endif - - return 1; -} - -/* - * Process a key_share extension received in the ClientHello. |pkt| contains - * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. - */ -int tls_parse_ctos_key_share_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, - size_t chainidx) -{ -#ifndef OPENSSL_NO_TLS1_3 - unsigned int group_id; - PACKET key_share_list, encoded_pt; - const uint16_t *clntgroups, *srvrgroups; - size_t clnt_num_groups, srvr_num_groups; - int found = 0; - - if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0) - return 1; - - /* Sanity check */ - if (s->s3.peer_tmp != NULL) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); - return 0; - } - - /* Get our list of supported groups */ - tls1_get_supported_groups(s, &srvrgroups, &srvr_num_groups); - /* Get the clients list of supported groups. */ - tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups); - if (clnt_num_groups == 0) { - /* - * This can only happen if the supported_groups extension was not sent, - * because we verify that the length is non-zero when we process that - * extension. - */ - SSLfatal_ntls(s, SSL_AD_MISSING_EXTENSION, - SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION); - return 0; - } - - if (s->s3.group_id != 0 && PACKET_remaining(&key_share_list) == 0) { - /* - * If we set a group_id already, then we must have sent an HRR - * requesting a new key_share. If we haven't got one then that is an - * error - */ - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE); - return 0; - } - - while (PACKET_remaining(&key_share_list) > 0) { - if (!PACKET_get_net_2(&key_share_list, &group_id) - || !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt) - || PACKET_remaining(&encoded_pt) == 0) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); - return 0; - } - - /* - * If we already found a suitable key_share we loop through the - * rest to verify the structure, but don't process them. - */ - if (found) - continue; - - /* - * If we sent an HRR then the key_share sent back MUST be for the group - * we requested, and must be the only key_share sent. - */ - if (s->s3.group_id != 0 - && (group_id != s->s3.group_id - || PACKET_remaining(&key_share_list) != 0)) { - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE); - return 0; - } - - /* Check if this share is in supported_groups sent from client */ - if (!check_in_list_ntls(s, group_id, clntgroups, clnt_num_groups, 0)) { - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE); - return 0; - } - - /* Check if this share is for a group we can use */ - if (!check_in_list_ntls(s, group_id, srvrgroups, srvr_num_groups, 1)) { - /* Share not suitable */ - continue; - } - - if ((s->s3.peer_tmp = ssl_generate_param_group(s, group_id)) == NULL) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, - SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); - return 0; - } - - s->s3.group_id = group_id; - /* Cache the selected group ID in the SSL_SESSION */ - s->session->kex_group = group_id; - - if (tls13_set_encoded_pub_key(s->s3.peer_tmp, - PACKET_data(&encoded_pt), - PACKET_remaining(&encoded_pt)) <= 0) { - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_ECPOINT); - return 0; - } - - found = 1; - } -#endif - - return 1; -} - -int tls_parse_ctos_cookie_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, - size_t chainidx) -{ -#ifndef OPENSSL_NO_TLS1_3 - unsigned int format, version, key_share, group_id; - EVP_MD_CTX *hctx; - EVP_PKEY *pkey; - PACKET cookie, raw, chhash, appcookie; - WPACKET hrrpkt; - const unsigned char *data, *mdin, *ciphdata; - unsigned char hmac[SHA256_DIGEST_LENGTH]; - unsigned char hrr[MAX_HRR_SIZE]; - size_t rawlen, hmaclen, hrrlen, ciphlen; - unsigned long tm, now; - - /* Ignore any cookie if we're not set up to verify it */ - if (s->ctx->verify_stateless_cookie_cb == NULL - || (s->s3.flags & TLS1_FLAGS_STATELESS) == 0) - return 1; - - if (!PACKET_as_length_prefixed_2(pkt, &cookie)) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); - return 0; - } - - raw = cookie; - data = PACKET_data(&raw); - rawlen = PACKET_remaining(&raw); - if (rawlen < SHA256_DIGEST_LENGTH - || !PACKET_forward(&raw, rawlen - SHA256_DIGEST_LENGTH)) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); - return 0; - } - mdin = PACKET_data(&raw); - - /* Verify the HMAC of the cookie */ - hctx = EVP_MD_CTX_create(); - pkey = EVP_PKEY_new_raw_private_key_ex(s->ctx->libctx, "HMAC", - s->ctx->propq, - s->session_ctx->ext.cookie_hmac_key, - sizeof(s->session_ctx->ext.cookie_hmac_key)); - if (hctx == NULL || pkey == NULL) { - EVP_MD_CTX_free(hctx); - EVP_PKEY_free(pkey); - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); - return 0; - } - - hmaclen = SHA256_DIGEST_LENGTH; - if (EVP_DigestSignInit_ex(hctx, NULL, "SHA2-256", s->ctx->libctx, - s->ctx->propq, pkey, NULL) <= 0 - || EVP_DigestSign(hctx, hmac, &hmaclen, data, - rawlen - SHA256_DIGEST_LENGTH) <= 0 - || hmaclen != SHA256_DIGEST_LENGTH) { - EVP_MD_CTX_free(hctx); - EVP_PKEY_free(pkey); - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - EVP_MD_CTX_free(hctx); - EVP_PKEY_free(pkey); - - if (CRYPTO_memcmp(hmac, mdin, SHA256_DIGEST_LENGTH) != 0) { - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_COOKIE_MISMATCH); - return 0; - } - - if (!PACKET_get_net_2(&cookie, &format)) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); - return 0; - } - /* Check the cookie format is something we recognise. Ignore it if not */ - if (format != COOKIE_STATE_FORMAT_VERSION) - return 1; - - /* - * The rest of these checks really shouldn't fail since we have verified the - * HMAC above. - */ - - /* Check the version number is sane */ - if (!PACKET_get_net_2(&cookie, &version)) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); - return 0; - } - if (version != TLS1_3_VERSION) { - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, - SSL_R_BAD_PROTOCOL_VERSION_NUMBER); - return 0; - } - - if (!PACKET_get_net_2(&cookie, &group_id)) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); - return 0; - } - - ciphdata = PACKET_data(&cookie); - if (!PACKET_forward(&cookie, 2)) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); - return 0; - } - if (group_id != s->s3.group_id - || s->s3.tmp.new_cipher - != ssl_get_cipher_by_char(s, ciphdata, 0)) { - /* - * We chose a different cipher or group id this time around to what is - * in the cookie. Something must have changed. - */ - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_CIPHER); - return 0; - } - - if (!PACKET_get_1(&cookie, &key_share) - || !PACKET_get_net_4(&cookie, &tm) - || !PACKET_get_length_prefixed_2(&cookie, &chhash) - || !PACKET_get_length_prefixed_1(&cookie, &appcookie) - || PACKET_remaining(&cookie) != SHA256_DIGEST_LENGTH) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); - return 0; - } - - /* We tolerate a cookie age of up to 10 minutes (= 60 * 10 seconds) */ - now = (unsigned long)time(NULL); - if (tm > now || (now - tm) > 600) { - /* Cookie is stale. Ignore it */ - return 1; - } - - /* Verify the app cookie */ - if (s->ctx->verify_stateless_cookie_cb(s, PACKET_data(&appcookie), - PACKET_remaining(&appcookie)) == 0) { - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_COOKIE_MISMATCH); - return 0; - } - - /* - * Reconstruct the HRR that we would have sent in response to the original - * ClientHello so we can add it to the transcript hash. - * Note: This won't work with custom HRR extensions - */ - if (!WPACKET_init_static_len(&hrrpkt, hrr, sizeof(hrr), 0)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - if (!WPACKET_put_bytes_u8(&hrrpkt, SSL3_MT_SERVER_HELLO) - || !WPACKET_start_sub_packet_u24(&hrrpkt) - || !WPACKET_put_bytes_u16(&hrrpkt, TLS1_2_VERSION) - || !WPACKET_memcpy(&hrrpkt, hrrrandom_ntls, SSL3_RANDOM_SIZE) - || !WPACKET_sub_memcpy_u8(&hrrpkt, s->tmp_session_id, - s->tmp_session_id_len) - || !s->method->put_cipher_by_char(s->s3.tmp.new_cipher, &hrrpkt, - &ciphlen) - || !WPACKET_put_bytes_u8(&hrrpkt, 0) - || !WPACKET_start_sub_packet_u16(&hrrpkt)) { - WPACKET_cleanup(&hrrpkt); - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_supported_versions) - || !WPACKET_start_sub_packet_u16(&hrrpkt) - || !WPACKET_put_bytes_u16(&hrrpkt, s->version) - || !WPACKET_close(&hrrpkt)) { - WPACKET_cleanup(&hrrpkt); - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - if (key_share) { - if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_key_share) - || !WPACKET_start_sub_packet_u16(&hrrpkt) - || !WPACKET_put_bytes_u16(&hrrpkt, s->s3.group_id) - || !WPACKET_close(&hrrpkt)) { - WPACKET_cleanup(&hrrpkt); - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - } - if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_cookie) - || !WPACKET_start_sub_packet_u16(&hrrpkt) - || !WPACKET_sub_memcpy_u16(&hrrpkt, data, rawlen) - || !WPACKET_close(&hrrpkt) /* cookie extension */ - || !WPACKET_close(&hrrpkt) /* extension block */ - || !WPACKET_close(&hrrpkt) /* message */ - || !WPACKET_get_total_written(&hrrpkt, &hrrlen) - || !WPACKET_finish(&hrrpkt)) { - WPACKET_cleanup(&hrrpkt); - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - /* Reconstruct the transcript hash */ - if (!create_synthetic_message_hash_ntls(s, PACKET_data(&chhash), - PACKET_remaining(&chhash), hrr, - hrrlen)) { - /* SSLfatal_ntls() already called */ - return 0; - } - - /* Act as if this ClientHello came after a HelloRetryRequest */ - s->hello_retry_request = 1; - - s->ext.cookieok = 1; -#endif - - return 1; -} - int tls_parse_ctos_supported_groups_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { @@ -803,299 +452,6 @@ int tls_parse_ctos_ems_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, return 1; } - -int tls_parse_ctos_early_data_ntls(SSL *s, PACKET *pkt, unsigned int context, - X509 *x, size_t chainidx) -{ - if (PACKET_remaining(pkt) != 0) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); - return 0; - } - - if (s->hello_retry_request != SSL_HRR_NONE) { - SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_EXTENSION); - return 0; - } - - return 1; -} - -static SSL_TICKET_STATUS tls_get_stateful_ticket(SSL *s, PACKET *tick, - SSL_SESSION **sess) -{ - SSL_SESSION *tmpsess = NULL; - - s->ext.ticket_expected = 1; - - switch (PACKET_remaining(tick)) { - case 0: - return SSL_TICKET_EMPTY; - - case SSL_MAX_SSL_SESSION_ID_LENGTH: - break; - - default: - return SSL_TICKET_NO_DECRYPT; - } - - tmpsess = lookup_sess_in_cache(s, PACKET_data(tick), - SSL_MAX_SSL_SESSION_ID_LENGTH); - - if (tmpsess == NULL) - return SSL_TICKET_NO_DECRYPT; - - *sess = tmpsess; - return SSL_TICKET_SUCCESS; -} - -int tls_parse_ctos_psk_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, - size_t chainidx) -{ - PACKET identities, binders, binder; - size_t binderoffset, hashsize; - SSL_SESSION *sess = NULL; - unsigned int id, i, ext = 0; - const EVP_MD *md = NULL; - - /* - * If we have no PSK kex mode that we recognise then we can't resume so - * ignore this extension - */ - if ((s->ext.psk_kex_mode - & (TLSEXT_KEX_MODE_FLAG_KE | TLSEXT_KEX_MODE_FLAG_KE_DHE)) == 0) - return 1; - - if (!PACKET_get_length_prefixed_2(pkt, &identities)) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); - return 0; - } - - s->ext.ticket_expected = 0; - for (id = 0; PACKET_remaining(&identities) != 0; id++) { - PACKET identity; - unsigned long ticket_agel; - size_t idlen; - - if (!PACKET_get_length_prefixed_2(&identities, &identity) - || !PACKET_get_net_4(&identities, &ticket_agel)) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); - return 0; - } - - idlen = PACKET_remaining(&identity); - if (s->psk_find_session_cb != NULL - && !s->psk_find_session_cb(s, PACKET_data(&identity), idlen, - &sess)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_EXTENSION); - return 0; - } - -#ifndef OPENSSL_NO_PSK - if(sess == NULL - && s->psk_server_callback != NULL - && idlen <= PSK_MAX_IDENTITY_LEN) { - char *pskid = NULL; - unsigned char pskdata[PSK_MAX_PSK_LEN]; - unsigned int pskdatalen; - - if (!PACKET_strndup(&identity, &pskid)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - pskdatalen = s->psk_server_callback(s, pskid, pskdata, - sizeof(pskdata)); - OPENSSL_free(pskid); - if (pskdatalen > PSK_MAX_PSK_LEN) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } else if (pskdatalen > 0) { - const SSL_CIPHER *cipher; - const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 }; - - /* - * We found a PSK using an old style callback. We don't know - * the digest so we default to SHA256 as per the TLSv1.3 spec - */ - cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id); - if (cipher == NULL) { - OPENSSL_cleanse(pskdata, pskdatalen); - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - sess = SSL_SESSION_new(); - if (sess == NULL - || !SSL_SESSION_set1_master_key(sess, pskdata, - pskdatalen) - || !SSL_SESSION_set_cipher(sess, cipher) - || !SSL_SESSION_set_protocol_version(sess, - TLS1_3_VERSION)) { - OPENSSL_cleanse(pskdata, pskdatalen); - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - goto err; - } - OPENSSL_cleanse(pskdata, pskdatalen); - } - } -#endif /* OPENSSL_NO_PSK */ - - if (sess != NULL) { - /* We found a PSK */ - SSL_SESSION *sesstmp = ssl_session_dup(sess, 0); - - if (sesstmp == NULL) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - SSL_SESSION_free(sess); - sess = sesstmp; - - /* - * We've just been told to use this session for this context so - * make sure the sid_ctx matches up. - */ - memcpy(sess->sid_ctx, s->sid_ctx, s->sid_ctx_length); - sess->sid_ctx_length = s->sid_ctx_length; - ext = 1; - if (id == 0) - s->ext.early_data_ok = 1; - s->ext.ticket_expected = 1; - } else { - uint32_t ticket_age = 0, now, agesec, agems; - int ret; - - /* - * If we are using anti-replay protection then we behave as if - * SSL_OP_NO_TICKET is set - we are caching tickets anyway so there - * is no point in using full stateless tickets. - */ - if ((s->options & SSL_OP_NO_TICKET) != 0 - || (s->max_early_data > 0 - && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0)) - ret = tls_get_stateful_ticket(s, &identity, &sess); - else - ret = tls_decrypt_ticket(s, PACKET_data(&identity), - PACKET_remaining(&identity), NULL, 0, - &sess); - - if (ret == SSL_TICKET_EMPTY) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); - return 0; - } - - if (ret == SSL_TICKET_FATAL_ERR_MALLOC - || ret == SSL_TICKET_FATAL_ERR_OTHER) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - if (ret == SSL_TICKET_NONE || ret == SSL_TICKET_NO_DECRYPT) - continue; - - /* Check for replay */ - if (s->max_early_data > 0 - && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0 - && !SSL_CTX_remove_session(s->session_ctx, sess)) { - SSL_SESSION_free(sess); - sess = NULL; - continue; - } - - ticket_age = (uint32_t)ticket_agel; - now = (uint32_t)time(NULL); - agesec = now - (uint32_t)sess->time; - agems = agesec * (uint32_t)1000; - ticket_age -= sess->ext.tick_age_add; - - /* - * For simplicity we do our age calculations in seconds. If the - * client does it in ms then it could appear that their ticket age - * is longer than ours (our ticket age calculation should always be - * slightly longer than the client's due to the network latency). - * Therefore we add 1000ms to our age calculation to adjust for - * rounding errors. - */ - if (id == 0 - && sess->timeout >= (long)agesec - && agems / (uint32_t)1000 == agesec - && ticket_age <= agems + 1000 - && ticket_age + TICKET_AGE_ALLOWANCE >= agems + 1000) { - /* - * Ticket age is within tolerance and not expired. We allow it - * for early data - */ - s->ext.early_data_ok = 1; - } - } - - md = ssl_md(s->ctx, sess->cipher->algorithm2); - if (!EVP_MD_is_a(md, - EVP_MD_get0_name(ssl_md(s->ctx, - s->s3.tmp.new_cipher->algorithm2)))) { - /* The ciphersuite is not compatible with this session. */ - SSL_SESSION_free(sess); - sess = NULL; - s->ext.early_data_ok = 0; - s->ext.ticket_expected = 0; - continue; - } - break; - } - - if (sess == NULL) - return 1; - - binderoffset = PACKET_data(pkt) - (const unsigned char *)s->init_buf->data; - hashsize = EVP_MD_get_size(md); - - if (!PACKET_get_length_prefixed_2(pkt, &binders)) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); - goto err; - } - - for (i = 0; i <= id; i++) { - if (!PACKET_get_length_prefixed_1(&binders, &binder)) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); - goto err; - } - } - - if (PACKET_remaining(&binder) != hashsize) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); - goto err; - } - if (tls_psk_do_binder_ntls(s, md, (const unsigned char *)s->init_buf->data, - binderoffset, PACKET_data(&binder), NULL, sess, 0, - ext) != 1) { - /* SSLfatal_ntls() already called */ - goto err; - } - - s->ext.tick_identity = id; - - SSL_SESSION_free(s->session); - s->session = sess; - return 1; -err: - SSL_SESSION_free(sess); - return 0; -} - -int tls_parse_ctos_post_handshake_auth_ntls(SSL *s, PACKET *pkt, - ossl_unused unsigned int context, - ossl_unused X509 *x, - ossl_unused size_t chainidx) -{ - if (PACKET_remaining(pkt) != 0) { - SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, - SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR); - return 0; - } - - s->post_handshake_auth = SSL_PHA_EXT_RECEIVED; - - return 1; -} - EXT_RETURN tls_construct_stoc_server_name_ntls(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) @@ -1301,309 +657,3 @@ EXT_RETURN tls_construct_stoc_supported_versions_ntls(SSL *s, WPACKET *pkt, /* No supported_versions */ return EXT_RETURN_NOT_SENT; } - -EXT_RETURN tls_construct_stoc_key_share_ntls(SSL *s, WPACKET *pkt, - unsigned int context, X509 *x, - size_t chainidx) -{ -#ifndef OPENSSL_NO_TLS1_3 - unsigned char *encodedPoint; - size_t encoded_pt_len = 0; - EVP_PKEY *ckey = s->s3.peer_tmp, *skey = NULL; - const TLS_GROUP_INFO *ginf = NULL; - - if (s->hello_retry_request == SSL_HRR_PENDING) { - if (ckey != NULL) { - /* Original key_share was acceptable so don't ask for another one */ - return EXT_RETURN_NOT_SENT; - } - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_put_bytes_u16(pkt, s->s3.group_id) - || !WPACKET_close(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - return EXT_RETURN_SENT; - } - - if (ckey == NULL) { - /* No key_share received from client - must be resuming */ - if (!s->hit || !tls13_generate_handshake_secret(s, NULL, 0)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - return EXT_RETURN_NOT_SENT; - } - if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0) { - /* - * PSK ('hit') and explicitly not doing DHE (if the client sent the - * DHE option we always take it); don't send key share. - */ - return EXT_RETURN_NOT_SENT; - } - - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_put_bytes_u16(pkt, s->s3.group_id)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - if ((ginf = tls1_group_id_lookup(s->ctx, s->s3.group_id)) == NULL) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - if (!ginf->is_kem) { - /* Regular KEX */ - skey = ssl_generate_pkey(s, ckey); - if (skey == NULL) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); - return EXT_RETURN_FAIL; - } - - /* Generate encoding of server key */ - encoded_pt_len = EVP_PKEY_get1_encoded_public_key(skey, &encodedPoint); - if (encoded_pt_len == 0) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_EC_LIB); - EVP_PKEY_free(skey); - return EXT_RETURN_FAIL; - } - - if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len) - || !WPACKET_close(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - EVP_PKEY_free(skey); - OPENSSL_free(encodedPoint); - return EXT_RETURN_FAIL; - } - OPENSSL_free(encodedPoint); - - /* - * This causes the crypto state to be updated based on the derived keys - */ - s->s3.tmp.pkey = skey; - if (ssl_derive(s, skey, ckey, 1) == 0) { - /* SSLfatal_ntls() already called */ - return EXT_RETURN_FAIL; - } - } else { - /* KEM mode */ - unsigned char *ct = NULL; - size_t ctlen = 0; - - /* - * This does not update the crypto state. - * - * The generated pms is stored in `s->s3.tmp.pms` to be later used via - * ssl_gensecret(). - */ - if (ssl_encapsulate(s, ckey, &ct, &ctlen, 0) == 0) { - /* SSLfatal_ntls() already called */ - return EXT_RETURN_FAIL; - } - - if (ctlen == 0) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - OPENSSL_free(ct); - return EXT_RETURN_FAIL; - } - - if (!WPACKET_sub_memcpy_u16(pkt, ct, ctlen) - || !WPACKET_close(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - OPENSSL_free(ct); - return EXT_RETURN_FAIL; - } - OPENSSL_free(ct); - - /* - * This causes the crypto state to be updated based on the generated pms - */ - if (ssl_gensecret(s, s->s3.tmp.pms, s->s3.tmp.pmslen) == 0) { - /* SSLfatal_ntls() already called */ - return EXT_RETURN_FAIL; - } - } - s->s3.did_kex = 1; - return EXT_RETURN_SENT; -#else - return EXT_RETURN_FAIL; -#endif -} - -EXT_RETURN tls_construct_stoc_cookie_ntls(SSL *s, WPACKET *pkt, unsigned int context, - X509 *x, size_t chainidx) -{ -#ifndef OPENSSL_NO_TLS1_3 - unsigned char *hashval1, *hashval2, *appcookie1, *appcookie2, *cookie; - unsigned char *hmac, *hmac2; - size_t startlen, ciphlen, totcookielen, hashlen, hmaclen, appcookielen; - EVP_MD_CTX *hctx; - EVP_PKEY *pkey; - int ret = EXT_RETURN_FAIL; - - if ((s->s3.flags & TLS1_FLAGS_STATELESS) == 0) - return EXT_RETURN_NOT_SENT; - - if (s->ctx->gen_stateless_cookie_cb == NULL) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_COOKIE_CALLBACK_SET); - return EXT_RETURN_FAIL; - } - - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie) - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_get_total_written(pkt, &startlen) - || !WPACKET_reserve_bytes(pkt, MAX_COOKIE_SIZE, &cookie) - || !WPACKET_put_bytes_u16(pkt, COOKIE_STATE_FORMAT_VERSION) - || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION) - || !WPACKET_put_bytes_u16(pkt, s->s3.group_id) - || !s->method->put_cipher_by_char(s->s3.tmp.new_cipher, pkt, - &ciphlen) - /* Is there a key_share extension present in this HRR? */ - || !WPACKET_put_bytes_u8(pkt, s->s3.peer_tmp == NULL) - || !WPACKET_put_bytes_u32(pkt, (unsigned int)time(NULL)) - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &hashval1)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - /* - * Get the hash of the initial ClientHello. ssl_handshake_hash() operates - * on raw buffers, so we first reserve sufficient bytes (above) and then - * subsequently allocate them (below) - */ - if (!ssl3_digest_cached_records(s, 0) - || !ssl_handshake_hash(s, hashval1, EVP_MAX_MD_SIZE, &hashlen)) { - /* SSLfatal_ntls() already called */ - return EXT_RETURN_FAIL; - } - - if (!WPACKET_allocate_bytes(pkt, hashlen, &hashval2) - || !ossl_assert(hashval1 == hashval2) - || !WPACKET_close(pkt) - || !WPACKET_start_sub_packet_u8(pkt) - || !WPACKET_reserve_bytes(pkt, SSL_COOKIE_LENGTH, &appcookie1)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - /* Generate the application cookie */ - if (s->ctx->gen_stateless_cookie_cb(s, appcookie1, &appcookielen) == 0) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_R_COOKIE_GEN_CALLBACK_FAILURE); - return EXT_RETURN_FAIL; - } - - if (!WPACKET_allocate_bytes(pkt, appcookielen, &appcookie2) - || !ossl_assert(appcookie1 == appcookie2) - || !WPACKET_close(pkt) - || !WPACKET_get_total_written(pkt, &totcookielen) - || !WPACKET_reserve_bytes(pkt, SHA256_DIGEST_LENGTH, &hmac)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - hmaclen = SHA256_DIGEST_LENGTH; - - totcookielen -= startlen; - if (!ossl_assert(totcookielen <= MAX_COOKIE_SIZE - SHA256_DIGEST_LENGTH)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - /* HMAC the cookie */ - hctx = EVP_MD_CTX_create(); - pkey = EVP_PKEY_new_raw_private_key_ex(s->ctx->libctx, "HMAC", - s->ctx->propq, - s->session_ctx->ext.cookie_hmac_key, - sizeof(s->session_ctx->ext.cookie_hmac_key)); - if (hctx == NULL || pkey == NULL) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (EVP_DigestSignInit_ex(hctx, NULL, "SHA2-256", s->ctx->libctx, - s->ctx->propq, pkey, NULL) <= 0 - || EVP_DigestSign(hctx, hmac, &hmaclen, cookie, - totcookielen) <= 0) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - goto err; - } - - if (!ossl_assert(totcookielen + hmaclen <= MAX_COOKIE_SIZE)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - goto err; - } - - if (!WPACKET_allocate_bytes(pkt, hmaclen, &hmac2) - || !ossl_assert(hmac == hmac2) - || !ossl_assert(cookie == hmac - totcookielen) - || !WPACKET_close(pkt) - || !WPACKET_close(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - goto err; - } - - ret = EXT_RETURN_SENT; - - err: - EVP_MD_CTX_free(hctx); - EVP_PKEY_free(pkey); - return ret; -#else - return EXT_RETURN_FAIL; -#endif -} - -EXT_RETURN tls_construct_stoc_early_data_ntls(SSL *s, WPACKET *pkt, - unsigned int context, X509 *x, - size_t chainidx) -{ - if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) { - if (s->max_early_data == 0) - return EXT_RETURN_NOT_SENT; - - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_put_bytes_u32(pkt, s->max_early_data) - || !WPACKET_close(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - return EXT_RETURN_SENT; - } - - if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED) - return EXT_RETURN_NOT_SENT; - - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_close(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - return EXT_RETURN_SENT; -} - -EXT_RETURN tls_construct_stoc_psk_ntls(SSL *s, WPACKET *pkt, unsigned int context, - X509 *x, size_t chainidx) -{ - if (!s->hit) - return EXT_RETURN_NOT_SENT; - - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk) - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_put_bytes_u16(pkt, s->ext.tick_identity) - || !WPACKET_close(pkt)) { - SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return EXT_RETURN_FAIL; - } - - return EXT_RETURN_SENT; -} - diff --git a/ssl/statem_ntls/ntls_statem_local.h b/ssl/statem_ntls/ntls_statem_local.h index c48ad6481..0cffbbe93 100644 --- a/ssl/statem_ntls/ntls_statem_local.h +++ b/ssl/statem_ntls/ntls_statem_local.h @@ -205,8 +205,6 @@ int tls_parse_ctos_server_name_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); int tls_parse_ctos_maxfragmentlen_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); -int tls_parse_ctos_early_data_ntls(SSL *s, PACKET *pkt, unsigned int context, - X509 *x, size_t chainidx); int tls_parse_ctos_ec_pt_formats_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); int tls_parse_ctos_supported_groups_ntls(SSL *s, PACKET *pkt, unsigned int context, @@ -233,24 +231,11 @@ int tls_parse_ctos_use_srtp_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 #endif int tls_parse_ctos_etm_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); -int tls_parse_ctos_key_share_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, - size_t chainidx); -int tls_parse_ctos_cookie_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, - size_t chainidx); int tls_parse_ctos_ems_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); -int tls_parse_ctos_psk_kex_modes_ntls(SSL *s, PACKET *pkt, unsigned int context, - X509 *x, size_t chainidx); -int tls_parse_ctos_psk_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, - size_t chainidx); -int tls_parse_ctos_post_handshake_auth_ntls(SSL *, PACKET *pkt, unsigned int context, - X509 *x, size_t chainidx); EXT_RETURN tls_construct_stoc_server_name_ntls(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); -EXT_RETURN tls_construct_stoc_early_data_ntls(SSL *s, WPACKET *pkt, - unsigned int context, X509 *x, - size_t chainidx); EXT_RETURN tls_construct_stoc_maxfragmentlen_ntls(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); @@ -286,15 +271,6 @@ EXT_RETURN tls_construct_stoc_ems_ntls(SSL *s, WPACKET *pkt, unsigned int contex EXT_RETURN tls_construct_stoc_supported_versions_ntls(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); -EXT_RETURN tls_construct_stoc_key_share_ntls(SSL *s, WPACKET *pkt, - unsigned int context, X509 *x, - size_t chainidx); -EXT_RETURN tls_construct_stoc_cookie_ntls(SSL *s, WPACKET *pkt, unsigned int context, - X509 *x, size_t chainidx); - -EXT_RETURN tls_construct_stoc_psk_ntls(SSL *s, WPACKET *pkt, unsigned int context, - X509 *x, size_t chainidx); - /* Client Extension processing */ EXT_RETURN tls_construct_ctos_server_name_ntls(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); @@ -307,9 +283,6 @@ EXT_RETURN tls_construct_ctos_ec_pt_formats_ntls(SSL *s, WPACKET *pkt, EXT_RETURN tls_construct_ctos_supported_groups_ntls(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); -EXT_RETURN tls_construct_ctos_early_data_ntls(SSL *s, WPACKET *pkt, - unsigned int context, X509 *x, - size_t chainidx); EXT_RETURN tls_construct_ctos_session_ticket_ntls(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); @@ -342,26 +315,11 @@ EXT_RETURN tls_construct_ctos_ems_ntls(SSL *s, WPACKET *pkt, unsigned int contex EXT_RETURN tls_construct_ctos_supported_versions_ntls(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); -EXT_RETURN tls_construct_ctos_key_share_ntls(SSL *s, WPACKET *pkt, - unsigned int context, X509 *x, - size_t chainidx); -EXT_RETURN tls_construct_ctos_psk_kex_modes_ntls(SSL *s, WPACKET *pkt, - unsigned int context, X509 *x, - size_t chainidx); -EXT_RETURN tls_construct_ctos_cookie_ntls(SSL *s, WPACKET *pkt, unsigned int context, - X509 *x, size_t chainidx); EXT_RETURN tls_construct_ctos_padding_ntls(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); -EXT_RETURN tls_construct_ctos_psk_ntls(SSL *s, WPACKET *pkt, unsigned int context, - X509 *x, size_t chainidx); -EXT_RETURN tls_construct_ctos_post_handshake_auth_ntls(SSL *s, WPACKET *pkt, unsigned int context, - X509 *x, size_t chainidx); - int tls_parse_stoc_server_name_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); -int tls_parse_stoc_early_data_ntls(SSL *s, PACKET *pkt, unsigned int context, - X509 *x, size_t chainidx); int tls_parse_stoc_maxfragmentlen_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); int tls_parse_stoc_ec_pt_formats_ntls(SSL *s, PACKET *pkt, unsigned int context, @@ -392,13 +350,6 @@ int tls_parse_stoc_ems_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); int tls_parse_stoc_supported_versions_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); -int tls_parse_stoc_key_share_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, - size_t chainidx); -int tls_parse_stoc_cookie_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, - size_t chainidx); -int tls_parse_stoc_psk_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, - size_t chainidx); - int tls_handle_alpn_ntls(SSL *s); int tls13_save_handshake_digest_for_pha_ntls(SSL *s); From 63a0680fcfacb0f61d591e3816346cd9bc09cc8b Mon Sep 17 00:00:00 2001 From: K1 Date: Wed, 19 Jun 2024 22:58:52 +0800 Subject: [PATCH 35/66] Fix coverity issues, resource leaks CID: 488393, 471339, 471290, 471289, 471287, 471282, 471281, 471279, 471246, 471237, 471221, 471204, 471196, 471180, 471171, 471169, 471162, 278385, 21756. --- apps/speed.c | 1 + crypto/ec/ec_elgamal_crypt.c | 2 +- crypto/ec/ec_lib.c | 18 ++++++++---------- crypto/zkp/bulletproofs/bulletproofs_encode.c | 4 +++- crypto/zkp/gadget/zkp_range_proof.c | 1 + crypto/zkp/nizk/nizk_encode.c | 2 +- test/bntest.c | 1 + test/bulletproofs_test.c | 2 ++ test/nizk_test.c | 4 ++++ test/paillier_internal_test.c | 2 ++ test/pkcs12_format_test.c | 1 + test/zkp_gadget_test.c | 3 --- 12 files changed, 25 insertions(+), 16 deletions(-) diff --git a/apps/speed.c b/apps/speed.c index 1df5ce69d..e6aaa466c 100644 --- a/apps/speed.c +++ b/apps/speed.c @@ -5357,6 +5357,7 @@ static int do_multi(int multi, int size_num) close(1); if (dup(fd[1]) == -1) { BIO_printf(bio_err, "dup failed\n"); + close(fd[1]); exit(1); } close(fd[1]); diff --git a/crypto/ec/ec_elgamal_crypt.c b/crypto/ec/ec_elgamal_crypt.c index a6fe59749..6661e8bff 100644 --- a/crypto/ec/ec_elgamal_crypt.c +++ b/crypto/ec/ec_elgamal_crypt.c @@ -199,7 +199,7 @@ EC_ELGAMAL_MR_CTX *EC_ELGAMAL_MR_CTX_new(STACK_OF(EC_KEY) *keys, const EC_POINT if (h != NULL) { if (!(ctx->h = EC_POINT_dup(h, ctx->group))) - return 0; + goto err; } else { ctx->h = EC_POINT_new(group); if (ctx->h == NULL) { diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c index e92f582db..48b4539a8 100644 --- a/crypto/ec/ec_lib.c +++ b/crypto/ec/ec_lib.c @@ -1544,13 +1544,13 @@ int EC_POINTs_from_strings(const EC_GROUP *group, EC_POINTS **r, { int ret = 0; BN_CTX *new_ctx = NULL; - EC_POINTS *result = NULL; + EC_POINTS *result = NULL, *new_r = NULL; if (r == NULL || strings == NULL || num <= 0) return 0; if (*r == NULL) { - result = EC_POINTS_new(group, (uint32_t)num); + new_r = result = EC_POINTS_new(group, (uint32_t)num); if (result == NULL) return 0; } else { @@ -1574,14 +1574,13 @@ int EC_POINTs_from_strings(const EC_GROUP *group, EC_POINTS **r, } #endif - result = NULL; - /* * TODO */ err: BN_CTX_free(new_ctx); - EC_POINTS_free(result); + if (*r != new_r) + EC_POINTS_free(new_r); return ret; } @@ -1600,13 +1599,13 @@ int EC_POINTs_from_strings_scalar_mul(const EC_GROUP *group, EC_POINTS **r, { int ret = 0; BN_CTX *new_ctx = NULL; - EC_POINTS *result = NULL; + EC_POINTS *result, *new_r = NULL; if (r == NULL || strings == NULL || num <= 0) return 0; if (*r == NULL) { - result = EC_POINTS_new(group, (uint32_t)num); + new_r = result = EC_POINTS_new(group, (uint32_t)num); if (result == NULL) return 0; } else { @@ -1632,14 +1631,13 @@ int EC_POINTs_from_strings_scalar_mul(const EC_GROUP *group, EC_POINTS **r, } #endif - result = NULL; - /* * TODO */ err: BN_CTX_free(new_ctx); - EC_POINTS_free(result); + if (*r != new_r) + EC_POINTS_free(new_r); return ret; } diff --git a/crypto/zkp/bulletproofs/bulletproofs_encode.c b/crypto/zkp/bulletproofs/bulletproofs_encode.c index 94556c266..a208ef26a 100644 --- a/crypto/zkp/bulletproofs/bulletproofs_encode.c +++ b/crypto/zkp/bulletproofs/bulletproofs_encode.c @@ -184,8 +184,10 @@ static int bp_inner_product_proof_encode(bp_inner_product_proof_t *ip_proof, len += sk_len; - if (out == NULL) + if (out == NULL) { + sk_BIGNUM_free(sk_bn); return len; + } sk_len = zkp_stack_of_bignum_encode(sk_bn, p, bn_len); if (sk_len == 0) diff --git a/crypto/zkp/gadget/zkp_range_proof.c b/crypto/zkp/gadget/zkp_range_proof.c index 5a3235086..b27491bf2 100644 --- a/crypto/zkp/gadget/zkp_range_proof.c +++ b/crypto/zkp/gadget/zkp_range_proof.c @@ -410,6 +410,7 @@ void ZKP_RANGE_PROOF_free(ZKP_RANGE_PROOF *proof) NIZK_PLAINTEXT_KNOWLEDGE_PROOF_free(proof->ptke_proof); BP_RANGE_PROOF_free(proof->bp_proof); + OPENSSL_free(proof); } ZKP_RANGE_PROOF *ZKP_RANGE_PROOF_prove(ZKP_RANGE_CTX *ctx, int left_bound_bits, diff --git a/crypto/zkp/nizk/nizk_encode.c b/crypto/zkp/nizk/nizk_encode.c index 4305d44ca..d6ec1ba17 100644 --- a/crypto/zkp/nizk/nizk_encode.c +++ b/crypto/zkp/nizk/nizk_encode.c @@ -296,7 +296,7 @@ NIZK_WITNESS *NIZK_WITNESS_decode(const unsigned char *in, size_t size, int flag if (flag == 1) { if (size < (sizeof(int) + bn_len * 3)) { ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT); - return NULL; + goto err; } witness->v = zkp_bignum_decode(p, NULL, bn_len); diff --git a/test/bntest.c b/test/bntest.c index c5894c157..2ad00d65a 100644 --- a/test/bntest.c +++ b/test/bntest.c @@ -101,6 +101,7 @@ static BIGNUM *getBN(STANZA *s, const char *attribute) if (parseBN(&ret, hex) != (int)strlen(hex)) { TEST_error("Could not decode '%s'", hex); + BN_free(ret); return NULL; } return ret; diff --git a/test/bulletproofs_test.c b/test/bulletproofs_test.c index e54791188..84de4c480 100644 --- a/test/bulletproofs_test.c +++ b/test/bulletproofs_test.c @@ -1134,9 +1134,11 @@ static BP_R1CS_PROOF *r1cs_range_prove(BP_R1CS_CTX *ctx, BP_WITNESS *witness, if (!(proof = BP_R1CS_PROOF_prove(ctx))) goto err; + BN_free(v); return proof; err: + BN_free(v); BP_R1CS_LINEAR_COMBINATION_free(lc); BP_R1CS_PROOF_free(proof); return NULL; diff --git a/test/nizk_test.c b/test/nizk_test.c index 64d0da58d..2bf4ce31c 100644 --- a/test/nizk_test.c +++ b/test/nizk_test.c @@ -93,6 +93,8 @@ static int nizk_plaintext_knowledge_test(int plaintext) ret = 1; err: + EC_ELGAMAL_CIPHERTEXT_free(enc_ct); + EC_ELGAMAL_CTX_free(enc_ctx); NIZK_PLAINTEXT_KNOWLEDGE_PROOF_free(proof); NIZK_PLAINTEXT_KNOWLEDGE_CTX_free(ctx); NIZK_WITNESS_free(witness); @@ -176,6 +178,8 @@ static int nizk_plaintext_equality_test(int plaintext) ret = 1; err: + EC_ELGAMAL_MR_CTX_free(enc_ctx); + EC_ELGAMAL_MR_CIPHERTEXT_free(enc_ct); NIZK_PLAINTEXT_EQUALITY_PROOF_free(proof); NIZK_PLAINTEXT_EQUALITY_CTX_free(ctx); NIZK_WITNESS_free(witness); diff --git a/test/paillier_internal_test.c b/test/paillier_internal_test.c index e099f53ce..33f2389b6 100644 --- a/test/paillier_internal_test.c +++ b/test/paillier_internal_test.c @@ -189,6 +189,7 @@ static size_t paillier_add_plain(PAILLIER_CTX *ctx, unsigned char **out, ret = size; err: + OPENSSL_free(buf); PAILLIER_CIPHERTEXT_free(c); PAILLIER_CIPHERTEXT_free(r); return ret; @@ -270,6 +271,7 @@ static size_t paillier_mul(PAILLIER_CTX *ctx, unsigned char **out, ret = size; err: + OPENSSL_free(buf); PAILLIER_CIPHERTEXT_free(c); PAILLIER_CIPHERTEXT_free(r); return ret; diff --git a/test/pkcs12_format_test.c b/test/pkcs12_format_test.c index 258a78d80..77e3f2c17 100644 --- a/test/pkcs12_format_test.c +++ b/test/pkcs12_format_test.c @@ -776,6 +776,7 @@ static int test_set0_attrs(void) return end_pkcs12_builder(pb); err: + (void)end_pkcs12_builder(pb); return 0; } diff --git a/test/zkp_gadget_test.c b/test/zkp_gadget_test.c index 8d85ce941..c7b127d76 100644 --- a/test/zkp_gadget_test.c +++ b/test/zkp_gadget_test.c @@ -37,9 +37,6 @@ static int zkp_poly3_eval_test(void) BN_CTX *bn_ctx = NULL; STACK_OF(BIGNUM) *sk_eval = NULL; - if (!(sk_eval = sk_BIGNUM_new_reserve(NULL, n))) - goto err; - bn_ctx = BN_CTX_new(); if (bn_ctx == NULL) goto err; From 5121e42d525eb21778eda0c40c21f280f280b807 Mon Sep 17 00:00:00 2001 From: K1 Date: Mon, 24 Jun 2024 10:39:19 +0800 Subject: [PATCH 36/66] Check DSA parameters for excessive sizes before validating This avoids overly long computation of various validation checks. Fixes CVE-2024-4603 --- CHANGES | 2 + crypto/dsa/dsa_check.c | 50 ++++++++++++++-- .../invalid/p10240_q256_too_big.pem | 57 +++++++++++++++++++ 3 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 test/recipes/15-test_dsaparam_data/invalid/p10240_q256_too_big.pem diff --git a/CHANGES b/CHANGES index 647362367..b6d6c43c1 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,8 @@ Changes between 8.4.0 and 8.5.0 [xx XXX xxxx] + *) 修复CVE-2024-4603 + *) 修复CVE-2024-2511 *) 修复CVE-2023-6129 diff --git a/crypto/dsa/dsa_check.c b/crypto/dsa/dsa_check.c index 7ee914a47..6fccf6e1e 100644 --- a/crypto/dsa/dsa_check.c +++ b/crypto/dsa/dsa_check.c @@ -19,8 +19,34 @@ #include "dsa_local.h" #include "crypto/dsa.h" +static int dsa_precheck_params(const DSA *dsa, int *ret) +{ + if (dsa->params.p == NULL || dsa->params.q == NULL) { + ERR_raise(ERR_LIB_DSA, DSA_R_BAD_FFC_PARAMETERS); + *ret = FFC_CHECK_INVALID_PQ; + return 0; + } + + if (BN_num_bits(dsa->params.p) > OPENSSL_DSA_MAX_MODULUS_BITS) { + ERR_raise(ERR_LIB_DSA, DSA_R_MODULUS_TOO_LARGE); + *ret = FFC_CHECK_INVALID_PQ; + return 0; + } + + if (BN_num_bits(dsa->params.q) >= BN_num_bits(dsa->params.p)) { + ERR_raise(ERR_LIB_DSA, DSA_R_BAD_Q_VALUE); + *ret = FFC_CHECK_INVALID_PQ; + return 0; + } + + return 1; +} + int ossl_dsa_check_params(const DSA *dsa, int checktype, int *ret) { + if (!dsa_precheck_params(dsa, ret)) + return 0; + if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK) return ossl_ffc_params_simple_validate(dsa->libctx, &dsa->params, FFC_PARAM_TYPE_DSA, ret); @@ -39,7 +65,11 @@ int ossl_dsa_check_params(const DSA *dsa, int checktype, int *ret) */ int ossl_dsa_check_pub_key(const DSA *dsa, const BIGNUM *pub_key, int *ret) { - return ossl_ffc_validate_public_key(&dsa->params, pub_key, ret); + if (!dsa_precheck_params(dsa, ret)) + return 0; + + return ossl_ffc_validate_public_key(&dsa->params, pub_key, ret) + && *ret == 0; } /* @@ -49,15 +79,21 @@ int ossl_dsa_check_pub_key(const DSA *dsa, const BIGNUM *pub_key, int *ret) */ int ossl_dsa_check_pub_key_partial(const DSA *dsa, const BIGNUM *pub_key, int *ret) { - return ossl_ffc_validate_public_key_partial(&dsa->params, pub_key, ret); + if (!dsa_precheck_params(dsa, ret)) + return 0; + + return ossl_ffc_validate_public_key_partial(&dsa->params, pub_key, ret) + && *ret == 0; } int ossl_dsa_check_priv_key(const DSA *dsa, const BIGNUM *priv_key, int *ret) { *ret = 0; - return (dsa->params.q != NULL - && ossl_ffc_validate_private_key(dsa->params.q, priv_key, ret)); + if (!dsa_precheck_params(dsa, ret)) + return 0; + + return ossl_ffc_validate_private_key(dsa->params.q, priv_key, ret); } /* @@ -70,8 +106,10 @@ int ossl_dsa_check_pairwise(const DSA *dsa) BN_CTX *ctx = NULL; BIGNUM *pub_key = NULL; - if (dsa->params.p == NULL - || dsa->params.g == NULL + if (!dsa_precheck_params(dsa, &ret)) + return 0; + + if (dsa->params.g == NULL || dsa->priv_key == NULL || dsa->pub_key == NULL) return 0; diff --git a/test/recipes/15-test_dsaparam_data/invalid/p10240_q256_too_big.pem b/test/recipes/15-test_dsaparam_data/invalid/p10240_q256_too_big.pem new file mode 100644 index 000000000..e85e2953b --- /dev/null +++ b/test/recipes/15-test_dsaparam_data/invalid/p10240_q256_too_big.pem @@ -0,0 +1,57 @@ +-----BEGIN DSA PARAMETERS----- +MIIKLAKCBQEAym47LzPFZdbz16WvjczLKuzLtsP8yRk/exxL4bBthJhP1qOwctja +p1586SF7gDxCMn7yWVEYdfRbFefGoq0gj1XOE917XqlbnkmZhMgxut2KbNJo/xil +XNFUjGvKs3F413U9rAodC8f07cWHP1iTcWL+vPe6u2yilKWYYfnLWHQH+Z6aPrrF +x/R08LI6DZ6nEsIo+hxaQnEtx+iqNTJC6Q1RIjWDqxQkFVTkJ0Y7miRDXmRdneWk +oLrMZRpaXr5l5tSjEghh1pBgJcdyOv0lh4dlDy/alAiqE2Qlb667yHl6A9dDPlpW +dAntpffy4LwOxfbuEhISvKjjQoBwIvYE4TBPqL0Q6bC6HgQ4+tqd9b44pQjdIQjb +Xcjc6azheITSnPEex3OdKtKoQeRq01qCeLBpMXu1c+CTf4ApKArZvT3vZSg0hM1O +pR71bRZrEEegDj0LH2HCgI5W6H3blOS9A0kUTddCoQXr2lsVdiPtRbPKH1gcd9FQ +P8cGrvbakpTiC0dCczOMDaCteM1QNILlkM7ZoV6VghsKvDnFPxFsiIr5GgjasXP5 +hhbn3g7sDoq1LiTEo+IKQY28pBWx7etSOSRuXW/spnvCkivZla7lSEGljoy9QlQ2 +UZmsEQI9G3YyzgpxHvKZBK1CiZVTywdYKTZ4TYCxvqzhYhjv2bqbpjI12HRFLojB +koyEmMSp53lldCzp158PrIanqSp2rksMR8SmmCL3FwfAp2OjqFMEglG9DT8x0WaN +TLSkjGC6t2csMte7WyU1ekNoFDKfMjDSAz0+xIx21DEmZtYqFOg1DNPK1xYLS0pl +RSMRRkJVN2mk/G7/1oxlB8Wb9wgi3GKUqqCYT11SnBjzq0NdoJ3E4GMedp5Lx3AZ +4mFuRPUd4iV86tE0XDSHSFE7Y3ZkrOjD7Q/26/L53L/UH5z4HW6CHP5os7QERJjg +c1S3x87wXWo9QXbB9b2xmf+c+aWwAAr1cviw38tru58jF3/IGyduj9H8claKQqBG +cIOUF4aNe1hK2K3ArAOApUxr4KE+tCvrltRfiTmVFip0g9Jt1CPY3Zu7Bd4Z2ZkE +DtSztpwa49HrWF5E9xpquvBL2U8jQ68E7Xd8Wp4orI/TIChriamBmdkgRz3H2LvN +Ozb6+hsnEGrz3sp2RVAToSqA9ysa6nHZdfufPNtMEbQdO/k1ehmGRb0ljBRsO6b2 +rsG2eYuC8tg8eCrIkua0TGRI7g6a4K32AJdzaX6NsISaaIW+OYJuoDSscvD3oOg8 +PPEhU+zM7xJskTA+jxvPlikKx8V7MNHOCQECldJlUBwzJvqp40JvwfnDsF+8VYwd +UaiieR3pzMzyTjpReXRmZbnRPusRcsVzxb2OhB79wmuy4UPjjQBX+7eD0rs8xxvW +5a5q1Cjq4AvbwmmcA/wDrHDOjcbD/zodad2O1QtBWa/R4xyWea4zKsflgACE1zY9 +wW2br7+YQFekcrXkkkEzgxd6zxv8KVEDpXRZjmAM1cI5LvkoN64To4GedN8Qe/G7 +R9SZh9gnS17PTP64hK+aYqhFafMdu87q/+qLfxaSux727qE5hiW01u4nnWhACf9s +xuOozowKqxZxkolMIyZv6Lddwy1Zv5qjCyd0DvM/1skpXWkb9kfabYC+OhjsjVhs +0Ktfs6a5B3eixiw5x94hhIcTEcS4hmvhGUL72FiTca6ZeSERTKmNBy8CIQC9/ZUN +uU/V5JTcnYyUGHzm7+XcZBjyGBagBj9rCmW3SQKCBQAJ/k9rb39f1cO+/3XDEMjy +9bIEXSuS48g5RAc1UGd5nrrBQwuDxGWFyz0yvAY7LgyidZuJS21+MAp9EY7AOMmx +TDttifNaBJYt4GZ8of166PcqTKkHQwq5uBpxeSDv/ZE8YbYfaCtLTcUC8KlO+l36 +gjJHSkdkflSsGy1yObSNDQDfVAAwQs//TjDMnuEtvlNXZllsTvFFBceXVETn10K2 +ZMmdSIJNfLnjReUKEN6PfeGqv7F4xoyGwUybEfRE4u5RmXrqCODaIjY3SNMrOq8B +R3Ata/cCozsM1jIdIW2z+OybDJH+BYsYm2nkSZQjZS6javTYClLrntEKG/hAQwL8 +F16YLOQXpHhgiAaWnTZzANtLppB2+5qCVy5ElzKongOwT8JTjTFXOaRnqe/ngm9W +SSbrxfDaoWUOyK9XD8Cydzpv3n4Y8nWNGayi7/yAFCU36Ri040ufgv/TZLuKacnl ++3ga3ZUpRlSigzx0kb1+KjTSWeQ8vE/psdWjvBukVEbzdUauMLyRLo/6znSVvvPX +UGhviThE5uhrsUg+wEPFINriSHfF7JDKVhDcJnLBdaXvfN52pkF/naLBF5Rt3Gvq +fjCxjx0Sy9Lag1hDN4dor7dzuO7wmwOS01DJW1PtNLuuH0Bbqh1kYSaQkmyXBZWX +qo8K3nkoDM0niOtJJubOhTNrGmSaZpNXkK3Mcy9rBbdvEs5O0Jmqaax/eOdU0Yot +B3lX+3ddOseT2ZEFjzObqTtkWuFBeBxuYNcRTsu3qMdIBsEb8URQdsTtjoIja2fK +hreVgjK36GW70KXEl8V/vq5qjQulmqkBEjmilcDuiREKqQuyeagUOnhQaBplqVco +4xznh5DMBMRbpGb5lHxKv4cPNi+uNAJ5i98zWUM1JRt6aXnRCuWcll1z8fRZ+5kD +vK9FaZU3VRMK/eknEG49cGr8OuJ6ZRSaC+tKwV1y+amkSZpKPWnk2bUnQI3ApJv3 +k1e1EToeECpMUkLMDgNbpKBoz4nqMEvAAlYgw9xKNbLlQlahqTVEAmaJHh4yDMDy +i7IZ9Wrn47IGoR7s3cvhDHUpRPeW4nsmgzj+tf5EAxemI61STZJTTWo0iaPGJxct +9nhOOhw1I38Mvm4vkAbFH7YJ0B6QrjjYL2MbOTp5JiIh4vdOeWwNo9/y4ffyaN5+ +ADpxuuIAmcbdr6GPOhkOFFixRJa0B2eP1i032HESlLs8RB9oYtdTXdXQotnIgJGd +Y8tSKOa1zjzeLHn3AVpRZTUW++/BxmApV3GKIeG8fsUjg/df0QRrBcdC/1uccdaG +KKlAOwlywVn5jUlwHkTmDiTM9w5AqVVGHZ2b+4ZgQW8jnPKN0SrKf6U555D+zp7E +x4uXoE8ojN9y8m8UKf0cTLnujH2XgZorjPfuMOt5VZEhQFMS2QaljSeni5CJJ8gk +XtztNqfBlAtWR4V5iAHeQOfIB2YaOy8GESda89tyKraKeaez41VblpTVHTeq9IIF +YB4cQA2PfuNaGVRGLMAgT3Dvl+mxxxeJyxnGAiUcETU/jJJt9QombiuszBlYGQ5d +ELOSm/eQSRARV9zNSt5jaQlMSjMBqenIEM09BzYqa7jDwqoztFxNdO8bcuQPuKwa +4z3bBZ1yYm63WFdNbQqqGEwc0OYmqg1raJ0zltgHyjFyw8IGu4g/wETs+nVQcH7D +vKuje86bePD6kD/LH3wmkA== +-----END DSA PARAMETERS----- From f229155eb86b0324b837433298ed629923e0fbc2 Mon Sep 17 00:00:00 2001 From: K1 Date: Mon, 24 Jun 2024 21:44:06 +0800 Subject: [PATCH 37/66] enable CMS sign/verify for provider-implemented PKEYs We need to handle signatures with and without digest algs and we generalize the ossl_cms_ecdsa_dsa_sign() function to other algorithms that are handled in the same way. Reviewed-by: Matt Caswell Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/17733) --- crypto/cms/cms_ec.c | 23 ----------------------- crypto/cms/cms_local.h | 1 - crypto/cms/cms_sd.c | 37 ++++++++++++++++++++++++++++++++++--- crypto/objects/obj_xref.c | 10 +++++++++- 4 files changed, 43 insertions(+), 28 deletions(-) diff --git a/crypto/cms/cms_ec.c b/crypto/cms/cms_ec.c index b07af92ba..82f265e12 100644 --- a/crypto/cms/cms_ec.c +++ b/crypto/cms/cms_ec.c @@ -388,26 +388,3 @@ int ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt) ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); return 0; } - -/* ECDSA and DSA implementation is the same */ -int ossl_cms_ecdsa_dsa_sign(CMS_SignerInfo *si, int verify) -{ - assert(verify == 0 || verify == 1); - - if (verify == 0) { - int snid, hnid; - X509_ALGOR *alg1, *alg2; - EVP_PKEY *pkey = si->pkey; - - CMS_SignerInfo_get0_algs(si, NULL, NULL, &alg1, &alg2); - if (alg1 == NULL || alg1->algorithm == NULL) - return -1; - hnid = OBJ_obj2nid(alg1->algorithm); - if (hnid == NID_undef) - return -1; - if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_get_id(pkey))) - return -1; - X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); - } - return 1; -} diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h index 15b4a29ce..e9fb43715 100644 --- a/crypto/cms/cms_local.h +++ b/crypto/cms/cms_local.h @@ -479,7 +479,6 @@ int ossl_cms_check_signing_certs(const CMS_SignerInfo *si, int ossl_cms_dh_envelope(CMS_RecipientInfo *ri, int decrypt); int ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt); int ossl_cms_rsa_envelope(CMS_RecipientInfo *ri, int decrypt); -int ossl_cms_ecdsa_dsa_sign(CMS_SignerInfo *si, int verify); int ossl_cms_rsa_sign(CMS_SignerInfo *si, int verify); DECLARE_ASN1_ITEM(CMS_CertificateChoices) diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c index f8fe3bee8..0ed8f1027 100644 --- a/crypto/cms/cms_sd.c +++ b/crypto/cms/cms_sd.c @@ -227,19 +227,50 @@ int ossl_cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert) return -1; } +/* Method to map any, incl. provider-implemented PKEY types to OIDs */ +/* ECDSA and DSA and all provider-delivered signatures implementation is the same */ +static int cms_generic_sign(CMS_SignerInfo *si, int verify) +{ + if (!ossl_assert(verify == 0 || verify == 1)) + return -1; + + if (!verify) { + int snid, hnid, pknid; + X509_ALGOR *alg1, *alg2; + EVP_PKEY *pkey = si->pkey; + pknid = EVP_PKEY_get_id(pkey); + + CMS_SignerInfo_get0_algs(si, NULL, NULL, &alg1, &alg2); + if (alg1 == NULL || alg1->algorithm == NULL) + return -1; + hnid = OBJ_obj2nid(alg1->algorithm); + if (hnid == NID_undef) + return -1; + if (pknid <= 0) { /* check whether a provider registered a NID */ + const char *typename = EVP_PKEY_get0_type_name(pkey); + if (typename != NULL) + pknid = OBJ_txt2nid(typename); + } + if (!OBJ_find_sigid_by_algs(&snid, hnid, pknid)) + return -1; + return X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, NULL); + } + return 1; +} + static int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd) { EVP_PKEY *pkey = si->pkey; int i; if (EVP_PKEY_is_a(pkey, "DSA") || EVP_PKEY_is_a(pkey, "EC")) - return ossl_cms_ecdsa_dsa_sign(si, cmd); + return cms_generic_sign(si, cmd); else if (EVP_PKEY_is_a(pkey, "RSA") || EVP_PKEY_is_a(pkey, "RSA-PSS")) return ossl_cms_rsa_sign(si, cmd); - /* Something else? We'll give engines etc a chance to handle this */ + /* Now give engines, providers, etc a chance to handle this */ if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL) - return 1; + return cms_generic_sign(si, cmd); i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si); if (i == -2) { ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); diff --git a/crypto/objects/obj_xref.c b/crypto/objects/obj_xref.c index da1035112..10d55e00f 100644 --- a/crypto/objects/obj_xref.c +++ b/crypto/objects/obj_xref.c @@ -32,8 +32,16 @@ DECLARE_OBJ_BSEARCH_CMP_FN(const nid_triple *, const nid_triple *, sigx); static int sigx_cmp(const nid_triple *const *a, const nid_triple *const *b) { int ret; + ret = (*a)->hash_id - (*b)->hash_id; - if (ret) + /* The "b" side of the comparison carries the algorithms already + * registered. A NID_undef for 'hash_id' there means that the + * signature algorithm doesn't need a digest to operate OK. In + * such case, any hash_id/digest algorithm on the test side (a), + * incl. NID_undef, is acceptable. signature algorithm NID + * (pkey_id) must match in any case. + */ + if ((ret != 0) && ((*b)->hash_id != NID_undef)) return ret; return (*a)->pkey_id - (*b)->pkey_id; } From 0e9beb88d977e33f863c6e91864392f93656c62d Mon Sep 17 00:00:00 2001 From: K1 Date: Mon, 24 Jun 2024 21:44:55 +0800 Subject: [PATCH 38/66] Check error return from cms_sd_asn1_ctrl() correctly. (Merged from https://github.com/openssl/openssl/pull/21988) --- crypto/cms/cms_sd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c index 0ed8f1027..ae7a821b1 100644 --- a/crypto/cms/cms_sd.c +++ b/crypto/cms/cms_sd.c @@ -264,13 +264,13 @@ static int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd) int i; if (EVP_PKEY_is_a(pkey, "DSA") || EVP_PKEY_is_a(pkey, "EC")) - return cms_generic_sign(si, cmd); + return cms_generic_sign(si, cmd) > 0; else if (EVP_PKEY_is_a(pkey, "RSA") || EVP_PKEY_is_a(pkey, "RSA-PSS")) - return ossl_cms_rsa_sign(si, cmd); + return ossl_cms_rsa_sign(si, cmd) > 0; /* Now give engines, providers, etc a chance to handle this */ if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL) - return cms_generic_sign(si, cmd); + return cms_generic_sign(si, cmd) > 0; i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si); if (i == -2) { ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); From 98bb7e8378e17bc36d8903150f09da2daaa70bc7 Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 25 Jun 2024 12:33:01 +0800 Subject: [PATCH 39/66] Fix coverity issues, 497452, 497428, 497414, 497443, 497438 497452, 497428, 497414, Double free. 497443, An integer overflow. 497438, An integer overflow. --- crypto/asn1/x_delegated_credential.c | 4 ++-- ssl/record/ssl3_record_tls13.c | 4 ++-- test/cmp_ctx_test.c | 3 +++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/crypto/asn1/x_delegated_credential.c b/crypto/asn1/x_delegated_credential.c index 1dd0cfd20..310f49f88 100644 --- a/crypto/asn1/x_delegated_credential.c +++ b/crypto/asn1/x_delegated_credential.c @@ -202,7 +202,7 @@ DELEGATED_CREDENTIAL *DC_load_from_file_ex(const char *file, BIO *bio_dc = NULL; char *dc_hex_buf = NULL; unsigned char *dc_buf = NULL; - size_t dc_hex_len, len; + int dc_hex_len, len; size_t dc_buf_len; dc_hex_buf = OPENSSL_malloc(DC_MAX_LEN); @@ -233,7 +233,7 @@ DELEGATED_CREDENTIAL *DC_load_from_file_ex(const char *file, */ len = dc_hex_len / 2; - dc_buf = OPENSSL_malloc(len); + dc_buf = OPENSSL_malloc((size_t)len); if (dc_buf == NULL) { ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; diff --git a/ssl/record/ssl3_record_tls13.c b/ssl/record/ssl3_record_tls13.c index 6aa2fb980..67f1d048e 100644 --- a/ssl/record/ssl3_record_tls13.c +++ b/ssl/record/ssl3_record_tls13.c @@ -25,10 +25,10 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending, { EVP_CIPHER_CTX *ctx; unsigned char iv[EVP_MAX_IV_LENGTH], recheader[SSL3_RT_HEADER_LENGTH]; - size_t ivlen, taglen, offset, loop, hdrlen; + size_t taglen, offset, loop, hdrlen; unsigned char *staticiv; unsigned char *seq; - int lenu, lenf; + int lenu, lenf, ivlen; SSL3_RECORD *rec = &recs[0]; uint32_t alg_enc; WPACKET wpkt; diff --git a/test/cmp_ctx_test.c b/test/cmp_ctx_test.c index d379628f6..3660b3e61 100644 --- a/test/cmp_ctx_test.c +++ b/test/cmp_ctx_test.c @@ -394,6 +394,7 @@ execute_CTX_##SETN##_##GETN##_##FIELD(OSSL_CMP_CTX_TEST_FIXTURE *fixture) \ } else { \ if (DUP && val1_read == val1) { \ TEST_error("first set did not dup the value"); \ + val1_read = 0; \ res = 0; \ } \ if (DEFAULT(val1_read)) { \ @@ -422,6 +423,7 @@ execute_CTX_##SETN##_##GETN##_##FIELD(OSSL_CMP_CTX_TEST_FIXTURE *fixture) \ } else { \ if (DUP && val2_read == val2) { \ TEST_error("second set did not dup the value"); \ + val2_read = 0; \ res = 0; \ } \ if (val2 == val1) { \ @@ -451,6 +453,7 @@ execute_CTX_##SETN##_##GETN##_##FIELD(OSSL_CMP_CTX_TEST_FIXTURE *fixture) \ } else { \ if (DUP && val3_read == val2_read) { \ TEST_error("third get did not create a new dup"); \ + val3_read = 0; \ res = 0; \ } \ } \ From 03d02fd87b4ee44adeacb6ea2b12f51a2c7a2b71 Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 25 Jun 2024 15:39:58 +0800 Subject: [PATCH 40/66] Only free the read buffers if we're not using them If we're part way through processing a record, or the application has not released all the records then we should not free our buffer because they are still needed. CVE-2024-4741 --- ssl/record/rec_layer_s3.c | 9 +++++++++ ssl/record/record.h | 1 + ssl/ssl_lib.c | 3 +++ 3 files changed, 13 insertions(+) diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index fe1b3f3c1..af4aeb1bd 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -80,6 +80,15 @@ int RECORD_LAYER_read_pending(const RECORD_LAYER *rl) return SSL3_BUFFER_get_left(&rl->rbuf) != 0; } +int RECORD_LAYER_data_present(const RECORD_LAYER *rl) +{ + if (rl->rstate == SSL_ST_READ_BODY) + return 1; + if (RECORD_LAYER_processed_read_pending(rl)) + return 1; + return 0; +} + /* Checks if we have decrypted unread record data pending */ int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl) { diff --git a/ssl/record/record.h b/ssl/record/record.h index 234656bf9..b60f71c8c 100644 --- a/ssl/record/record.h +++ b/ssl/record/record.h @@ -205,6 +205,7 @@ void RECORD_LAYER_release(RECORD_LAYER *rl); int RECORD_LAYER_read_pending(const RECORD_LAYER *rl); int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl); int RECORD_LAYER_write_pending(const RECORD_LAYER *rl); +int RECORD_LAYER_data_present(const RECORD_LAYER *rl); void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl); void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl); int RECORD_LAYER_is_sslv2_record(RECORD_LAYER *rl); diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 03f2f051f..6b0b21d0b 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -6075,6 +6075,9 @@ int SSL_free_buffers(SSL *ssl) if (RECORD_LAYER_read_pending(rl) || RECORD_LAYER_write_pending(rl)) return 0; + if (RECORD_LAYER_data_present(rl)) + return 0; + RECORD_LAYER_release(rl); return 1; } From 4b16389c20ce5d279367f6a365692e9ecd39b3e1 Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 25 Jun 2024 15:42:06 +0800 Subject: [PATCH 41/66] Set rlayer.packet to NULL after we've finished using it In order to ensure we do not have a UAF we reset the rlayer.packet pointer to NULL after we free it. CVE-2024-4741 --- ssl/record/rec_layer_s3.c | 7 +++++++ ssl/record/ssl3_buffer.c | 2 ++ 2 files changed, 9 insertions(+) diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index af4aeb1bd..3d57380a9 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -16,6 +16,7 @@ #include #include "record_local.h" #include "internal/packet.h" +#include "internal/cryptlib.h" #if defined(OPENSSL_SMALL_FOOTPRINT) || \ !( defined(AES_ASM) && ( \ @@ -235,6 +236,12 @@ int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold, /* ... now we can act as if 'extend' was set */ } + if (!ossl_assert(s->rlayer.packet != NULL)) { + /* does not happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return -1; + } + len = s->rlayer.packet_length; pkt = rb->buf + align; /* diff --git a/ssl/record/ssl3_buffer.c b/ssl/record/ssl3_buffer.c index 01c553ebf..bdfb5b740 100644 --- a/ssl/record/ssl3_buffer.c +++ b/ssl/record/ssl3_buffer.c @@ -181,5 +181,7 @@ int ssl3_release_read_buffer(SSL *s) OPENSSL_cleanse(b->buf, b->len); OPENSSL_free(b->buf); b->buf = NULL; + s->rlayer.packet = NULL; + s->rlayer.packet_length = 0; return 1; } From f689c6a810ef3b3eaa13c20ebb41142be31c1a4b Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 25 Jun 2024 15:43:59 +0800 Subject: [PATCH 42/66] Extend the SSL_free_buffers testing Test that attempting to free the buffers at points where they should not be freed works as expected. Follow on from CVE-2024-4741 --- test/sslbuffertest.c | 93 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/test/sslbuffertest.c b/test/sslbuffertest.c index 3c3e69d61..133fdb13e 100644 --- a/test/sslbuffertest.c +++ b/test/sslbuffertest.c @@ -150,6 +150,98 @@ static int test_func(int test) return result; } +/* + * Test that attempting to free the buffers at points where they cannot be freed + * works as expected + * Test 0: Attempt to free buffers after a full record has been processed, but + * the application has only performed a partial read + * Test 1: Attempt to free buffers after only a partial record header has been + * received + * Test 2: Attempt to free buffers after a full record header but no record body + * Test 3: Attempt to free buffers after a full record hedaer and partial record + * body + */ +static int test_free_buffers(int test) +{ + int result = 0; + SSL *serverssl = NULL, *clientssl = NULL; + const char testdata[] = "Test data"; + char buf[40]; + size_t written, readbytes; + + if (!TEST_true(create_ssl_objects(serverctx, clientctx, &serverssl, + &clientssl, NULL, NULL))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + + if (!TEST_true(SSL_write_ex(clientssl, testdata, sizeof(testdata), + &written))) + goto end; + + if (test == 0) { + /* + * Deliberately only read the first byte - so the remaining bytes are + * still buffered + */ + if (!TEST_true(SSL_read_ex(serverssl, buf, 1, &readbytes))) + goto end; + } else { + BIO *tmp; + size_t partial_len; + + /* Remove all the data that is pending for read by the server */ + tmp = SSL_get_rbio(serverssl); + if (!TEST_true(BIO_read_ex(tmp, buf, sizeof(buf), &readbytes)) + || !TEST_size_t_lt(readbytes, sizeof(buf)) + || !TEST_size_t_gt(readbytes, SSL3_RT_HEADER_LENGTH)) + goto end; + + switch(test) { + case 1: + partial_len = SSL3_RT_HEADER_LENGTH - 1; + break; + case 2: + partial_len = SSL3_RT_HEADER_LENGTH; + break; + case 3: + partial_len = readbytes - 1; + break; + default: + TEST_error("Invalid test index"); + goto end; + } + + /* Put back just the partial record */ + if (!TEST_true(BIO_write_ex(tmp, buf, partial_len, &written))) + goto end; + + /* + * Attempt a read. This should fail because only a partial record is + * available. + */ + if (!TEST_false(SSL_read_ex(serverssl, buf, 1, &readbytes))) + goto end; + } + + /* + * Attempting to free the buffers at this point should fail because they are + * still in use + */ + if (!TEST_false(SSL_free_buffers(serverssl))) + goto end; + + result = 1; + end: + SSL_free(clientssl); + SSL_free(serverssl); + + return result; +} + OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n") int setup_tests(void) @@ -173,6 +265,7 @@ int setup_tests(void) } ADD_ALL_TESTS(test_func, 9); + ADD_ALL_TESTS(test_free_buffers, 4); return 1; } From 8411797178233ed790a5a1b5aabfd1d6cf2df029 Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 25 Jun 2024 15:49:11 +0800 Subject: [PATCH 43/66] Move the ability to load the dasync engine into ssltestlib.c The sslapitest has a helper function to load the dasync engine which is useful for testing pipelining. We would like to have the same facility from sslbuffertest, so we move the function to the common location ssltestlib.c Follow on from CVE-2024-4741 --- test/helpers/ssltestlib.c | 33 +++++++++++++++++++++++++++++++++ test/helpers/ssltestlib.h | 1 + 2 files changed, 34 insertions(+) diff --git a/test/helpers/ssltestlib.c b/test/helpers/ssltestlib.c index 70438867f..2f5f1a364 100644 --- a/test/helpers/ssltestlib.c +++ b/test/helpers/ssltestlib.c @@ -7,8 +7,17 @@ * https://www.openssl.org/source/license.html */ +/* + * We need access to the deprecated low level ENGINE APIs for legacy purposes + * when the deprecated calls are not hidden + */ +#ifndef OPENSSL_NO_DEPRECATED_3_0 +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + #include +#include #include "internal/nelem.h" #include "ssltestlib.h" #include "../testutil.h" @@ -1060,3 +1069,27 @@ void shutdown_ssl_connection(SSL *serverssl, SSL *clientssl) SSL_free(serverssl); SSL_free(clientssl); } + +ENGINE *load_dasync(void) +{ +#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE) + ENGINE *e; + + if (!TEST_ptr(e = ENGINE_by_id("dasync"))) + return NULL; + + if (!TEST_true(ENGINE_init(e))) { + ENGINE_free(e); + return NULL; + } + + if (!TEST_true(ENGINE_register_ciphers(e))) { + ENGINE_free(e); + return NULL; + } + + return e; +#else + return NULL; +#endif +} diff --git a/test/helpers/ssltestlib.h b/test/helpers/ssltestlib.h index 046628636..b9ad697f5 100644 --- a/test/helpers/ssltestlib.h +++ b/test/helpers/ssltestlib.h @@ -56,4 +56,5 @@ typedef struct mempacket_st MEMPACKET; DEFINE_STACK_OF(MEMPACKET) +ENGINE *load_dasync(void); #endif /* OSSL_TEST_SSLTESTLIB_H */ From 19795466365ad491ee3ab56ac4275d766a2df40d Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 25 Jun 2024 15:51:42 +0800 Subject: [PATCH 44/66] Further extend the SSL_free_buffers testing We extend the testing to test what happens when pipelining is in use. Follow on from CVE-2024-4741 --- test/sslbuffertest.c | 113 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 97 insertions(+), 16 deletions(-) diff --git a/test/sslbuffertest.c b/test/sslbuffertest.c index 133fdb13e..7079d04e1 100644 --- a/test/sslbuffertest.c +++ b/test/sslbuffertest.c @@ -8,10 +8,19 @@ * or in the file LICENSE in the source distribution. */ +/* + * We need access to the deprecated low level Engine APIs for legacy purposes + * when the deprecated calls are not hidden + */ +#ifndef OPENSSL_NO_DEPRECATED_3_0 +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + #include #include #include #include +#include #include "internal/packet.h" @@ -160,34 +169,65 @@ static int test_func(int test) * Test 2: Attempt to free buffers after a full record header but no record body * Test 3: Attempt to free buffers after a full record hedaer and partial record * body + * Test 4-7: We repeat tests 0-3 but including data from a second pipelined + * record */ static int test_free_buffers(int test) { int result = 0; SSL *serverssl = NULL, *clientssl = NULL; const char testdata[] = "Test data"; - char buf[40]; + char buf[120]; size_t written, readbytes; + int i, pipeline = test > 3; + ENGINE *e = NULL; + + if (pipeline) { + e = load_dasync(); + if (e == NULL) + goto end; + test -= 4; + } if (!TEST_true(create_ssl_objects(serverctx, clientctx, &serverssl, &clientssl, NULL, NULL))) goto end; + if (pipeline) { + if (!TEST_true(SSL_set_cipher_list(serverssl, "AES128-SHA")) + || !TEST_true(SSL_set_max_proto_version(serverssl, + TLS1_2_VERSION)) + || !TEST_true(SSL_set_max_pipelines(serverssl, 2))) + goto end; + } + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) goto end; - - if (!TEST_true(SSL_write_ex(clientssl, testdata, sizeof(testdata), - &written))) - goto end; + /* + * For the non-pipeline case we write one record. For pipelining we write + * two records. + */ + for (i = 0; i <= pipeline; i++) { + if (!TEST_true(SSL_write_ex(clientssl, testdata, strlen(testdata), + &written))) + goto end; + } if (test == 0) { + size_t readlen = 1; + /* - * Deliberately only read the first byte - so the remaining bytes are - * still buffered - */ - if (!TEST_true(SSL_read_ex(serverssl, buf, 1, &readbytes))) + * Deliberately only read the first byte - so the remaining bytes are + * still buffered. In the pipelining case we read as far as the first + * byte from the second record. + */ + if (pipeline) + readlen += strlen(testdata); + + if (!TEST_true(SSL_read_ex(serverssl, buf, readlen, &readbytes)) + || !TEST_size_t_eq(readlen, readbytes)) goto end; } else { BIO *tmp; @@ -215,16 +255,47 @@ static int test_free_buffers(int test) goto end; } - /* Put back just the partial record */ - if (!TEST_true(BIO_write_ex(tmp, buf, partial_len, &written))) - goto end; + if (pipeline) { + /* We happen to know the first record is 57 bytes long */ + const size_t first_rec_len = 57; + + if (test != 3) + partial_len += first_rec_len; + + /* + * Sanity check. If we got the record len right then this should + * never fail. + */ + if (!TEST_int_eq(buf[first_rec_len], SSL3_RT_APPLICATION_DATA)) + goto end; + } /* - * Attempt a read. This should fail because only a partial record is - * available. + * Put back just the partial record (plus the whole initial record in + * the pipelining case) */ - if (!TEST_false(SSL_read_ex(serverssl, buf, 1, &readbytes))) + if (!TEST_true(BIO_write_ex(tmp, buf, partial_len, &written))) goto end; + + if (pipeline) { + /* + * Attempt a read. This should pass but only return data from the + * first record. Only a partial record is available for the second + * record. + */ + if (!TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf), + &readbytes)) + || !TEST_size_t_eq(readbytes, strlen(testdata))) + goto end; + } else { + /* + * Attempt a read. This should fail because only a partial record is + * available. + */ + if (!TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf), + &readbytes))) + goto end; + } } /* @@ -238,7 +309,13 @@ static int test_free_buffers(int test) end: SSL_free(clientssl); SSL_free(serverssl); - +#ifndef OPENSSL_NO_DYNAMIC_ENGINE + if (e != NULL) { + ENGINE_unregister_ciphers(e); + ENGINE_finish(e); + ENGINE_free(e); + } +#endif return result; } @@ -265,7 +342,11 @@ int setup_tests(void) } ADD_ALL_TESTS(test_func, 9); +#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE) + ADD_ALL_TESTS(test_free_buffers, 8); +#else ADD_ALL_TESTS(test_free_buffers, 4); +#endif return 1; } From 894a738d557da09f49e9b63ae93129929c0ebd74 Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 25 Jun 2024 15:53:54 +0800 Subject: [PATCH 45/66] Add a CHANGES entry for CVE-2024-4741 --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index b6d6c43c1..645fafb82 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,8 @@ Changes between 8.4.0 and 8.5.0 [xx XXX xxxx] + *) 修复CVE-2024-4741 + *) 修复CVE-2024-4603 *) 修复CVE-2024-2511 From ff9f60df3399c7928c680f27d191109c41fa5052 Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 25 Jun 2024 17:55:42 +0800 Subject: [PATCH 46/66] Add a test for TLS pipelining TLS pipelining provides the ability for libssl to read or write multiple records in parallel. It requires special ciphers to do this, and there are currently no built-in ciphers that provide this capability. However, the dasync engine does have such a cipher, so we add a test for this capability using that engine. --- test/sslapitest.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) diff --git a/test/sslapitest.c b/test/sslapitest.c index f891e646d..aa65d2cd4 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "helpers/ssltestlib.h" #include "testutil.h" @@ -9914,6 +9915,205 @@ static int test_load_dhfile(void) #endif } +#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE) +/* + * Test TLSv1.2 with a pipeline capable cipher. TLSv1.3 and DTLS do not + * support this yet. The only pipeline capable cipher that we have is in the + * dasync engine (providers don't support this yet), so we have to use + * deprecated APIs for this test. + * + * Test 0: Client has pipelining enabled, server does not + * Test 1: Server has pipelining enabled, client does not + * Test 2: Client has pipelining enabled, server does not: not enough data to + * fill all the pipelines + * Test 3: Client has pipelining enabled, server does not: not enough data to + * fill all the pipelines by more than a full pipeline's worth + * Test 4: Client has pipelining enabled, server does not: more data than all + * the available pipelines can take + * Test 5: Client has pipelining enabled, server does not: Maximum size pipeline + * Test 6: Repeat of test 0, but the engine is loaded late (after the SSL_CTX + * is created) + */ +static int test_pipelining(int idx) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL, *peera, *peerb; + int testresult = 0, numreads; + /* A 55 byte message */ + unsigned char *msg = (unsigned char *) + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123"; + size_t written, readbytes, offset, msglen, fragsize = 10, numpipes = 5; + size_t expectedreads; + unsigned char *buf = NULL; + ENGINE *e = NULL; + + if (idx != 6) { + e = load_dasync(); + if (e == NULL) + return 0; + } + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), 0, + TLS1_2_VERSION, &sctx, &cctx, cert, + privkey))) + goto end; + + if (idx == 6) { + e = load_dasync(); + if (e == NULL) + goto end; + /* Now act like test 0 */ + idx = 0; + } + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, + &clientssl, NULL, NULL))) + goto end; + + if (!TEST_true(SSL_set_cipher_list(clientssl, "AES128-SHA"))) + goto end; + + /* peera is always configured for pipelining, while peerb is not. */ + if (idx == 1) { + peera = serverssl; + peerb = clientssl; + + } else { + peera = clientssl; + peerb = serverssl; + } + + if (idx == 5) { + numpipes = 2; + /* Maximum allowed fragment size */ + fragsize = SSL3_RT_MAX_PLAIN_LENGTH; + msglen = fragsize * numpipes; + msg = OPENSSL_malloc(msglen); + if (!TEST_ptr(msg)) + goto end; + if (!TEST_int_gt(RAND_bytes_ex(libctx, msg, msglen, 0), 0)) + goto end; + } else if (idx == 4) { + msglen = 55; + } else { + msglen = 50; + } + if (idx == 2) + msglen -= 2; /* Send 2 less bytes */ + else if (idx == 3) + msglen -= 12; /* Send 12 less bytes */ + + buf = OPENSSL_malloc(msglen); + if (!TEST_ptr(buf)) + goto end; + + if (idx == 5) { + /* + * Test that setting a split send fragment longer than the maximum + * allowed fails + */ + if (!TEST_false(SSL_set_split_send_fragment(peera, fragsize + 1))) + goto end; + } + + /* + * In the normal case. We have 5 pipelines with 10 bytes per pipeline + * (50 bytes in total). This is a ridiculously small number of bytes - + * but sufficient for our purposes + */ + if (!TEST_true(SSL_set_max_pipelines(peera, numpipes)) + || !TEST_true(SSL_set_split_send_fragment(peera, fragsize))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + /* Write some data from peera to peerb */ + if (!TEST_true(SSL_write_ex(peera, msg, msglen, &written)) + || !TEST_size_t_eq(written, msglen)) + goto end; + + /* + * If the pipelining code worked, then we expect all |numpipes| pipelines to + * have been used - except in test 3 where only |numpipes - 1| pipelines + * will be used. This will result in |numpipes| records (|numpipes - 1| for + * test 3) having been sent to peerb. Since peerb is not using read_ahead we + * expect this to be read in |numpipes| or |numpipes - 1| separate + * SSL_read_ex calls. In the case of test 4, there is then one additional + * read for left over data that couldn't fit in the previous pipelines + */ + for (offset = 0, numreads = 0; + offset < msglen; + offset += readbytes, numreads++) { + if (!TEST_true(SSL_read_ex(peerb, buf + offset, + msglen - offset, &readbytes))) + goto end; + } + + expectedreads = idx == 4 ? numpipes + 1 + : (idx == 3 ? numpipes - 1 : numpipes); + if (!TEST_mem_eq(msg, msglen, buf, offset) + || !TEST_int_eq(numreads, expectedreads)) + goto end; + + /* + * Write some data from peerb to peera. We do this in up to |numpipes + 1| + * chunks to exercise the read pipelining code on peera. + */ + for (offset = 0; offset < msglen; offset += fragsize) { + size_t sendlen = msglen - offset; + + if (sendlen > fragsize) + sendlen = fragsize; + if (!TEST_true(SSL_write_ex(peerb, msg + offset, sendlen, &written)) + || !TEST_size_t_eq(written, sendlen)) + goto end; + } + + /* + * The data was written in |numpipes|, |numpipes - 1| or |numpipes + 1| + * separate chunks (depending on which test we are running). If the + * pipelining is working then we expect peera to read up to numpipes chunks + * and process them in parallel, giving back the complete result in a single + * call to SSL_read_ex + */ + if (!TEST_true(SSL_read_ex(peera, buf, msglen, &readbytes)) + || !TEST_size_t_le(readbytes, msglen)) + goto end; + + if (idx == 4) { + size_t readbytes2; + + if (!TEST_true(SSL_read_ex(peera, buf + readbytes, + msglen - readbytes, &readbytes2))) + goto end; + readbytes += readbytes2; + if (!TEST_size_t_le(readbytes, msglen)) + goto end; + } + + if (!TEST_mem_eq(msg, msglen, buf, readbytes)) + goto end; + + testresult = 1; +end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + if (e != NULL) { + ENGINE_unregister_ciphers(e); + ENGINE_finish(e); + ENGINE_free(e); + } + OPENSSL_free(buf); + if (fragsize == SSL3_RT_MAX_PLAIN_LENGTH) + OPENSSL_free(msg); + return testresult; +} +#endif /* !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE) */ + #ifndef OPENSSL_NO_CERT_COMPRESSION #define CERT_COMPRESSION_XOR 16384 #define CERT_COMPRESSION_ROL 65535 @@ -10604,6 +10804,9 @@ int setup_tests(void) ADD_ALL_TESTS(test_session_cache_overflow, 4); #endif ADD_TEST(test_load_dhfile); +#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE) + ADD_ALL_TESTS(test_pipelining, 7); +#endif ADD_ALL_TESTS(test_multi_resume, 5); return 1; From 8dffa02e52ba2935df5d281745651e0806b7f12d Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 25 Jun 2024 17:56:56 +0800 Subject: [PATCH 47/66] Pipeline output/input buf arrays must live until the EVP_Cipher is called The pipeline input/output buf arrays must remain accessible to the EVP_CIPHER_CTX until EVP_Cipher is subsequently called. This fixes an asan error discovered by the newly added pipeline test. --- ssl/record/ssl3_record.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c index 08d50bc6a..8b8527fcd 100644 --- a/ssl/record/ssl3_record.c +++ b/ssl/record/ssl3_record.c @@ -982,6 +982,7 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending, EVP_CIPHER_CTX *ds; size_t reclen[SSL_MAX_PIPELINES]; unsigned char buf[SSL_MAX_PIPELINES][EVP_AEAD_TLS1_AAD_LEN]; + unsigned char *data[SSL_MAX_PIPELINES]; int i, pad = 0, tmpr; size_t bs, ctr, padnum, loop; unsigned char padval; @@ -1139,8 +1140,6 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending, } } if (n_recs > 1) { - unsigned char *data[SSL_MAX_PIPELINES]; - /* Set the output buffers */ for (ctr = 0; ctr < n_recs; ctr++) { data[ctr] = recs[ctr].data; From e85d8922f257dd74dcbb4a79aa513c730c15007c Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 25 Jun 2024 17:58:06 +0800 Subject: [PATCH 48/66] Fix read pipelining During read pipelining we must ensure that the buffer is sufficiently large to read enough data to fill our pipelines. We also remove some code that moved data to the start of the packet if we can. This was unnecessary because of later code which would end up moving it anyway. The earlier move was also incorrect in the case that |clearold| was 0. This would cause the read pipelining code to fail with sufficiently large records. --- ssl/record/rec_layer_s3.c | 20 +------------------- ssl/record/ssl3_buffer.c | 5 +++++ 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index 3d57380a9..ab4bf5876 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -212,25 +212,7 @@ int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold, /* start with empty packet ... */ if (left == 0) rb->offset = align; - else if (align != 0 && left >= SSL3_RT_HEADER_LENGTH) { - /* - * check if next packet length is large enough to justify payload - * alignment... - */ - pkt = rb->buf + rb->offset; - if (pkt[0] == SSL3_RT_APPLICATION_DATA - && (pkt[3] << 8 | pkt[4]) >= 128) { - /* - * Note that even if packet is corrupted and its length field - * is insane, we can only be led to wrong decision about - * whether memmove will occur or not. Header values has no - * effect on memmove arguments and therefore no buffer - * overrun can be triggered. - */ - memmove(rb->buf + align, pkt, left); - rb->offset = align; - } - } + s->rlayer.packet = rb->buf + rb->offset; s->rlayer.packet_length = 0; /* ... now we can act as if 'extend' was set */ diff --git a/ssl/record/ssl3_buffer.c b/ssl/record/ssl3_buffer.c index bdfb5b740..e08666c5b 100644 --- a/ssl/record/ssl3_buffer.c +++ b/ssl/record/ssl3_buffer.c @@ -58,6 +58,11 @@ int ssl3_setup_read_buffer(SSL *s) if (ssl_allow_compression(s)) len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; #endif + + /* Ensure our buffer is large enough to support all our pipelines */ + if (s->max_pipelines > 1) + len *= s->max_pipelines; + if (b->default_len > len) len = b->default_len; if ((p = OPENSSL_malloc(len)) == NULL) { From 450c859c7fa743bcf6c36049ad3fbc528f10ec91 Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 25 Jun 2024 17:59:18 +0800 Subject: [PATCH 49/66] Do not have more data in a pipeline than the split_send_fragment We shouldn't be putting more data into a pipeline than the value of split_send_fragment. This is a backport of a fix which was included in a much larger commit in master (c6186792b98) related to moving the pipelining code into the new record layer that exists there. --- ssl/record/rec_layer_s3.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index ab4bf5876..3eb4fb6ab 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -611,14 +611,13 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len, if (numpipes > maxpipes) numpipes = maxpipes; - if (n / numpipes >= max_send_fragment) { + if (n / numpipes >= split_send_fragment) { /* * We have enough data to completely fill all available * pipelines */ - for (j = 0; j < numpipes; j++) { - pipelens[j] = max_send_fragment; - } + for (j = 0; j < numpipes; j++) + pipelens[j] = split_send_fragment; } else { /* We can partially fill all available pipelines */ tmppipelen = n / numpipes; From 7964dca26ba696e52907fa1405b6a5dbab91b7ec Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 25 Jun 2024 20:03:42 +0800 Subject: [PATCH 50/66] Don't attempt to set provider params on an ENGINE based cipher If an ENGINE has been loaded after the SSL_CTX has been created then the cipher we have cached might be provider based, but the cipher we actually end up using might not be. Don't try to set provider params on a cipher that is actually ENGINE based. --- ssl/s3_enc.c | 6 +++++- ssl/t1_enc.c | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index 2ca3f74ae..ee4f58e75 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c @@ -225,7 +225,11 @@ int ssl3_change_cipher_state(SSL *s, int which) goto err; } - if (EVP_CIPHER_get0_provider(c) != NULL + /* + * The cipher we actually ended up using in the EVP_CIPHER_CTX may be + * different to that in c if we have an ENGINE in use + */ + if (EVP_CIPHER_get0_provider(EVP_CIPHER_CTX_get0_cipher(dd)) != NULL && !tls_provider_set_tls_params(s, dd, c, m)) { /* SSLfatal already called */ goto err; diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 2b449e1bc..67b45905d 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -397,7 +397,12 @@ int tls1_change_cipher_state(SSL *s, int which) SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); goto err; } - if (EVP_CIPHER_get0_provider(c) != NULL + + /* + * The cipher we actually ended up using in the EVP_CIPHER_CTX may be + * different to that in c if we have an ENGINE in use + */ + if (EVP_CIPHER_get0_provider(EVP_CIPHER_CTX_get0_cipher(dd)) != NULL && !tls_provider_set_tls_params(s, dd, c, m)) { /* SSLfatal already called */ goto err; From 036d0f66fa31f0b26b55b06d179e173864a58284 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 12 Jul 2024 15:08:43 +0800 Subject: [PATCH 51/66] Fix SSL_select_next_proto Ensure that the provided client list is non-NULL and starts with a valid entry. When called from the ALPN callback the client list should already have been validated by OpenSSL so this should not cause a problem. When called from the NPN callback the client list is locally configured and will not have already been validated. Therefore SSL_select_next_proto should not assume that it is correctly formatted. We implement stricter checking of the client protocol list. We also do the same for the server list while we are about it. CVE-2024-5535 (cherry picked from commit cf6f91f6121f4db167405db2f0de410a456f260c) --- ssl/ssl_lib.c | 63 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 6b0b21d0b..75d297275 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -3010,37 +3010,54 @@ int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, unsigned int server_len, const unsigned char *client, unsigned int client_len) { - unsigned int i, j; - const unsigned char *result; - int status = OPENSSL_NPN_UNSUPPORTED; + PACKET cpkt, csubpkt, spkt, ssubpkt; + + if (!PACKET_buf_init(&cpkt, client, client_len) + || !PACKET_get_length_prefixed_1(&cpkt, &csubpkt) + || PACKET_remaining(&csubpkt) == 0) { + *out = NULL; + *outlen = 0; + return OPENSSL_NPN_NO_OVERLAP; + } + + /* + * Set the default opportunistic protocol. Will be overwritten if we find + * a match. + */ + *out = (unsigned char *)PACKET_data(&csubpkt); + *outlen = (unsigned char)PACKET_remaining(&csubpkt); /* * For each protocol in server preference order, see if we support it. */ - for (i = 0; i < server_len;) { - for (j = 0; j < client_len;) { - if (server[i] == client[j] && - memcmp(&server[i + 1], &client[j + 1], server[i]) == 0) { - /* We found a match */ - result = &server[i]; - status = OPENSSL_NPN_NEGOTIATED; - goto found; + if (PACKET_buf_init(&spkt, server, server_len)) { + while (PACKET_get_length_prefixed_1(&spkt, &ssubpkt)) { + if (PACKET_remaining(&ssubpkt) == 0) + continue; /* Invalid - ignore it */ + if (PACKET_buf_init(&cpkt, client, client_len)) { + while (PACKET_get_length_prefixed_1(&cpkt, &csubpkt)) { + if (PACKET_equal(&csubpkt, PACKET_data(&ssubpkt), + PACKET_remaining(&ssubpkt))) { + /* We found a match */ + *out = (unsigned char *)PACKET_data(&ssubpkt); + *outlen = (unsigned char)PACKET_remaining(&ssubpkt); + return OPENSSL_NPN_NEGOTIATED; + } + } + /* Ignore spurious trailing bytes in the client list */ + } else { + /* This should never happen */ + return OPENSSL_NPN_NO_OVERLAP; } - j += client[j]; - j++; } - i += server[i]; - i++; + /* Ignore spurious trailing bytes in the server list */ } - /* There's no overlap between our protocols and the server's list. */ - result = client; - status = OPENSSL_NPN_NO_OVERLAP; - - found: - *out = (unsigned char *)result + 1; - *outlen = result[0]; - return status; + /* + * There's no overlap between our protocols and the server's list. We use + * the default opportunistic protocol selected earlier + */ + return OPENSSL_NPN_NO_OVERLAP; } #ifndef OPENSSL_NO_NEXTPROTONEG From 1137d9bc36f88ee1d7f621e697fefec8fb609a72 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 12 Jul 2024 15:11:08 +0800 Subject: [PATCH 52/66] More correctly handle a selected_len of 0 when processing NPN In the case where the NPN callback returns with SSL_TLEXT_ERR_OK, but the selected_len is 0 we should fail. Previously this would fail with an internal_error alert because calling OPENSSL_malloc(selected_len) will return NULL when selected_len is 0. We make this error detection more explicit and return a handshake failure alert. Follow on from CVE-2024-5535 (cherry picked from commit 159921152fd4aa91e4c849fd281ad93ac0d0d0ba) --- ssl/statem/extensions_clnt.c | 3 ++- ssl/statem_ntls/ntls_extensions_clnt.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index 3f914dba5..0e6359987 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -1650,7 +1650,8 @@ int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, PACKET_data(pkt), PACKET_remaining(pkt), s->ctx->ext.npn_select_cb_arg) != - SSL_TLSEXT_ERR_OK) { + SSL_TLSEXT_ERR_OK + || selected_len == 0) { SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_BAD_EXTENSION); return 0; } diff --git a/ssl/statem_ntls/ntls_extensions_clnt.c b/ssl/statem_ntls/ntls_extensions_clnt.c index 75c0812f1..52fcebe08 100644 --- a/ssl/statem_ntls/ntls_extensions_clnt.c +++ b/ssl/statem_ntls/ntls_extensions_clnt.c @@ -644,7 +644,8 @@ int tls_parse_stoc_npn_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, PACKET_data(pkt), PACKET_remaining(pkt), s->ctx->ext.npn_select_cb_arg) != - SSL_TLSEXT_ERR_OK) { + SSL_TLSEXT_ERR_OK + || selected_len == 0) { SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_BAD_EXTENSION); return 0; } From 7f4500f0f4c43779333a04410f361cf95341c402 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 12 Jul 2024 15:14:15 +0800 Subject: [PATCH 53/66] Add a test for SSL_select_next_proto Follow on from CVE-2024-5535 (cherry picked from commit 707c71aa03ba968e09325d72cf1e8dcac70df2df) --- test/sslapitest.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/test/sslapitest.c b/test/sslapitest.c index aa65d2cd4..352e51cc2 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -10533,6 +10533,142 @@ static int test_multi_resume(int idx) return testresult; } +static struct next_proto_st { + int serverlen; + unsigned char server[40]; + int clientlen; + unsigned char client[40]; + int expected_ret; + size_t selectedlen; + unsigned char selected[40]; +} next_proto_tests[] = { + { + 4, { 3, 'a', 'b', 'c' }, + 4, { 3, 'a', 'b', 'c' }, + OPENSSL_NPN_NEGOTIATED, + 3, { 'a', 'b', 'c' } + }, + { + 7, { 3, 'a', 'b', 'c', 2, 'a', 'b' }, + 4, { 3, 'a', 'b', 'c' }, + OPENSSL_NPN_NEGOTIATED, + 3, { 'a', 'b', 'c' } + }, + { + 7, { 2, 'a', 'b', 3, 'a', 'b', 'c', }, + 4, { 3, 'a', 'b', 'c' }, + OPENSSL_NPN_NEGOTIATED, + 3, { 'a', 'b', 'c' } + }, + { + 4, { 3, 'a', 'b', 'c' }, + 7, { 3, 'a', 'b', 'c', 2, 'a', 'b', }, + OPENSSL_NPN_NEGOTIATED, + 3, { 'a', 'b', 'c' } + }, + { + 4, { 3, 'a', 'b', 'c' }, + 7, { 2, 'a', 'b', 3, 'a', 'b', 'c'}, + OPENSSL_NPN_NEGOTIATED, + 3, { 'a', 'b', 'c' } + }, + { + 7, { 2, 'b', 'c', 3, 'a', 'b', 'c' }, + 7, { 2, 'a', 'b', 3, 'a', 'b', 'c'}, + OPENSSL_NPN_NEGOTIATED, + 3, { 'a', 'b', 'c' } + }, + { + 10, { 2, 'b', 'c', 3, 'a', 'b', 'c', 2, 'a', 'b' }, + 7, { 2, 'a', 'b', 3, 'a', 'b', 'c'}, + OPENSSL_NPN_NEGOTIATED, + 3, { 'a', 'b', 'c' } + }, + { + 4, { 3, 'b', 'c', 'd' }, + 4, { 3, 'a', 'b', 'c' }, + OPENSSL_NPN_NO_OVERLAP, + 3, { 'a', 'b', 'c' } + }, + { + 0, { 0 }, + 4, { 3, 'a', 'b', 'c' }, + OPENSSL_NPN_NO_OVERLAP, + 3, { 'a', 'b', 'c' } + }, + { + -1, { 0 }, + 4, { 3, 'a', 'b', 'c' }, + OPENSSL_NPN_NO_OVERLAP, + 3, { 'a', 'b', 'c' } + }, + { + 4, { 3, 'a', 'b', 'c' }, + 0, { 0 }, + OPENSSL_NPN_NO_OVERLAP, + 0, { 0 } + }, + { + 4, { 3, 'a', 'b', 'c' }, + -1, { 0 }, + OPENSSL_NPN_NO_OVERLAP, + 0, { 0 } + }, + { + 3, { 3, 'a', 'b', 'c' }, + 4, { 3, 'a', 'b', 'c' }, + OPENSSL_NPN_NO_OVERLAP, + 3, { 'a', 'b', 'c' } + }, + { + 4, { 3, 'a', 'b', 'c' }, + 3, { 3, 'a', 'b', 'c' }, + OPENSSL_NPN_NO_OVERLAP, + 0, { 0 } + } +}; + +static int test_select_next_proto(int idx) +{ + struct next_proto_st *np = &next_proto_tests[idx]; + int ret = 0; + unsigned char *out, *client, *server; + unsigned char outlen; + unsigned int clientlen, serverlen; + + if (np->clientlen == -1) { + client = NULL; + clientlen = 0; + } else { + client = np->client; + clientlen = (unsigned int)np->clientlen; + } + if (np->serverlen == -1) { + server = NULL; + serverlen = 0; + } else { + server = np->server; + serverlen = (unsigned int)np->serverlen; + } + + if (!TEST_int_eq(SSL_select_next_proto(&out, &outlen, server, serverlen, + client, clientlen), + np->expected_ret)) + goto err; + + if (np->selectedlen == 0) { + if (!TEST_ptr_null(out) || !TEST_uchar_eq(outlen, 0)) + goto err; + } else { + if (!TEST_mem_eq(out, outlen, np->selected, np->selectedlen)) + goto err; + } + + ret = 1; + err: + return ret; +} + OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile provider config dhfile\n") int setup_tests(void) @@ -10808,6 +10944,7 @@ int setup_tests(void) ADD_ALL_TESTS(test_pipelining, 7); #endif ADD_ALL_TESTS(test_multi_resume, 5); + ADD_ALL_TESTS(test_select_next_proto, OSSL_NELEM(next_proto_tests)); return 1; err: From e50a6b630930dfb5c75d841d25dbcc0d2a163429 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 12 Jul 2024 15:16:43 +0800 Subject: [PATCH 54/66] Allow an empty NPN/ALPN protocol list in the tests Allow ourselves to configure an empty NPN/ALPN protocol list and test what happens if we do. Follow on from CVE-2024-5535 (cherry picked from commit 72394c9a1a6a6b07edf43eb2ad7e95e1093ada1b) --- test/helpers/handshake.c | 6 + test/ssl-tests/08-npn.cnf | 553 +++++++++++++++++++--------------- test/ssl-tests/08-npn.cnf.in | 35 +++ test/ssl-tests/09-alpn.cnf | 66 +++- test/ssl-tests/09-alpn.cnf.in | 33 ++ 5 files changed, 449 insertions(+), 244 deletions(-) diff --git a/test/helpers/handshake.c b/test/helpers/handshake.c index 3697a5fc7..190b69c8b 100644 --- a/test/helpers/handshake.c +++ b/test/helpers/handshake.c @@ -349,6 +349,12 @@ static int parse_protos(const char *protos, unsigned char **out, size_t *outlen) len = strlen(protos); + if (len == 0) { + *out = NULL; + *outlen = 0; + return 1; + } + /* Should never have reuse. */ if (!TEST_ptr_null(*out) /* Test values are small, so we omit length limit checks. */ diff --git a/test/ssl-tests/08-npn.cnf b/test/ssl-tests/08-npn.cnf index f38b3f697..1931d02de 100644 --- a/test/ssl-tests/08-npn.cnf +++ b/test/ssl-tests/08-npn.cnf @@ -1,6 +1,6 @@ # Generated with generate_ssl_tests.pl -num_tests = 20 +num_tests = 22 test-0 = 0-npn-simple test-1 = 1-npn-client-finds-match @@ -8,20 +8,22 @@ test-2 = 2-npn-client-honours-server-pref test-3 = 3-npn-client-first-pref-on-mismatch test-4 = 4-npn-no-server-support test-5 = 5-npn-no-client-support -test-6 = 6-npn-with-sni-no-context-switch -test-7 = 7-npn-with-sni-context-switch -test-8 = 8-npn-selected-sni-server-supports-npn -test-9 = 9-npn-selected-sni-server-does-not-support-npn -test-10 = 10-alpn-preferred-over-npn -test-11 = 11-sni-npn-preferred-over-alpn -test-12 = 12-npn-simple-resumption -test-13 = 13-npn-server-switch-resumption -test-14 = 14-npn-client-switch-resumption -test-15 = 15-npn-client-first-pref-on-mismatch-resumption -test-16 = 16-npn-no-server-support-resumption -test-17 = 17-npn-no-client-support-resumption -test-18 = 18-alpn-preferred-over-npn-resumption -test-19 = 19-npn-used-if-alpn-not-supported-resumption +test-6 = 6-npn-empty-client-list +test-7 = 7-npn-empty-server-list +test-8 = 8-npn-with-sni-no-context-switch +test-9 = 9-npn-with-sni-context-switch +test-10 = 10-npn-selected-sni-server-supports-npn +test-11 = 11-npn-selected-sni-server-does-not-support-npn +test-12 = 12-alpn-preferred-over-npn +test-13 = 13-sni-npn-preferred-over-alpn +test-14 = 14-npn-simple-resumption +test-15 = 15-npn-server-switch-resumption +test-16 = 16-npn-client-switch-resumption +test-17 = 17-npn-client-first-pref-on-mismatch-resumption +test-18 = 18-npn-no-server-support-resumption +test-19 = 19-npn-no-client-support-resumption +test-20 = 20-alpn-preferred-over-npn-resumption +test-21 = 21-npn-used-if-alpn-not-supported-resumption # =========================================================== [0-npn-simple] @@ -206,253 +208,318 @@ NPNProtocols = foo # =========================================================== -[6-npn-with-sni-no-context-switch] -ssl_conf = 6-npn-with-sni-no-context-switch-ssl +[6-npn-empty-client-list] +ssl_conf = 6-npn-empty-client-list-ssl -[6-npn-with-sni-no-context-switch-ssl] -server = 6-npn-with-sni-no-context-switch-server -client = 6-npn-with-sni-no-context-switch-client -server2 = 6-npn-with-sni-no-context-switch-server2 +[6-npn-empty-client-list-ssl] +server = 6-npn-empty-client-list-server +client = 6-npn-empty-client-list-client -[6-npn-with-sni-no-context-switch-server] +[6-npn-empty-client-list-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[6-npn-with-sni-no-context-switch-server2] +[6-npn-empty-client-list-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.2 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-6] +ExpectedClientAlert = HandshakeFailure +ExpectedResult = ClientFail +server = 6-npn-empty-client-list-server-extra +client = 6-npn-empty-client-list-client-extra + +[6-npn-empty-client-list-server-extra] +NPNProtocols = foo + +[6-npn-empty-client-list-client-extra] +NPNProtocols = + + +# =========================================================== + +[7-npn-empty-server-list] +ssl_conf = 7-npn-empty-server-list-ssl + +[7-npn-empty-server-list-ssl] +server = 7-npn-empty-server-list-server +client = 7-npn-empty-server-list-client + +[7-npn-empty-server-list-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[6-npn-with-sni-no-context-switch-client] +[7-npn-empty-server-list-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-6] +[test-7] +ExpectedNPNProtocol = foo +server = 7-npn-empty-server-list-server-extra +client = 7-npn-empty-server-list-client-extra + +[7-npn-empty-server-list-server-extra] +NPNProtocols = + +[7-npn-empty-server-list-client-extra] +NPNProtocols = foo + + +# =========================================================== + +[8-npn-with-sni-no-context-switch] +ssl_conf = 8-npn-with-sni-no-context-switch-ssl + +[8-npn-with-sni-no-context-switch-ssl] +server = 8-npn-with-sni-no-context-switch-server +client = 8-npn-with-sni-no-context-switch-client +server2 = 8-npn-with-sni-no-context-switch-server2 + +[8-npn-with-sni-no-context-switch-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[8-npn-with-sni-no-context-switch-server2] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[8-npn-with-sni-no-context-switch-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.2 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-8] ExpectedNPNProtocol = foo ExpectedServerName = server1 -server = 6-npn-with-sni-no-context-switch-server-extra -server2 = 6-npn-with-sni-no-context-switch-server2-extra -client = 6-npn-with-sni-no-context-switch-client-extra +server = 8-npn-with-sni-no-context-switch-server-extra +server2 = 8-npn-with-sni-no-context-switch-server2-extra +client = 8-npn-with-sni-no-context-switch-client-extra -[6-npn-with-sni-no-context-switch-server-extra] +[8-npn-with-sni-no-context-switch-server-extra] NPNProtocols = foo ServerNameCallback = IgnoreMismatch -[6-npn-with-sni-no-context-switch-server2-extra] +[8-npn-with-sni-no-context-switch-server2-extra] NPNProtocols = bar -[6-npn-with-sni-no-context-switch-client-extra] +[8-npn-with-sni-no-context-switch-client-extra] NPNProtocols = foo,bar ServerName = server1 # =========================================================== -[7-npn-with-sni-context-switch] -ssl_conf = 7-npn-with-sni-context-switch-ssl +[9-npn-with-sni-context-switch] +ssl_conf = 9-npn-with-sni-context-switch-ssl -[7-npn-with-sni-context-switch-ssl] -server = 7-npn-with-sni-context-switch-server -client = 7-npn-with-sni-context-switch-client -server2 = 7-npn-with-sni-context-switch-server2 +[9-npn-with-sni-context-switch-ssl] +server = 9-npn-with-sni-context-switch-server +client = 9-npn-with-sni-context-switch-client +server2 = 9-npn-with-sni-context-switch-server2 -[7-npn-with-sni-context-switch-server] +[9-npn-with-sni-context-switch-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[7-npn-with-sni-context-switch-server2] +[9-npn-with-sni-context-switch-server2] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[7-npn-with-sni-context-switch-client] +[9-npn-with-sni-context-switch-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-7] +[test-9] ExpectedNPNProtocol = bar ExpectedServerName = server2 -server = 7-npn-with-sni-context-switch-server-extra -server2 = 7-npn-with-sni-context-switch-server2-extra -client = 7-npn-with-sni-context-switch-client-extra +server = 9-npn-with-sni-context-switch-server-extra +server2 = 9-npn-with-sni-context-switch-server2-extra +client = 9-npn-with-sni-context-switch-client-extra -[7-npn-with-sni-context-switch-server-extra] +[9-npn-with-sni-context-switch-server-extra] NPNProtocols = foo ServerNameCallback = IgnoreMismatch -[7-npn-with-sni-context-switch-server2-extra] +[9-npn-with-sni-context-switch-server2-extra] NPNProtocols = bar -[7-npn-with-sni-context-switch-client-extra] +[9-npn-with-sni-context-switch-client-extra] NPNProtocols = foo,bar ServerName = server2 # =========================================================== -[8-npn-selected-sni-server-supports-npn] -ssl_conf = 8-npn-selected-sni-server-supports-npn-ssl +[10-npn-selected-sni-server-supports-npn] +ssl_conf = 10-npn-selected-sni-server-supports-npn-ssl -[8-npn-selected-sni-server-supports-npn-ssl] -server = 8-npn-selected-sni-server-supports-npn-server -client = 8-npn-selected-sni-server-supports-npn-client -server2 = 8-npn-selected-sni-server-supports-npn-server2 +[10-npn-selected-sni-server-supports-npn-ssl] +server = 10-npn-selected-sni-server-supports-npn-server +client = 10-npn-selected-sni-server-supports-npn-client +server2 = 10-npn-selected-sni-server-supports-npn-server2 -[8-npn-selected-sni-server-supports-npn-server] +[10-npn-selected-sni-server-supports-npn-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[8-npn-selected-sni-server-supports-npn-server2] +[10-npn-selected-sni-server-supports-npn-server2] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[8-npn-selected-sni-server-supports-npn-client] +[10-npn-selected-sni-server-supports-npn-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-8] +[test-10] ExpectedNPNProtocol = bar ExpectedServerName = server2 -server = 8-npn-selected-sni-server-supports-npn-server-extra -server2 = 8-npn-selected-sni-server-supports-npn-server2-extra -client = 8-npn-selected-sni-server-supports-npn-client-extra +server = 10-npn-selected-sni-server-supports-npn-server-extra +server2 = 10-npn-selected-sni-server-supports-npn-server2-extra +client = 10-npn-selected-sni-server-supports-npn-client-extra -[8-npn-selected-sni-server-supports-npn-server-extra] +[10-npn-selected-sni-server-supports-npn-server-extra] ServerNameCallback = IgnoreMismatch -[8-npn-selected-sni-server-supports-npn-server2-extra] +[10-npn-selected-sni-server-supports-npn-server2-extra] NPNProtocols = bar -[8-npn-selected-sni-server-supports-npn-client-extra] +[10-npn-selected-sni-server-supports-npn-client-extra] NPNProtocols = foo,bar ServerName = server2 # =========================================================== -[9-npn-selected-sni-server-does-not-support-npn] -ssl_conf = 9-npn-selected-sni-server-does-not-support-npn-ssl +[11-npn-selected-sni-server-does-not-support-npn] +ssl_conf = 11-npn-selected-sni-server-does-not-support-npn-ssl -[9-npn-selected-sni-server-does-not-support-npn-ssl] -server = 9-npn-selected-sni-server-does-not-support-npn-server -client = 9-npn-selected-sni-server-does-not-support-npn-client -server2 = 9-npn-selected-sni-server-does-not-support-npn-server2 +[11-npn-selected-sni-server-does-not-support-npn-ssl] +server = 11-npn-selected-sni-server-does-not-support-npn-server +client = 11-npn-selected-sni-server-does-not-support-npn-client +server2 = 11-npn-selected-sni-server-does-not-support-npn-server2 -[9-npn-selected-sni-server-does-not-support-npn-server] +[11-npn-selected-sni-server-does-not-support-npn-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[9-npn-selected-sni-server-does-not-support-npn-server2] +[11-npn-selected-sni-server-does-not-support-npn-server2] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[9-npn-selected-sni-server-does-not-support-npn-client] +[11-npn-selected-sni-server-does-not-support-npn-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-9] +[test-11] ExpectedServerName = server2 -server = 9-npn-selected-sni-server-does-not-support-npn-server-extra -client = 9-npn-selected-sni-server-does-not-support-npn-client-extra +server = 11-npn-selected-sni-server-does-not-support-npn-server-extra +client = 11-npn-selected-sni-server-does-not-support-npn-client-extra -[9-npn-selected-sni-server-does-not-support-npn-server-extra] +[11-npn-selected-sni-server-does-not-support-npn-server-extra] NPNProtocols = bar ServerNameCallback = IgnoreMismatch -[9-npn-selected-sni-server-does-not-support-npn-client-extra] +[11-npn-selected-sni-server-does-not-support-npn-client-extra] NPNProtocols = foo,bar ServerName = server2 # =========================================================== -[10-alpn-preferred-over-npn] -ssl_conf = 10-alpn-preferred-over-npn-ssl +[12-alpn-preferred-over-npn] +ssl_conf = 12-alpn-preferred-over-npn-ssl -[10-alpn-preferred-over-npn-ssl] -server = 10-alpn-preferred-over-npn-server -client = 10-alpn-preferred-over-npn-client +[12-alpn-preferred-over-npn-ssl] +server = 12-alpn-preferred-over-npn-server +client = 12-alpn-preferred-over-npn-client -[10-alpn-preferred-over-npn-server] +[12-alpn-preferred-over-npn-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[10-alpn-preferred-over-npn-client] +[12-alpn-preferred-over-npn-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-10] +[test-12] ExpectedALPNProtocol = foo -server = 10-alpn-preferred-over-npn-server-extra -client = 10-alpn-preferred-over-npn-client-extra +server = 12-alpn-preferred-over-npn-server-extra +client = 12-alpn-preferred-over-npn-client-extra -[10-alpn-preferred-over-npn-server-extra] +[12-alpn-preferred-over-npn-server-extra] ALPNProtocols = foo NPNProtocols = bar -[10-alpn-preferred-over-npn-client-extra] +[12-alpn-preferred-over-npn-client-extra] ALPNProtocols = foo NPNProtocols = bar # =========================================================== -[11-sni-npn-preferred-over-alpn] -ssl_conf = 11-sni-npn-preferred-over-alpn-ssl +[13-sni-npn-preferred-over-alpn] +ssl_conf = 13-sni-npn-preferred-over-alpn-ssl -[11-sni-npn-preferred-over-alpn-ssl] -server = 11-sni-npn-preferred-over-alpn-server -client = 11-sni-npn-preferred-over-alpn-client -server2 = 11-sni-npn-preferred-over-alpn-server2 +[13-sni-npn-preferred-over-alpn-ssl] +server = 13-sni-npn-preferred-over-alpn-server +client = 13-sni-npn-preferred-over-alpn-client +server2 = 13-sni-npn-preferred-over-alpn-server2 -[11-sni-npn-preferred-over-alpn-server] +[13-sni-npn-preferred-over-alpn-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[11-sni-npn-preferred-over-alpn-server2] +[13-sni-npn-preferred-over-alpn-server2] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[11-sni-npn-preferred-over-alpn-client] +[13-sni-npn-preferred-over-alpn-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-11] +[test-13] ExpectedNPNProtocol = bar ExpectedServerName = server2 -server = 11-sni-npn-preferred-over-alpn-server-extra -server2 = 11-sni-npn-preferred-over-alpn-server2-extra -client = 11-sni-npn-preferred-over-alpn-client-extra +server = 13-sni-npn-preferred-over-alpn-server-extra +server2 = 13-sni-npn-preferred-over-alpn-server2-extra +client = 13-sni-npn-preferred-over-alpn-client-extra -[11-sni-npn-preferred-over-alpn-server-extra] +[13-sni-npn-preferred-over-alpn-server-extra] ALPNProtocols = foo ServerNameCallback = IgnoreMismatch -[11-sni-npn-preferred-over-alpn-server2-extra] +[13-sni-npn-preferred-over-alpn-server2-extra] NPNProtocols = bar -[11-sni-npn-preferred-over-alpn-client-extra] +[13-sni-npn-preferred-over-alpn-client-extra] ALPNProtocols = foo NPNProtocols = bar ServerName = server2 @@ -460,356 +527,356 @@ ServerName = server2 # =========================================================== -[12-npn-simple-resumption] -ssl_conf = 12-npn-simple-resumption-ssl +[14-npn-simple-resumption] +ssl_conf = 14-npn-simple-resumption-ssl -[12-npn-simple-resumption-ssl] -server = 12-npn-simple-resumption-server -client = 12-npn-simple-resumption-client -resume-server = 12-npn-simple-resumption-server -resume-client = 12-npn-simple-resumption-client +[14-npn-simple-resumption-ssl] +server = 14-npn-simple-resumption-server +client = 14-npn-simple-resumption-client +resume-server = 14-npn-simple-resumption-server +resume-client = 14-npn-simple-resumption-client -[12-npn-simple-resumption-server] +[14-npn-simple-resumption-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[12-npn-simple-resumption-client] +[14-npn-simple-resumption-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-12] +[test-14] ExpectedNPNProtocol = foo HandshakeMode = Resume ResumptionExpected = Yes -server = 12-npn-simple-resumption-server-extra -resume-server = 12-npn-simple-resumption-server-extra -client = 12-npn-simple-resumption-client-extra -resume-client = 12-npn-simple-resumption-client-extra +server = 14-npn-simple-resumption-server-extra +resume-server = 14-npn-simple-resumption-server-extra +client = 14-npn-simple-resumption-client-extra +resume-client = 14-npn-simple-resumption-client-extra -[12-npn-simple-resumption-server-extra] +[14-npn-simple-resumption-server-extra] NPNProtocols = foo -[12-npn-simple-resumption-client-extra] +[14-npn-simple-resumption-client-extra] NPNProtocols = foo # =========================================================== -[13-npn-server-switch-resumption] -ssl_conf = 13-npn-server-switch-resumption-ssl +[15-npn-server-switch-resumption] +ssl_conf = 15-npn-server-switch-resumption-ssl -[13-npn-server-switch-resumption-ssl] -server = 13-npn-server-switch-resumption-server -client = 13-npn-server-switch-resumption-client -resume-server = 13-npn-server-switch-resumption-resume-server -resume-client = 13-npn-server-switch-resumption-client +[15-npn-server-switch-resumption-ssl] +server = 15-npn-server-switch-resumption-server +client = 15-npn-server-switch-resumption-client +resume-server = 15-npn-server-switch-resumption-resume-server +resume-client = 15-npn-server-switch-resumption-client -[13-npn-server-switch-resumption-server] +[15-npn-server-switch-resumption-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[13-npn-server-switch-resumption-resume-server] +[15-npn-server-switch-resumption-resume-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[13-npn-server-switch-resumption-client] +[15-npn-server-switch-resumption-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-13] +[test-15] ExpectedNPNProtocol = baz HandshakeMode = Resume ResumptionExpected = Yes -server = 13-npn-server-switch-resumption-server-extra -resume-server = 13-npn-server-switch-resumption-resume-server-extra -client = 13-npn-server-switch-resumption-client-extra -resume-client = 13-npn-server-switch-resumption-client-extra +server = 15-npn-server-switch-resumption-server-extra +resume-server = 15-npn-server-switch-resumption-resume-server-extra +client = 15-npn-server-switch-resumption-client-extra +resume-client = 15-npn-server-switch-resumption-client-extra -[13-npn-server-switch-resumption-server-extra] +[15-npn-server-switch-resumption-server-extra] NPNProtocols = bar,foo -[13-npn-server-switch-resumption-resume-server-extra] +[15-npn-server-switch-resumption-resume-server-extra] NPNProtocols = baz,foo -[13-npn-server-switch-resumption-client-extra] +[15-npn-server-switch-resumption-client-extra] NPNProtocols = foo,bar,baz # =========================================================== -[14-npn-client-switch-resumption] -ssl_conf = 14-npn-client-switch-resumption-ssl +[16-npn-client-switch-resumption] +ssl_conf = 16-npn-client-switch-resumption-ssl -[14-npn-client-switch-resumption-ssl] -server = 14-npn-client-switch-resumption-server -client = 14-npn-client-switch-resumption-client -resume-server = 14-npn-client-switch-resumption-server -resume-client = 14-npn-client-switch-resumption-resume-client +[16-npn-client-switch-resumption-ssl] +server = 16-npn-client-switch-resumption-server +client = 16-npn-client-switch-resumption-client +resume-server = 16-npn-client-switch-resumption-server +resume-client = 16-npn-client-switch-resumption-resume-client -[14-npn-client-switch-resumption-server] +[16-npn-client-switch-resumption-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[14-npn-client-switch-resumption-client] +[16-npn-client-switch-resumption-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[14-npn-client-switch-resumption-resume-client] +[16-npn-client-switch-resumption-resume-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-14] +[test-16] ExpectedNPNProtocol = bar HandshakeMode = Resume ResumptionExpected = Yes -server = 14-npn-client-switch-resumption-server-extra -resume-server = 14-npn-client-switch-resumption-server-extra -client = 14-npn-client-switch-resumption-client-extra -resume-client = 14-npn-client-switch-resumption-resume-client-extra +server = 16-npn-client-switch-resumption-server-extra +resume-server = 16-npn-client-switch-resumption-server-extra +client = 16-npn-client-switch-resumption-client-extra +resume-client = 16-npn-client-switch-resumption-resume-client-extra -[14-npn-client-switch-resumption-server-extra] +[16-npn-client-switch-resumption-server-extra] NPNProtocols = foo,bar,baz -[14-npn-client-switch-resumption-client-extra] +[16-npn-client-switch-resumption-client-extra] NPNProtocols = foo,baz -[14-npn-client-switch-resumption-resume-client-extra] +[16-npn-client-switch-resumption-resume-client-extra] NPNProtocols = bar,baz # =========================================================== -[15-npn-client-first-pref-on-mismatch-resumption] -ssl_conf = 15-npn-client-first-pref-on-mismatch-resumption-ssl +[17-npn-client-first-pref-on-mismatch-resumption] +ssl_conf = 17-npn-client-first-pref-on-mismatch-resumption-ssl -[15-npn-client-first-pref-on-mismatch-resumption-ssl] -server = 15-npn-client-first-pref-on-mismatch-resumption-server -client = 15-npn-client-first-pref-on-mismatch-resumption-client -resume-server = 15-npn-client-first-pref-on-mismatch-resumption-resume-server -resume-client = 15-npn-client-first-pref-on-mismatch-resumption-client +[17-npn-client-first-pref-on-mismatch-resumption-ssl] +server = 17-npn-client-first-pref-on-mismatch-resumption-server +client = 17-npn-client-first-pref-on-mismatch-resumption-client +resume-server = 17-npn-client-first-pref-on-mismatch-resumption-resume-server +resume-client = 17-npn-client-first-pref-on-mismatch-resumption-client -[15-npn-client-first-pref-on-mismatch-resumption-server] +[17-npn-client-first-pref-on-mismatch-resumption-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[15-npn-client-first-pref-on-mismatch-resumption-resume-server] +[17-npn-client-first-pref-on-mismatch-resumption-resume-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[15-npn-client-first-pref-on-mismatch-resumption-client] +[17-npn-client-first-pref-on-mismatch-resumption-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-15] +[test-17] ExpectedNPNProtocol = foo HandshakeMode = Resume ResumptionExpected = Yes -server = 15-npn-client-first-pref-on-mismatch-resumption-server-extra -resume-server = 15-npn-client-first-pref-on-mismatch-resumption-resume-server-extra -client = 15-npn-client-first-pref-on-mismatch-resumption-client-extra -resume-client = 15-npn-client-first-pref-on-mismatch-resumption-client-extra +server = 17-npn-client-first-pref-on-mismatch-resumption-server-extra +resume-server = 17-npn-client-first-pref-on-mismatch-resumption-resume-server-extra +client = 17-npn-client-first-pref-on-mismatch-resumption-client-extra +resume-client = 17-npn-client-first-pref-on-mismatch-resumption-client-extra -[15-npn-client-first-pref-on-mismatch-resumption-server-extra] +[17-npn-client-first-pref-on-mismatch-resumption-server-extra] NPNProtocols = bar -[15-npn-client-first-pref-on-mismatch-resumption-resume-server-extra] +[17-npn-client-first-pref-on-mismatch-resumption-resume-server-extra] NPNProtocols = baz -[15-npn-client-first-pref-on-mismatch-resumption-client-extra] +[17-npn-client-first-pref-on-mismatch-resumption-client-extra] NPNProtocols = foo,bar # =========================================================== -[16-npn-no-server-support-resumption] -ssl_conf = 16-npn-no-server-support-resumption-ssl +[18-npn-no-server-support-resumption] +ssl_conf = 18-npn-no-server-support-resumption-ssl -[16-npn-no-server-support-resumption-ssl] -server = 16-npn-no-server-support-resumption-server -client = 16-npn-no-server-support-resumption-client -resume-server = 16-npn-no-server-support-resumption-resume-server -resume-client = 16-npn-no-server-support-resumption-client +[18-npn-no-server-support-resumption-ssl] +server = 18-npn-no-server-support-resumption-server +client = 18-npn-no-server-support-resumption-client +resume-server = 18-npn-no-server-support-resumption-resume-server +resume-client = 18-npn-no-server-support-resumption-client -[16-npn-no-server-support-resumption-server] +[18-npn-no-server-support-resumption-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[16-npn-no-server-support-resumption-resume-server] +[18-npn-no-server-support-resumption-resume-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[16-npn-no-server-support-resumption-client] +[18-npn-no-server-support-resumption-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-16] +[test-18] HandshakeMode = Resume ResumptionExpected = Yes -server = 16-npn-no-server-support-resumption-server-extra -client = 16-npn-no-server-support-resumption-client-extra -resume-client = 16-npn-no-server-support-resumption-client-extra +server = 18-npn-no-server-support-resumption-server-extra +client = 18-npn-no-server-support-resumption-client-extra +resume-client = 18-npn-no-server-support-resumption-client-extra -[16-npn-no-server-support-resumption-server-extra] +[18-npn-no-server-support-resumption-server-extra] NPNProtocols = foo -[16-npn-no-server-support-resumption-client-extra] +[18-npn-no-server-support-resumption-client-extra] NPNProtocols = foo # =========================================================== -[17-npn-no-client-support-resumption] -ssl_conf = 17-npn-no-client-support-resumption-ssl +[19-npn-no-client-support-resumption] +ssl_conf = 19-npn-no-client-support-resumption-ssl -[17-npn-no-client-support-resumption-ssl] -server = 17-npn-no-client-support-resumption-server -client = 17-npn-no-client-support-resumption-client -resume-server = 17-npn-no-client-support-resumption-server -resume-client = 17-npn-no-client-support-resumption-resume-client +[19-npn-no-client-support-resumption-ssl] +server = 19-npn-no-client-support-resumption-server +client = 19-npn-no-client-support-resumption-client +resume-server = 19-npn-no-client-support-resumption-server +resume-client = 19-npn-no-client-support-resumption-resume-client -[17-npn-no-client-support-resumption-server] +[19-npn-no-client-support-resumption-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[17-npn-no-client-support-resumption-client] +[19-npn-no-client-support-resumption-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[17-npn-no-client-support-resumption-resume-client] +[19-npn-no-client-support-resumption-resume-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-17] +[test-19] HandshakeMode = Resume ResumptionExpected = Yes -server = 17-npn-no-client-support-resumption-server-extra -resume-server = 17-npn-no-client-support-resumption-server-extra -client = 17-npn-no-client-support-resumption-client-extra +server = 19-npn-no-client-support-resumption-server-extra +resume-server = 19-npn-no-client-support-resumption-server-extra +client = 19-npn-no-client-support-resumption-client-extra -[17-npn-no-client-support-resumption-server-extra] +[19-npn-no-client-support-resumption-server-extra] NPNProtocols = foo -[17-npn-no-client-support-resumption-client-extra] +[19-npn-no-client-support-resumption-client-extra] NPNProtocols = foo # =========================================================== -[18-alpn-preferred-over-npn-resumption] -ssl_conf = 18-alpn-preferred-over-npn-resumption-ssl +[20-alpn-preferred-over-npn-resumption] +ssl_conf = 20-alpn-preferred-over-npn-resumption-ssl -[18-alpn-preferred-over-npn-resumption-ssl] -server = 18-alpn-preferred-over-npn-resumption-server -client = 18-alpn-preferred-over-npn-resumption-client -resume-server = 18-alpn-preferred-over-npn-resumption-resume-server -resume-client = 18-alpn-preferred-over-npn-resumption-client +[20-alpn-preferred-over-npn-resumption-ssl] +server = 20-alpn-preferred-over-npn-resumption-server +client = 20-alpn-preferred-over-npn-resumption-client +resume-server = 20-alpn-preferred-over-npn-resumption-resume-server +resume-client = 20-alpn-preferred-over-npn-resumption-client -[18-alpn-preferred-over-npn-resumption-server] +[20-alpn-preferred-over-npn-resumption-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[18-alpn-preferred-over-npn-resumption-resume-server] +[20-alpn-preferred-over-npn-resumption-resume-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[18-alpn-preferred-over-npn-resumption-client] +[20-alpn-preferred-over-npn-resumption-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-18] +[test-20] ExpectedALPNProtocol = foo HandshakeMode = Resume ResumptionExpected = Yes -server = 18-alpn-preferred-over-npn-resumption-server-extra -resume-server = 18-alpn-preferred-over-npn-resumption-resume-server-extra -client = 18-alpn-preferred-over-npn-resumption-client-extra -resume-client = 18-alpn-preferred-over-npn-resumption-client-extra +server = 20-alpn-preferred-over-npn-resumption-server-extra +resume-server = 20-alpn-preferred-over-npn-resumption-resume-server-extra +client = 20-alpn-preferred-over-npn-resumption-client-extra +resume-client = 20-alpn-preferred-over-npn-resumption-client-extra -[18-alpn-preferred-over-npn-resumption-server-extra] +[20-alpn-preferred-over-npn-resumption-server-extra] NPNProtocols = bar -[18-alpn-preferred-over-npn-resumption-resume-server-extra] +[20-alpn-preferred-over-npn-resumption-resume-server-extra] ALPNProtocols = foo NPNProtocols = baz -[18-alpn-preferred-over-npn-resumption-client-extra] +[20-alpn-preferred-over-npn-resumption-client-extra] ALPNProtocols = foo NPNProtocols = bar,baz # =========================================================== -[19-npn-used-if-alpn-not-supported-resumption] -ssl_conf = 19-npn-used-if-alpn-not-supported-resumption-ssl +[21-npn-used-if-alpn-not-supported-resumption] +ssl_conf = 21-npn-used-if-alpn-not-supported-resumption-ssl -[19-npn-used-if-alpn-not-supported-resumption-ssl] -server = 19-npn-used-if-alpn-not-supported-resumption-server -client = 19-npn-used-if-alpn-not-supported-resumption-client -resume-server = 19-npn-used-if-alpn-not-supported-resumption-resume-server -resume-client = 19-npn-used-if-alpn-not-supported-resumption-client +[21-npn-used-if-alpn-not-supported-resumption-ssl] +server = 21-npn-used-if-alpn-not-supported-resumption-server +client = 21-npn-used-if-alpn-not-supported-resumption-client +resume-server = 21-npn-used-if-alpn-not-supported-resumption-resume-server +resume-client = 21-npn-used-if-alpn-not-supported-resumption-client -[19-npn-used-if-alpn-not-supported-resumption-server] +[21-npn-used-if-alpn-not-supported-resumption-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[19-npn-used-if-alpn-not-supported-resumption-resume-server] +[21-npn-used-if-alpn-not-supported-resumption-resume-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[19-npn-used-if-alpn-not-supported-resumption-client] +[21-npn-used-if-alpn-not-supported-resumption-client] CipherString = DEFAULT MaxProtocol = TLSv1.2 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-19] +[test-21] ExpectedNPNProtocol = baz HandshakeMode = Resume ResumptionExpected = Yes -server = 19-npn-used-if-alpn-not-supported-resumption-server-extra -resume-server = 19-npn-used-if-alpn-not-supported-resumption-resume-server-extra -client = 19-npn-used-if-alpn-not-supported-resumption-client-extra -resume-client = 19-npn-used-if-alpn-not-supported-resumption-client-extra +server = 21-npn-used-if-alpn-not-supported-resumption-server-extra +resume-server = 21-npn-used-if-alpn-not-supported-resumption-resume-server-extra +client = 21-npn-used-if-alpn-not-supported-resumption-client-extra +resume-client = 21-npn-used-if-alpn-not-supported-resumption-client-extra -[19-npn-used-if-alpn-not-supported-resumption-server-extra] +[21-npn-used-if-alpn-not-supported-resumption-server-extra] ALPNProtocols = foo NPNProtocols = bar -[19-npn-used-if-alpn-not-supported-resumption-resume-server-extra] +[21-npn-used-if-alpn-not-supported-resumption-resume-server-extra] NPNProtocols = baz -[19-npn-used-if-alpn-not-supported-resumption-client-extra] +[21-npn-used-if-alpn-not-supported-resumption-client-extra] ALPNProtocols = foo NPNProtocols = bar,baz diff --git a/test/ssl-tests/08-npn.cnf.in b/test/ssl-tests/08-npn.cnf.in index 30783e45e..1dc2704bd 100644 --- a/test/ssl-tests/08-npn.cnf.in +++ b/test/ssl-tests/08-npn.cnf.in @@ -110,6 +110,41 @@ our @tests = ( "ExpectedNPNProtocol" => undef, }, }, + { + name => "npn-empty-client-list", + server => { + extra => { + "NPNProtocols" => "foo", + }, + }, + client => { + extra => { + "NPNProtocols" => "", + }, + "MaxProtocol" => "TLSv1.2" + }, + test => { + "ExpectedResult" => "ClientFail", + "ExpectedClientAlert" => "HandshakeFailure" + }, + }, + { + name => "npn-empty-server-list", + server => { + extra => { + "NPNProtocols" => "", + }, + }, + client => { + extra => { + "NPNProtocols" => "foo", + }, + "MaxProtocol" => "TLSv1.2" + }, + test => { + "ExpectedNPNProtocol" => "foo" + }, + }, { name => "npn-with-sni-no-context-switch", server => { diff --git a/test/ssl-tests/09-alpn.cnf b/test/ssl-tests/09-alpn.cnf index e7e6cb953..dd668739a 100644 --- a/test/ssl-tests/09-alpn.cnf +++ b/test/ssl-tests/09-alpn.cnf @@ -1,6 +1,6 @@ # Generated with generate_ssl_tests.pl -num_tests = 16 +num_tests = 18 test-0 = 0-alpn-simple test-1 = 1-alpn-server-finds-match @@ -18,6 +18,8 @@ test-12 = 12-alpn-client-switch-resumption test-13 = 13-alpn-alert-on-mismatch-resumption test-14 = 14-alpn-no-server-support-resumption test-15 = 15-alpn-no-client-support-resumption +test-16 = 16-alpn-empty-client-list +test-17 = 17-alpn-empty-server-list # =========================================================== [0-alpn-simple] @@ -617,3 +619,65 @@ ALPNProtocols = foo ALPNProtocols = foo +# =========================================================== + +[16-alpn-empty-client-list] +ssl_conf = 16-alpn-empty-client-list-ssl + +[16-alpn-empty-client-list-ssl] +server = 16-alpn-empty-client-list-server +client = 16-alpn-empty-client-list-client + +[16-alpn-empty-client-list-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[16-alpn-empty-client-list-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-16] +server = 16-alpn-empty-client-list-server-extra +client = 16-alpn-empty-client-list-client-extra + +[16-alpn-empty-client-list-server-extra] +ALPNProtocols = foo + +[16-alpn-empty-client-list-client-extra] +ALPNProtocols = + + +# =========================================================== + +[17-alpn-empty-server-list] +ssl_conf = 17-alpn-empty-server-list-ssl + +[17-alpn-empty-server-list-ssl] +server = 17-alpn-empty-server-list-server +client = 17-alpn-empty-server-list-client + +[17-alpn-empty-server-list-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[17-alpn-empty-server-list-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-17] +ExpectedResult = ServerFail +ExpectedServerAlert = NoApplicationProtocol +server = 17-alpn-empty-server-list-server-extra +client = 17-alpn-empty-server-list-client-extra + +[17-alpn-empty-server-list-server-extra] +ALPNProtocols = + +[17-alpn-empty-server-list-client-extra] +ALPNProtocols = foo + + diff --git a/test/ssl-tests/09-alpn.cnf.in b/test/ssl-tests/09-alpn.cnf.in index 81330756c..322b7096a 100644 --- a/test/ssl-tests/09-alpn.cnf.in +++ b/test/ssl-tests/09-alpn.cnf.in @@ -322,4 +322,37 @@ our @tests = ( "ExpectedALPNProtocol" => undef, }, }, + { + name => "alpn-empty-client-list", + server => { + extra => { + "ALPNProtocols" => "foo", + }, + }, + client => { + extra => { + "ALPNProtocols" => "", + }, + }, + test => { + "ExpectedALPNProtocol" => undef, + }, + }, + { + name => "alpn-empty-server-list", + server => { + extra => { + "ALPNProtocols" => "", + }, + }, + client => { + extra => { + "ALPNProtocols" => "foo", + }, + }, + test => { + "ExpectedResult" => "ServerFail", + "ExpectedServerAlert" => "NoApplicationProtocol", + }, + }, ); From 98ff83c6cb7e4b137f474e5e05bcee4e138312aa Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 12 Jul 2024 15:18:06 +0800 Subject: [PATCH 55/66] Correct return values for tls_construct_stoc_next_proto_neg Return EXT_RETURN_NOT_SENT in the event that we don't send the extension, rather than EXT_RETURN_SENT. This actually makes no difference at all to the current control flow since this return value is ignored in this case anyway. But lets make it correct anyway. Follow on from CVE-2024-5535 (cherry picked from commit 189a7ed3e380e34ea38fe4190a7c9396bace0fb7) --- ssl/statem/extensions_srvr.c | 3 ++- ssl/statem_ntls/ntls_extensions_srvr.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c index 84bc87f2e..b386cfa90 100644 --- a/ssl/statem/extensions_srvr.c +++ b/ssl/statem/extensions_srvr.c @@ -1566,9 +1566,10 @@ EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt, return EXT_RETURN_FAIL; } s->s3.npn_seen = 1; + return EXT_RETURN_SENT; } - return EXT_RETURN_SENT; + return EXT_RETURN_NOT_SENT; } #endif diff --git a/ssl/statem_ntls/ntls_extensions_srvr.c b/ssl/statem_ntls/ntls_extensions_srvr.c index 0c4e4d60d..38db60294 100644 --- a/ssl/statem_ntls/ntls_extensions_srvr.c +++ b/ssl/statem_ntls/ntls_extensions_srvr.c @@ -587,9 +587,10 @@ EXT_RETURN tls_construct_stoc_next_proto_neg_ntls(SSL *s, WPACKET *pkt, return EXT_RETURN_FAIL; } s->s3.npn_seen = 1; + return EXT_RETURN_SENT; } - return EXT_RETURN_SENT; + return EXT_RETURN_NOT_SENT; } #endif From e1b2a773660647813984126a1dafa2d6351b2677 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 12 Jul 2024 15:19:10 +0800 Subject: [PATCH 56/66] Add ALPN validation in the client The ALPN protocol selected by the server must be one that we originally advertised. We should verify that it is. Follow on from CVE-2024-5535 (cherry picked from commit 4b375b998798dd516d367036773073e1b88e6433) --- ssl/statem/extensions_clnt.c | 24 ++++++++++++++++++++++++ ssl/statem_ntls/ntls_extensions_clnt.c | 24 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index 0e6359987..3efeb9ce0 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -1680,6 +1680,8 @@ int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { size_t len; + PACKET confpkt, protpkt; + int valid = 0; /* We must have requested it. */ if (!s->s3.alpn_sent) { @@ -1698,6 +1700,28 @@ int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); return 0; } + + /* It must be a protocol that we sent */ + if (!PACKET_buf_init(&confpkt, s->ext.alpn, s->ext.alpn_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + while (PACKET_get_length_prefixed_1(&confpkt, &protpkt)) { + if (PACKET_remaining(&protpkt) != len) + continue; + if (memcmp(PACKET_data(pkt), PACKET_data(&protpkt), len) == 0) { + /* Valid protocol found */ + valid = 1; + break; + } + } + + if (!valid) { + /* The protocol sent from the server does not match one we advertised */ + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); + return 0; + } + OPENSSL_free(s->s3.alpn_selected); s->s3.alpn_selected = OPENSSL_malloc(len); if (s->s3.alpn_selected == NULL) { diff --git a/ssl/statem_ntls/ntls_extensions_clnt.c b/ssl/statem_ntls/ntls_extensions_clnt.c index 52fcebe08..3a27dbc97 100644 --- a/ssl/statem_ntls/ntls_extensions_clnt.c +++ b/ssl/statem_ntls/ntls_extensions_clnt.c @@ -674,6 +674,8 @@ int tls_parse_stoc_alpn_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { size_t len; + PACKET confpkt, protpkt; + int valid = 0; /* We must have requested it. */ if (!s->s3.alpn_sent) { @@ -692,6 +694,28 @@ int tls_parse_stoc_alpn_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); return 0; } + + /* It must be a protocol that we sent */ + if (!PACKET_buf_init(&confpkt, s->ext.alpn, s->ext.alpn_len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + while (PACKET_get_length_prefixed_1(&confpkt, &protpkt)) { + if (PACKET_remaining(&protpkt) != len) + continue; + if (memcmp(PACKET_data(pkt), PACKET_data(&protpkt), len) == 0) { + /* Valid protocol found */ + valid = 1; + break; + } + } + + if (!valid) { + /* The protocol sent from the server does not match one we advertised */ + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); + return 0; + } + OPENSSL_free(s->s3.alpn_selected); s->s3.alpn_selected = OPENSSL_malloc(len); if (s->s3.alpn_selected == NULL) { From 8906cf32a98462260a47ae81d639c9d3ddeb15f3 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 12 Jul 2024 15:20:21 +0800 Subject: [PATCH 57/66] Add explicit testing of ALN and NPN in sslapitest We already had some tests elsewhere - but this extends that testing with additional tests. Follow on from CVE-2024-5535 (cherry picked from commit ca176d7291eb780e4ed2781342f5be5a32210a68) --- test/sslapitest.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) diff --git a/test/sslapitest.c b/test/sslapitest.c index 352e51cc2..ca2caed2e 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -10669,6 +10669,231 @@ static int test_select_next_proto(int idx) return ret; } +static const unsigned char fooprot[] = {3, 'f', 'o', 'o' }; +static const unsigned char barprot[] = {3, 'b', 'a', 'r' }; + +#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_NEXTPROTONEG) +static int npn_advert_cb(SSL *ssl, const unsigned char **out, + unsigned int *outlen, void *arg) +{ + int *idx = (int *)arg; + + switch (*idx) { + default: + case 0: + *out = fooprot; + *outlen = sizeof(fooprot); + return SSL_TLSEXT_ERR_OK; + + case 1: + *outlen = 0; + return SSL_TLSEXT_ERR_OK; + + case 2: + return SSL_TLSEXT_ERR_NOACK; + } +} + +static int npn_select_cb(SSL *s, unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg) +{ + int *idx = (int *)arg; + + switch (*idx) { + case 0: + case 1: + *out = (unsigned char *)(fooprot + 1); + *outlen = *fooprot; + return SSL_TLSEXT_ERR_OK; + + case 3: + *out = (unsigned char *)(barprot + 1); + *outlen = *barprot; + return SSL_TLSEXT_ERR_OK; + + case 4: + *outlen = 0; + return SSL_TLSEXT_ERR_OK; + + default: + case 2: + return SSL_TLSEXT_ERR_ALERT_FATAL; + } +} + +/* + * Test the NPN callbacks + * Test 0: advert = foo, select = foo + * Test 1: advert = , select = foo + * Test 2: no advert + * Test 3: advert = foo, select = bar + * Test 4: advert = foo, select = (should fail) + */ +static int test_npn(int idx) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl = NULL, *clientssl = NULL; + int testresult = 0; + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), 0, TLS1_2_VERSION, + &sctx, &cctx, cert, privkey))) + goto end; + + SSL_CTX_set_next_protos_advertised_cb(sctx, npn_advert_cb, &idx); + SSL_CTX_set_next_proto_select_cb(cctx, npn_select_cb, &idx); + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, + NULL))) + goto end; + + if (idx == 4) { + /* We don't allow empty selection of NPN, so this should fail */ + if (!TEST_false(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + } else { + const unsigned char *prot; + unsigned int protlen; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + SSL_get0_next_proto_negotiated(serverssl, &prot, &protlen); + switch (idx) { + case 0: + case 1: + if (!TEST_mem_eq(prot, protlen, fooprot + 1, *fooprot)) + goto end; + break; + case 2: + if (!TEST_uint_eq(protlen, 0)) + goto end; + break; + case 3: + if (!TEST_mem_eq(prot, protlen, barprot + 1, *barprot)) + goto end; + break; + default: + TEST_error("Should not get here"); + goto end; + } + } + + testresult = 1; + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} +#endif /* !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_NEXTPROTONEG) */ + +static int alpn_select_cb2(SSL *ssl, const unsigned char **out, + unsigned char *outlen, const unsigned char *in, + unsigned int inlen, void *arg) +{ + int *idx = (int *)arg; + + switch (*idx) { + case 0: + *out = (unsigned char *)(fooprot + 1); + *outlen = *fooprot; + return SSL_TLSEXT_ERR_OK; + + case 2: + *out = (unsigned char *)(barprot + 1); + *outlen = *barprot; + return SSL_TLSEXT_ERR_OK; + + case 3: + *outlen = 0; + return SSL_TLSEXT_ERR_OK; + + default: + case 1: + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + return 0; +} + +/* + * Test the ALPN callbacks + * Test 0: client = foo, select = foo + * Test 1: client = , select = none + * Test 2: client = foo, select = bar (should fail) + * Test 3: client = foo, select = (should fail) + */ +static int test_alpn(int idx) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl = NULL, *clientssl = NULL; + int testresult = 0; + const unsigned char *prots = fooprot; + unsigned int protslen = sizeof(fooprot); + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), 0, 0, + &sctx, &cctx, cert, privkey))) + goto end; + + SSL_CTX_set_alpn_select_cb(sctx, alpn_select_cb2, &idx); + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, + NULL))) + goto end; + + if (idx == 1) { + prots = NULL; + protslen = 0; + } + + /* SSL_set_alpn_protos returns 0 for success! */ + if (!TEST_false(SSL_set_alpn_protos(clientssl, prots, protslen))) + goto end; + + if (idx == 2 || idx == 3) { + /* We don't allow empty selection of NPN, so this should fail */ + if (!TEST_false(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + } else { + const unsigned char *prot; + unsigned int protlen; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + SSL_get0_alpn_selected(clientssl, &prot, &protlen); + switch (idx) { + case 0: + if (!TEST_mem_eq(prot, protlen, fooprot + 1, *fooprot)) + goto end; + break; + case 1: + if (!TEST_uint_eq(protlen, 0)) + goto end; + break; + default: + TEST_error("Should not get here"); + goto end; + } + } + + testresult = 1; + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile provider config dhfile\n") int setup_tests(void) @@ -10945,6 +11170,10 @@ int setup_tests(void) #endif ADD_ALL_TESTS(test_multi_resume, 5); ADD_ALL_TESTS(test_select_next_proto, OSSL_NELEM(next_proto_tests)); +#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_NEXTPROTONEG) + ADD_ALL_TESTS(test_npn, 5); +#endif + ADD_ALL_TESTS(test_alpn, 4); return 1; err: From 6d7e26faff551e8327f4017c70801f5ffaa5a60b Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 12 Jul 2024 15:22:25 +0800 Subject: [PATCH 58/66] Add a test for an empty NextProto message It is valid according to the spec for a NextProto message to have no protocols listed in it. The OpenSSL implementation however does not allow us to create such a message. In order to check that we work as expected when communicating with a client that does generate such messages we have to use a TLSProxy test. Follow on from CVE-2024-5535 (cherry picked from commit 99c2b6b971c302595db1801e26a202247238659d) --- test/recipes/70-test_npn.t | 73 +++++++++++++++++++++++++++++++++ util/perl/TLSProxy/Message.pm | 9 ++++ util/perl/TLSProxy/NextProto.pm | 54 ++++++++++++++++++++++++ util/perl/TLSProxy/Proxy.pm | 1 + 4 files changed, 137 insertions(+) create mode 100644 test/recipes/70-test_npn.t create mode 100644 util/perl/TLSProxy/NextProto.pm diff --git a/test/recipes/70-test_npn.t b/test/recipes/70-test_npn.t new file mode 100644 index 000000000..f82e71af6 --- /dev/null +++ b/test/recipes/70-test_npn.t @@ -0,0 +1,73 @@ +#! /usr/bin/env perl +# Copyright 2024 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 + +use strict; +use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file/; +use OpenSSL::Test::Utils; + +use TLSProxy::Proxy; + +my $test_name = "test_npn"; +setup($test_name); + +plan skip_all => "TLSProxy isn't usable on $^O" + if $^O =~ /^(VMS)$/; + +plan skip_all => "$test_name needs the dynamic engine feature enabled" + if disabled("engine") || disabled("dynamic-engine"); + +plan skip_all => "$test_name needs the sock feature enabled" + if disabled("sock"); + +plan skip_all => "$test_name needs NPN enabled" + if disabled("nextprotoneg"); + +plan skip_all => "$test_name needs TLSv1.2 enabled" + if disabled("tls1_2"); + +my $proxy = TLSProxy::Proxy->new( + undef, + cmdstr(app(["openssl"]), display => 1), + srctop_file("apps", "server.pem"), + (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) +); + +$proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; +plan tests => 1; + +my $npnseen = 0; + +# Test 1: Check sending an empty NextProto message from the client works. This is +# valid as per the spec, but OpenSSL does not allow you to send it. +# Therefore we must be prepared to receive such a message but we cannot +# generate it except via TLSProxy +$proxy->clear(); +$proxy->filter(\&npn_filter); +$proxy->clientflags("-nextprotoneg foo -no_tls1_3"); +$proxy->serverflags("-nextprotoneg foo"); +$proxy->start(); +ok($npnseen && TLSProxy::Message->success(), "Empty NPN message"); + +sub npn_filter +{ + my $proxy = shift; + my $message; + + # The NextProto message always appears in flight 2 + return if $proxy->flight != 2; + + foreach my $message (@{$proxy->message_list}) { + if ($message->mt == TLSProxy::Message::MT_NEXT_PROTO) { + # Our TLSproxy NextProto message support doesn't support parsing of + # the message. If we repack it just creates an empty NextProto + # message - which is exactly the scenario we want to test here. + $message->repack(); + $npnseen = 1; + } + } +} diff --git a/util/perl/TLSProxy/Message.pm b/util/perl/TLSProxy/Message.pm index 55af352a4..2457834fb 100644 --- a/util/perl/TLSProxy/Message.pm +++ b/util/perl/TLSProxy/Message.pm @@ -378,6 +378,15 @@ sub create_message [@message_frag_lens] ); $message->parse(); + } elsif ($mt == MT_NEXT_PROTO) { + $message = TLSProxy::NextProto->new( + $server, + $data, + [@message_rec_list], + $startoffset, + [@message_frag_lens] + ); + $message->parse(); } else { #Unknown message type $message = TLSProxy::Message->new( diff --git a/util/perl/TLSProxy/NextProto.pm b/util/perl/TLSProxy/NextProto.pm new file mode 100644 index 000000000..0e1834754 --- /dev/null +++ b/util/perl/TLSProxy/NextProto.pm @@ -0,0 +1,54 @@ +# Copyright 2024 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 + +use strict; + +package TLSProxy::NextProto; + +use vars '@ISA'; +push @ISA, 'TLSProxy::Message'; + +sub new +{ + my $class = shift; + my ($server, + $data, + $records, + $startoffset, + $message_frag_lens) = @_; + + my $self = $class->SUPER::new( + $server, + TLSProxy::Message::MT_NEXT_PROTO, + $data, + $records, + $startoffset, + $message_frag_lens); + + return $self; +} + +sub parse +{ + # We don't support parsing at the moment +} + +# This is supposed to reconstruct the on-the-wire message data following changes. +# For now though since we don't support parsing we just create an empty NextProto +# message - this capability is used in test_npn +sub set_message_contents +{ + my $self = shift; + my $data; + + $data = pack("C32", 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + $self->data($data); +} +1; diff --git a/util/perl/TLSProxy/Proxy.pm b/util/perl/TLSProxy/Proxy.pm index 3de10eccb..b707722b6 100644 --- a/util/perl/TLSProxy/Proxy.pm +++ b/util/perl/TLSProxy/Proxy.pm @@ -23,6 +23,7 @@ use TLSProxy::CertificateRequest; use TLSProxy::CertificateVerify; use TLSProxy::ServerKeyExchange; use TLSProxy::NewSessionTicket; +use TLSProxy::NextProto; my $have_IPv6; my $IP_factory; From 9573eb9a40009969b9dd743f14b1a5a34756398e Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 12 Jul 2024 15:24:13 +0800 Subject: [PATCH 59/66] Add a CHANGES entry for CVE-2024-5535 --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 645fafb82..54fa50839 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,8 @@ Changes between 8.4.0 and 8.5.0 [xx XXX xxxx] + *) 修复CVE-2024-5535 + *) 修复CVE-2024-4741 *) 修复CVE-2024-4603 From da08681fd0bca4e92f82106385895b19a778bfb4 Mon Sep 17 00:00:00 2001 From: K1 Date: Mon, 29 Jul 2024 16:34:48 +0800 Subject: [PATCH 60/66] Modify ci os-zoo, support more os Support more OS, including alpine, debian(10, 11, 12), ubuntu(20.04, 22.04), fedora(38, 39), centos(8), rockylinux(8, 9), macos(12, 13, 14), windows(2019, 2022). --- .github/workflows/os-zoo.yml | 138 ++++++++++++++++++++++++++++++----- 1 file changed, 118 insertions(+), 20 deletions(-) diff --git a/.github/workflows/os-zoo.yml b/.github/workflows/os-zoo.yml index 3e05b803d..2ae49e5d2 100644 --- a/.github/workflows/os-zoo.yml +++ b/.github/workflows/os-zoo.yml @@ -1,4 +1,4 @@ -# Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2021-2024 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 @@ -11,56 +11,154 @@ on: schedule: - cron: '0 5 * * *' +permissions: + contents: read + jobs: - unix: + alpine: strategy: fail-fast: false matrix: - os: [ - macos-10.15, - macos-11, - ubuntu-18.04, - ubuntu-20.04, - ] - runs-on: ${{ matrix.os }} + tag: [edge, latest] + cc: [gcc, clang] + branch: [8.3-stable, 8.4-stable, master] + runs-on: ubuntu-latest + container: + image: docker.io/library/alpine:${{ matrix.tag }} + env: + # https://www.openwall.com/lists/musl/2022/02/16/14 + EXTRA_CFLAGS: ${{ matrix.cc == 'clang' && '-Wno-sign-compare' || '' }} + CC: ${{ matrix.cc }} steps: - - uses: actions/checkout@v2 + - name: install packages + run: apk --no-cache add build-base perl linux-headers ${{ matrix.cc }} + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} - name: config run: | - CC=${{ matrix.zoo.cc }} ./config --banner=Configured \ - -Wall -Werror --strict-warnings enable-fips + ./config --banner=Configured no-shared -Wall -Werror enable-ntls --strict-warnings \ + ${EXTRA_CFLAGS} - name: config dump run: ./configdata.pm --dump - name: make run: make -s -j4 + - name: get cpu info + run: | + cat /proc/cpuinfo + ./util/opensslwrap.sh version -c - name: make test run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} + + linux: + strategy: + fail-fast: false + matrix: + branch: [8.3-stable, 8.4-stable, master] + zoo: + - image: docker.io/library/debian:10 + install: apt-get update && apt-get install -y gcc make perl + - image: docker.io/library/debian:11 + install: apt-get update && apt-get install -y gcc make perl + - image: docker.io/library/debian:12 + install: apt-get update && apt-get install -y gcc make perl + - image: docker.io/library/ubuntu:20.04 + install: apt-get update && apt-get install -y gcc make perl + - image: docker.io/library/ubuntu:22.04 + install: apt-get update && apt-get install -y gcc make perl + - image: docker.io/library/fedora:38 + install: dnf install -y gcc make perl-core + - image: docker.io/library/fedora:39 + install: dnf install -y gcc make perl-core + - image: docker.io/library/centos:8 + install: | + sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* && \ + sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* && \ + dnf install -y gcc make perl-core + - image: docker.io/library/rockylinux:8 + install: dnf install -y gcc make perl-core + - image: docker.io/library/rockylinux:9 + install: dnf install -y gcc make perl-core + runs-on: ubuntu-latest + container: ${{ matrix.zoo.image }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + - name: install packages + run: ${{ matrix.zoo.install }} + - name: config + run: ./config + - name: config dump + run: ./configdata.pm --dump + - name: make + run: make -j4 + - name: get cpu info + run: | + cat /proc/cpuinfo + ./util/opensslwrap.sh version -c + - name: make test + run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} + + macos: + strategy: + fail-fast: false + matrix: + branch: [8.3-stable, 8.4-stable, master] + os: [macos-12, macos-13, macos-14] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + - name: config + run: ./config --banner=Configured -Wall -Werror --strict-warnings enable-ntls + - name: config dump + run: ./configdata.pm --dump + - name: make + run: make -s -j4 + - name: get cpu info + run: | + sysctl machdep.cpu + ./util/opensslwrap.sh version -c + - name: make test + run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} + windows: strategy: fail-fast: false matrix: - os: [ - windows-2019, - windows-2022 - ] + branch: [8.3-stable, 8.4-stable, master] + os: [windows-2019, windows-2022] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} - uses: ilammy/msvc-dev-cmd@v1 - uses: ilammy/setup-nasm@v1 - - uses: shogo82148/actions-setup-perl@v1 - name: prepare the build directory run: mkdir _build - name: config working-directory: _build - run: | - perl ..\Configure --banner=Configured no-makedepend enable-fips + run: perl ..\Configure --banner=Configured no-makedepend enable-ntls - name: config dump working-directory: _build run: ./configdata.pm --dump - name: build working-directory: _build run: nmake /S + - name: download coreinfo + uses: suisei-cn/actions-download-file@v1.6.0 + with: + url: "https://download.sysinternals.com/files/Coreinfo.zip" + target: _build/coreinfo/ + - name: get cpu info + working-directory: _build + run: | + 7z.exe x coreinfo/Coreinfo.zip + ./Coreinfo64.exe -accepteula -f + apps/openssl.exe version -c - name: test working-directory: _build run: nmake test VERBOSE_FAILURE=yes HARNESS_JOBS=4 From 732c29476b49cd2990bb8fd92e8a02a762c41c14 Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 30 Jul 2024 11:34:30 +0800 Subject: [PATCH 61/66] Define OPENSSL_NO_ for alrorithms which has been removed Fixes #638 To keep backward compatibility, still define the macro OPENSSL_NO_ for the algorithm which has been removed by Tongsuo to solve compilation problems. --- Configure | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Configure b/Configure index ce92fd517..0f73ccd0a 100755 --- a/Configure +++ b/Configure @@ -588,8 +588,23 @@ our %disabled = ( # "what" => "comment" "zkp-gadget" => "default", "zkp-transcript" => "default", "bn-method" => "default", - "smtc" => "default", - "smtc-debug" => "default", + "smtc" => "default", + "smtc-debug" => "default", + "aria" => "default", # ARIA has been removed + "bf" => "default", # Blowfish has been removed + "blake2" => "default", # Blake2 has been removed + "camellia" => "default", # Camellia has been removed + "cast" => "default", # CAST has been removed + "idea" => "default", # IDEA has been removed + "md2" => "default", # MD2 has been removed + "mdc2" => "default", # MDC2 has been removed + "md4" => "default", # MD4 has been removed + "gost" => "default", # GOST has been removed + "rc2" => "default", # RC2 has been removed + "rmd160" => "default", # RIPEMD has been removed + "ripemd" => "default", # RIPEMD has been removed + "seed" => "default", # SEED has been removed + "whirlpool" => "default", # Whirlpool has been removed ); # Note: => pair form used for aesthetics, not to truly make a hash table From a13ed8e261a098bb0e02174fdb4e2074626cbf44 Mon Sep 17 00:00:00 2001 From: K1 Date: Wed, 31 Jul 2024 10:33:16 +0800 Subject: [PATCH 62/66] Add loongarch64 target add loongarch64 config for no-asm. --- Configurations/10-main.conf | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Configurations/10-main.conf b/Configurations/10-main.conf index aa464356c..f504d6a19 100644 --- a/Configurations/10-main.conf +++ b/Configurations/10-main.conf @@ -515,6 +515,13 @@ my %targets = ( perlasm_scheme => "linux64", }, + # loongarch64 below refers to contemporary LoongArch Architecture + # specifications, + "linux64-loongarch64" => { + inherit_from => [ "linux-generic64"], + perlasm_scheme => "linux64", + }, + #### IA-32 targets... #### These two targets are a bit aged and are to be used on older Linux #### machines where gcc doesn't understand -m32 and -m64 From 7ecc19e2f07a498242448d8937fa4b01a3d972ea Mon Sep 17 00:00:00 2001 From: K1 Date: Wed, 28 Feb 2024 16:54:10 +0800 Subject: [PATCH 63/66] SMTC integrates with crypto card based on atf-slibce engine;add sdf, TSAPI and etc. DRBG set reseed interval and reseed_time_interval according to GM/T 0105-2021. Modify of the integrity verification mechanism to SM2 signature. App rand supports getting entropy from specified source. Rename entropy rtc1 to rtcode, rtc2 to rtmem. Add rtsock entropy source. Support requesting entropy from specified entropy source. Support atf-slibce engine. Add sdf framework and partial APIs. Add sdf app. App speed add keygen for SM2 and GenerateKey with SDF. Add TSAPI, mainly includes functions such as random number, signature verification, encryption and decryption, etc. --- .github/workflows/ci.yml | 9 +- .github/workflows/compiler-zoo.yml | 3 +- .github/workflows/run-checker-ci.yml | 2 - .github/workflows/run-checker-daily.yml | 2 - .github/workflows/run-checker-merge.yml | 2 - CHANGES | 12 +- Configurations/00-base-templates.conf | 6 + Configure | 67 +- VERSION.dat | 3 +- apps/build.info | 4 + apps/mod.c | 595 +++++--- apps/openssl.c | 115 +- apps/rand.c | 84 +- apps/s_server.c | 2 - apps/sdf.c | 543 +++++++ apps/speed.c | 326 +++- apps/version.c | 1 - crypto/bio/bss_log.c | 20 +- crypto/build.info | 15 +- crypto/err/openssl.txt | 7 +- crypto/evp/m_sigver.c | 12 +- crypto/evp/pmeth_gn.c | 9 + crypto/evp/pmeth_lib.c | 76 + crypto/info.c | 16 +- crypto/init.c | 4 + crypto/o_syslog.c | 80 + crypto/provider.c | 10 + crypto/provider_core.c | 24 + crypto/provider_predefined.c | 11 +- crypto/rand/prov_seed.c | 28 + crypto/rand/rand_lib.c | 19 + crypto/rand/rand_pool.c | 8 + crypto/sdf/build.info | 3 + crypto/sdf/sdf_lib.c | 416 ++++++ crypto/sdf/sdf_local.h | 130 ++ crypto/sdf/sdf_meth.c | 168 +++ crypto/sm2/sm2_crypt.c | 56 + crypto/trace.c | 5 +- crypto/tsapi/build.info | 3 + crypto/tsapi/tsapi_lib.c | 1322 +++++++++++++++++ crypto/x509/v3_skid.c | 6 +- include/crypto/rand.h | 15 + include/crypto/rand_pool.h | 23 +- include/crypto/sm2.h | 5 + include/internal/cryptlib.h | 5 + include/internal/provider.h | 2 + include/internal/sdf.h | 16 + include/internal/smtc_names.h | 20 +- include/openssl/core_dispatch.h | 6 + include/openssl/crypto.h.in | 27 + include/openssl/evp.h | 6 + include/openssl/opensslv.h.in | 2 +- include/openssl/proverr.h | 6 +- include/openssl/provider.h | 2 + include/openssl/rand.h | 1 + include/openssl/sdf.h | 118 ++ include/openssl/self_test.h | 6 + include/openssl/sgd.h | 53 + include/openssl/trace.h | 3 +- include/openssl/tsapi.h | 98 ++ include/openssl/types.h | 2 + providers/build.info | 36 +- providers/common/include/prov/proverr.h | 2 +- providers/common/include/prov/provider_util.h | 8 +- providers/common/provider_err.c | 10 +- providers/implementations/rands/drbg_hash.c | 18 +- providers/implementations/rands/drbg_local.h | 32 +- .../implementations/rands/seeding/rand_unix.c | 125 +- .../implementations/rands/seeding/rand_win.c | 110 +- providers/implementations/rands/smtc_rng.c | 164 +- providers/prov_running.c | 2 + providers/smtc/README.md | 20 +- providers/smtc/self_test.c | 625 ++++++-- providers/smtc/self_test.h | 18 +- providers/smtc/self_test_data.inc | 142 +- providers/smtc/self_test_kats.c | 386 ++++- providers/smtc/self_test_rand.c | 104 +- providers/smtc/self_test_rand.h | 8 +- providers/smtc/smtckey.h.in | 11 +- providers/smtc/smtcprov.c | 334 ++++- ssl/ssl_rsa.c | 139 ++ ssl/statem_ntls/ntls_statem_srvr.c | 2 +- ssl/t1_enc.c | 7 + test/build.info | 6 +- test/{ssl-tests => ntls-tests}/31-ntls.cnf | 0 test/{ssl-tests => ntls-tests}/31-ntls.cnf.in | 0 .../32-ntls-force-ntls.cnf | 0 .../32-ntls-force-ntls.cnf.in | 0 .../39-ntls-sni-ticket.cnf | 0 .../39-ntls-sni-ticket.cnf.in | 0 .../40-ntls_client_auth.cnf | 0 .../40-ntls_client_auth.cnf.in | 0 .../41-ntls-alpn.cnf | 0 .../41-ntls-alpn.cnf.in | 0 test/recipes/00-prep_smtc_cnf.t | 9 +- test/recipes/10-test_mod_sm2.t | 8 +- test/recipes/20-test_cli_smtc.t | 95 +- test/recipes/20-test_mod.t | 10 +- test/recipes/70-test_ntlssni.t | 6 +- test/recipes/80-test_ntls.t | 129 ++ test/recipes/80-test_sign_sm2.t | 7 +- test/recipes/80-test_ssl_new.t | 32 +- test/recipes/92-test_tsapi.t | 22 + test/{smtc-and-base.cnf => smtc.cnf} | 5 - test/testutil/provider.c | 2 +- test/tsapi_test.c | 484 ++++++ util/libcrypto.num | 54 + 107 files changed, 6826 insertions(+), 986 deletions(-) create mode 100644 apps/sdf.c create mode 100644 crypto/o_syslog.c create mode 100644 crypto/sdf/build.info create mode 100644 crypto/sdf/sdf_lib.c create mode 100644 crypto/sdf/sdf_local.h create mode 100644 crypto/sdf/sdf_meth.c create mode 100644 crypto/tsapi/build.info create mode 100644 crypto/tsapi/tsapi_lib.c create mode 100644 include/internal/sdf.h create mode 100644 include/openssl/sdf.h create mode 100644 include/openssl/sgd.h create mode 100644 include/openssl/tsapi.h rename test/{ssl-tests => ntls-tests}/31-ntls.cnf (100%) rename test/{ssl-tests => ntls-tests}/31-ntls.cnf.in (100%) rename test/{ssl-tests => ntls-tests}/32-ntls-force-ntls.cnf (100%) rename test/{ssl-tests => ntls-tests}/32-ntls-force-ntls.cnf.in (100%) rename test/{ssl-tests => ntls-tests}/39-ntls-sni-ticket.cnf (100%) rename test/{ssl-tests => ntls-tests}/39-ntls-sni-ticket.cnf.in (100%) rename test/{ssl-tests => ntls-tests}/40-ntls_client_auth.cnf (100%) rename test/{ssl-tests => ntls-tests}/40-ntls_client_auth.cnf.in (100%) rename test/{ssl-tests => ntls-tests}/41-ntls-alpn.cnf (100%) rename test/{ssl-tests => ntls-tests}/41-ntls-alpn.cnf.in (100%) create mode 100644 test/recipes/80-test_ntls.t create mode 100644 test/recipes/92-test_tsapi.t rename test/{smtc-and-base.cnf => smtc.cnf} (82%) create mode 100644 test/tsapi_test.c diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c40b7209..473c13119 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -209,7 +209,7 @@ jobs: - name: modprobe tls run: sudo modprobe tls - name: config - run: ./config --banner=Configured --strict-warnings no-ec enable-ssl-trace enable-zlib enable-zlib-dynamic enable-crypto-mdebug enable-crypto-mdebug-backtrace enable-egd enable-ktls enable-fips enable-ntls enable-optimize-chacha-choose enable-status enable-crypto-mdebug-count enable-cert-compression enable-delegated-credential enable-bn-method --with-rand-seed=getrandom,rtc && perl configdata.pm --dump + run: ./config --banner=Configured --strict-warnings no-ec enable-ssl-trace enable-zlib enable-zlib-dynamic enable-crypto-mdebug enable-crypto-mdebug-backtrace enable-egd enable-ktls enable-fips enable-ntls enable-optimize-chacha-choose enable-status enable-crypto-mdebug-count enable-cert-compression enable-delegated-credential enable-bn-method --with-rand-seed=rtcode,rtmem,rtsock && perl configdata.pm --dump - name: make run: make -s -j4 - name: make test @@ -399,8 +399,11 @@ jobs: run: ./config enable-ntls enable-smtc enable-smtc-debug --strict-warnings && perl configdata.pm --dump - name: make run: make -s -j4 - - name: make test - run: make test + - name: make test selected cases + run: | + make test TESTS="test_abort test_sanity test_symbol_presence test_test test_errstr test_internal_context \ + test_internal_sm3 test_internal_sm4 test_smtc_rand_self_test test_mod test_mod_sm2 test_cli_smtc \ + test_ntlssni test_tsapi test_sign_sm2 test_ntls" - name: make clean run: make clean - name: check dirty diff --git a/.github/workflows/compiler-zoo.yml b/.github/workflows/compiler-zoo.yml index 59d37425e..c89fb0b27 100644 --- a/.github/workflows/compiler-zoo.yml +++ b/.github/workflows/compiler-zoo.yml @@ -76,8 +76,7 @@ jobs: - name: config run: | CC=${{ matrix.zoo.cc }} ./config --banner=Configured no-shared \ - -Wall -Werror enable-ntls enable-smtc enable-smtc-debug \ - --strict-warnings + -Wall -Werror enable-ntls --strict-warnings - name: config dump run: ./configdata.pm --dump diff --git a/.github/workflows/run-checker-ci.yml b/.github/workflows/run-checker-ci.yml index 71660df1e..b5f07a7b8 100644 --- a/.github/workflows/run-checker-ci.yml +++ b/.github/workflows/run-checker-ci.yml @@ -32,8 +32,6 @@ jobs: no-tls1_3, enable-trace enable-fips, enable-ntls, - enable-smtc enable-smtc-debug, - enable-ntls enable-smtc enable-smtc-debug, no-ts, no-ui, ] diff --git a/.github/workflows/run-checker-daily.yml b/.github/workflows/run-checker-daily.yml index 1a927a904..7888e6277 100644 --- a/.github/workflows/run-checker-daily.yml +++ b/.github/workflows/run-checker-daily.yml @@ -114,8 +114,6 @@ jobs: enable-zlib-dynamic, no-zlib-dynamic, enable-ntls, - enable-smtc enable-smtc-debug, - enable-ntls enable-smtc enable-smtc-debug, enable-ec_elgamal enable-twisted_ec_elgamal, enable-bulletproofs, enable-bulletproofs enable-nizk enable-zkp-gadget enable-ec_elgamal enable-twisted_ec_elgamal, diff --git a/.github/workflows/run-checker-merge.yml b/.github/workflows/run-checker-merge.yml index c5e0c3853..977e9fa52 100644 --- a/.github/workflows/run-checker-merge.yml +++ b/.github/workflows/run-checker-merge.yml @@ -27,8 +27,6 @@ jobs: enable-weak-ssl-ciphers, enable-zlib, enable-ntls, - enable-smtc enable-smtc-debug, - enable-ntls enable-smtc enable-smtc-debug, ] runs-on: ubuntu-latest steps: diff --git a/CHANGES b/CHANGES index 54fa50839..b1a9673b8 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,16 @@ Changes between 8.4.0 and 8.5.0 [xx XXX xxxx] + *) SMTC Provider适配蚂蚁密码卡(atf_slibce) + + *) 增加SDF框架和部分功能接口 + + *) 随机数熵源增加rtcode、rtmem和rtsock + + *) speed支持测试SM2密钥对生成和SM4密钥对生成(SDF方式) + + *) 增加TSAPI,支持常见密码学算法 + *) 修复CVE-2024-5535 *) 修复CVE-2024-4741 @@ -28,8 +38,6 @@ *) 修复CVE-2023-5678 - *) 随机数熵源增加系统时间(RTC)方案 - *) 增加商用密码检测和认证Provider,包括身份认证、完整性验证、算法自测试、随机数自检、 熵源健康测试;增加mod应用,包括生成SMTC配置、自测试功能 diff --git a/Configurations/00-base-templates.conf b/Configurations/00-base-templates.conf index 073867565..5111bbe50 100644 --- a/Configurations/00-base-templates.conf +++ b/Configurations/00-base-templates.conf @@ -50,6 +50,9 @@ my %targets=( my @defs = ( 'OPENSSL_BUILDING_OPENSSL' ); push @defs, "ZLIB" unless $disabled{zlib}; push @defs, "ZLIB_SHARED" unless $disabled{"zlib-dynamic"}; + + push @defs, "SDF_LIB" unless $disabled{"sdf-lib"}; + push @defs, "SDF_LIB_SHARED" unless $disabled{"sdf-lib-dynamic"}; return [ @defs ]; }, includes => @@ -57,6 +60,9 @@ my %targets=( my @incs = (); push @incs, $withargs{zlib_include} if !$disabled{zlib} && $withargs{zlib_include}; + + push @incs, $withargs{sdf_include} + if !$disabled{sdf_lib} && $withargs{sdf_include}; return [ @incs ]; }, }, diff --git a/Configure b/Configure index 0f73ccd0a..e3bd53819 100755 --- a/Configure +++ b/Configure @@ -271,9 +271,14 @@ $config{builddir} = abs2rel($blddir, $blddir); # echo -n 'holy hand grenade of antioch' | openssl sha256 $config{FIPSKEY} = 'f4556650ac31d35461610bac4ed81b1a181b2d8a43ea2854cbae22ca74560813'; -# echo -n "Tongsuo in hand, no worries about compliance" | tongsuo sm3 -$config{SMTCKEY} = - '5b3d9ad84fd72961e63f27a3d5da2bb663e2ed9c7b761b8ad6d041ebc68f5098'; +$config{SMTCPASSWD} = 'Tongsuo123'; +$config{SMTCPUBKEY} = +'-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAERjiZ5ubxrnOZnjhvqvuJ5UcdRI64 +sBEVwF0UztQK9eYzqOsFEm0PKkCjoYkdmiZ+Und0agHk94eFKhtUYsu0bw== +-----END PUBLIC KEY-----'; +$config{SMTCPUBKEY} =~ s|\n|\\n|g; + # Collect reconfiguration information if needed my @argvcopy=@ARGV; @@ -355,8 +360,6 @@ $config{tongsuo_prerelease} = $config{tongsuo_version} = "$config{tongsuo_major}.$config{tongsuo_minor}.$config{tongsuo_patch}"; $config{tongsuo_full_version} = "$config{tongsuo_version}$config{tongsuo_prerelease}"; -$config{tongsuo_smtc_info} = $version{TONGSUO_SMTC_INFO}; - die "erroneous version information in VERSION.dat: ", "$config{version}, $config{shlib_version}\n" unless (defined $version{MAJOR} @@ -404,6 +407,7 @@ my @dtls = qw(dtls1 dtls1_2); my @disablables = ( "acvp-tests", "afalgeng", + "atf_slibce", "asan", "asm", "async", @@ -474,6 +478,8 @@ my @disablables = ( "smtc-debug", "scrypt", "sctp", + "sdf-lib", + "sdf-lib-dynamic", "secure-memory", "shared", "siphash", @@ -605,6 +611,9 @@ our %disabled = ( # "what" => "comment" "ripemd" => "default", # RIPEMD has been removed "seed" => "default", # SEED has been removed "whirlpool" => "default", # Whirlpool has been removed + "atf_slibce" => "default", + "sdf-lib" => "default", + "sdf-lib-dynamic" => "default", ); # Note: => pair form used for aesthetics, not to truly make a hash table @@ -692,8 +701,8 @@ my @disable_cascades = ( "deprecated-3.0" => [ "engine", "srp" ], # SMTC does not support ct for now - # SMTC only support builtin module for now - sub { !$disabled{"smtc"}} => [ "ct", "module" ], + sub { !$disabled{"smtc"}} => [ "ct" ], + "sdf-lib" => [ "sdf-lib-dynamic" ], ); # Avoid protocol support holes. Also disable all versions below N, if version @@ -811,7 +820,7 @@ my %cmdvars = (); # Stores FOO='blah' type arguments my %unsupported_options = (); my %deprecated_options = (); # If you change this, update apps/version.c -my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom rtc); +my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom rtcode rtmem rtsock); my @seed_sources = (); while (@argvcopy) { @@ -929,6 +938,10 @@ while (@argvcopy) { delete $disabled{"zlib"}; } + elsif ($1 eq "sdf-lib-dynamic") + { + delete $disabled{"sdf-lib"}; + } my $algo = $1; delete $disabled{$algo}; @@ -1026,6 +1039,18 @@ while (@argvcopy) push @seed_sources, $x; } } + elsif (/^--with-atf_slibce-lib=(.*)$/) + { + $withargs{atf_slibce_lib}=$1; + } + elsif (/^--with-sdf-lib=(.*)$/) + { + $withargs{sdf_lib}=$1; + } + elsif (/^--with-sdf-include=(.*)$/) + { + $withargs{sdf_include}=$1; + } elsif (/^--fips-key=(.*)$/) { $user{FIPSKEY}=lc($1); @@ -1036,15 +1061,25 @@ while (@argvcopy) die "FIPS key too long (64 bytes max)\n" if length $1 > 64; } - elsif (/^--smtc-key=(.*)$/) + elsif (/^--smtc-pubkey=(.*)$/) { - $user{SMTCKEY}=lc($1); - die "Non-hex character in SMTC key\n" - if $user{SMTCKEY} =~ /[^a-f0-9]/; - die "SMTC key must have even number of characters\n" - if length $1 & 1; - die "SMTC key too long (64 bytes max)\n" - if length $1 > 64; + open my $fh, "<", $1 or die "Can't open $1: $!\n"; + $user{SMTCPUBKEY} = do { local $/; <$fh> }; + close $fh; + chomp $user{SMTCPUBKEY}; + $user{SMTCPUBKEY} =~ s|\n|\\n|g; + } + elsif (/^--smtc-passwd=(.*)$/) + { + $user{SMTCPASSWD} = $1; + die "Invalid character in SMTC password (A-Z, a-z, 0-9)\n" + if $user{SMTCPASSWD} =~ /[^A-Za-z0-9]/; + die "Invalid SMTC password length (8 ~ 64 bytes)\n" + if length $1 < 8 or length $1 > 64; + } + elsif (/^--smtc-info=(.*)$/) + { + $config{tongsuo_smtc_info} = $1; } elsif (/^--banner=(.*)$/) { diff --git a/VERSION.dat b/VERSION.dat index 3b6f7ac66..d83daf21b 100644 --- a/VERSION.dat +++ b/VERSION.dat @@ -8,5 +8,4 @@ SHLIB_VERSION=3 TONGSUO_MAJOR=8 TONGSUO_MINOR=5 TONGSUO_PATCH=0 -TONGSUO_PRE_RELEASE_TAG=dev -TONGSUO_SMTC_INFO= +TONGSUO_PRE_RELEASE_TAG=dev \ No newline at end of file diff --git a/apps/build.info b/apps/build.info index 56ac5a3a3..32f955474 100644 --- a/apps/build.info +++ b/apps/build.info @@ -75,6 +75,10 @@ IF[{- !$disabled{'sm2_threshold'} -}] $OPENSSLSRC=$OPENSSLSRC sm2_threshold.c ENDIF +IF[{- !$disabled{'sdf-lib'} -}] + $OPENSSLSRC=$OPENSSLSRC sdf.c +ENDIF + IF[{- !$disabled{apps} -}] PROGRAMS=openssl SOURCE[openssl]=$INITSRC $OPENSSLSRC diff --git a/apps/mod.c b/apps/mod.c index 65cf4220e..575667a45 100644 --- a/apps/mod.c +++ b/apps/mod.c @@ -6,35 +6,45 @@ * in the file LICENSE in the source distribution or at * https://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt */ -#include +#include "internal/deprecated.h" +#include +#include +#include #include "apps.h" #include "progs.h" #include #include #include +#include #include #include #include #include +#include #include #include "internal/smtc_names.h" #include "../providers/smtc/smtckey.h" -#define PASSWD_BUF_SIZE 1024 -#define BUFSIZE 4096 +#define BUFSIZE 4096 +#define SMTC_AUTH_PASSWD_MAX_LEN 64 +#define SMTC_AUTH_KEY_LEN 64 +#define SMTC_AUTH_SALT_LEN 64 typedef struct { const char *section; const char *module_path; + char *sig; + const char *kek; + const char *eng; + const char *syslog; + char *key; + char *salt; + const char *rand_poweron_test; #ifndef OPENSSL_NO_SMTC_DEBUG - int verify_pass; + const char *verify_sig; + const char *verify_pass; #endif - int show_selftest; - unsigned char admin_salt[SM3_DIGEST_LENGTH]; - unsigned char admin_pass[SM3_DIGEST_LENGTH]; - unsigned char module_mac[EVP_MAX_MD_SIZE]; - size_t module_mac_len; } SMTC_CONF; typedef enum OPTION_choice { @@ -42,82 +52,131 @@ typedef enum OPTION_choice { OPT_EOF = 0, OPT_HELP, OPT_TEST, + OPT_RESET, OPT_MODULE, OPT_PROV_NAME, - OPT_SECTION_NAME, + OPT_SIGFILE, + OPT_STATUS, + OPT_INSTALL, + OPT_KEK, + OPT_ENGINE, + OPT_PASS, OPT_OUT, - OPT_SHOW_SELFTEST, #ifndef OPENSSL_NO_SMTC_DEBUG - OPT_NO_PASS, + OPT_NO_VERIFY, + OPT_NO_AUTH, + OPT_NO_RAND_POWERON_TEST, #endif - OPT_R_ENUM } OPTION_CHOICE; const OPTIONS mod_options[] = { OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + {"install", OPT_INSTALL, '-', "Install module, generate config file"}, {"test", OPT_TEST, '-', "Self test"}, - {"module", OPT_MODULE, '<', "File name of the provider module"}, - {"provider_name", OPT_PROV_NAME, 's', "SMTC provider name"}, - {"section_name", - OPT_SECTION_NAME, - 's', - "SMTC Provider config section name (optional)"}, - {"show_selftest", OPT_SHOW_SELFTEST, '-', "Show self test"}, + {"status", OPT_STATUS, '-', "Display the status of the module"}, + {"reset", OPT_RESET, '-', "Reset module, clear salt and password"}, + {"module", OPT_MODULE, 's', "File path of the module"}, + {"provider_name", OPT_PROV_NAME, 's', "Provider name"}, + {"pass", OPT_PASS, '-', "Setup password"}, + {"kek", OPT_KEK, 's', "The key for encrypting HMAC key"}, + {"engine", OPT_ENGINE, 's', "Use the engine e, possibly a hardware device"}, #ifndef OPENSSL_NO_SMTC_DEBUG - {"no_pass", OPT_NO_PASS, '-', "Do not setup password"}, + {"no_verify", OPT_NO_VERIFY, '-', "Do not verify the integrity of the software"}, + {"no_auth", OPT_NO_AUTH, '-', "No authentication required for user login"}, + {"no_rand_poweron_test", OPT_NO_RAND_POWERON_TEST, '-', "No random poweron test"}, #endif + + OPT_SECTION("Input"), + {"sigfile", OPT_SIGFILE, '<', "Signature file"}, + OPT_SECTION("Output"), {"out", OPT_OUT, '>', "Output config file, used when generating"}, - {NULL}}; -static int setup_password(unsigned char *admin_salt, unsigned char *admin_pass) +static int check_passwd(const char *passwd, size_t len) { - int ret = 0; - char passwd[PASSWD_BUF_SIZE]; - EVP_MD_CTX *mctx = NULL; + size_t i; + int upper = 0, lower = 0, digit = 0; - if (EVP_read_pw_string(passwd, sizeof(passwd), "Setup password: ", 1) != 0) - goto end; + if (len < 8 || len > 64) + return 0; - if (RAND_bytes(admin_salt, SM3_DIGEST_LENGTH) <= 0) - goto end; + for (i = 0; i < len; i++) { + if (isupper(passwd[i])) + upper = 1; + else if (islower(passwd[i])) + lower = 1; + else if (isdigit(passwd[i])) + digit = 1; + else + return 0; + } - if ((mctx = EVP_MD_CTX_new()) == NULL - || !EVP_DigestInit_ex(mctx, EVP_sm3(), NULL) - || !EVP_DigestUpdate(mctx, admin_salt, SM3_DIGEST_LENGTH) - || !EVP_DigestUpdate(mctx, passwd, strlen(passwd)) - || !EVP_DigestFinal_ex(mctx, admin_pass, NULL)) - goto end; + if ((upper & lower & digit) == 0) + return 0; - ret = 1; -end: - EVP_MD_CTX_free(mctx); - return ret; + return 1; } -static int do_mac(EVP_MAC_CTX *ctx, unsigned char *tmp, BIO *in, - unsigned char *out, size_t *out_len) + +static int setup_password(EVP_PKEY *kek, unsigned char *auth_salt, + unsigned char **auth_key, size_t *auth_key_len) { - int ret = 0; - int i; - size_t outsz = *out_len; + int ok = 0; + EVP_PKEY_CTX *ctx = NULL; + char passwd[SMTC_AUTH_PASSWD_MAX_LEN + 1] = {0}; + unsigned char key[SMTC_AUTH_KEY_LEN]; + unsigned char *enc_key = NULL; + size_t outlen; + + if (EVP_read_pw_string_min(passwd, 8, sizeof(passwd) - 1, + "Setup password: ", 1) != 0) + goto end; + + if (!check_passwd(passwd, strlen(passwd))) { + BIO_printf(bio_err, "Passwords should be 8-64 characters in length and" + "must contain number, uppercase and lowercase letter\n"); + goto end; + } - if (!EVP_MAC_init(ctx, NULL, 0, NULL)) - goto err; - if (EVP_MAC_CTX_get_mac_size(ctx) > outsz) + if (RAND_bytes(auth_salt, SMTC_AUTH_SALT_LEN) != 1) goto end; - while ((i = BIO_read(in, (char *)tmp, BUFSIZE)) != 0) { - if (i < 0 || !EVP_MAC_update(ctx, tmp, i)) - goto err; + + if (PKCS5_PBKDF2_HMAC(passwd, strlen(passwd), auth_salt, SMTC_AUTH_SALT_LEN, + 10000, EVP_sm3(), SMTC_AUTH_KEY_LEN, key) != 1) + goto end; + + if (kek) { + ctx = EVP_PKEY_CTX_new(kek, NULL); + if (ctx == NULL) + goto end; + + if (EVP_PKEY_encrypt_init(ctx) != 1) + goto end; + + if (EVP_PKEY_encrypt(ctx, NULL, &outlen, key, SMTC_AUTH_KEY_LEN) != 1) + goto end; + + enc_key = OPENSSL_malloc(outlen); + + if (EVP_PKEY_encrypt(ctx, enc_key, &outlen, key, SMTC_AUTH_KEY_LEN) != 1 + ) { + BIO_printf(bio_err, "Failed to encrypt auth key\n"); + goto end; + } + + *auth_key = enc_key; + enc_key = NULL; + *auth_key_len = outlen; } + + ok = 1; + OSSL_syslog(LOG_NOTICE, "Setup password success\n"); end: - if (!EVP_MAC_final(ctx, out, out_len, outsz)) - goto err; - ret = 1; -err: - return ret; + EVP_PKEY_CTX_free(ctx); + OPENSSL_free(enc_key); + return ok; } static int write_config_header(BIO *out, const char *prov_name, @@ -130,20 +189,6 @@ static int write_config_header(BIO *out, const char *prov_name, && BIO_printf(out, "%s = %s\n\n", prov_name, section); } -static int print_hex(BIO *bio, const char *label, const unsigned char *val, - size_t len) -{ - int ret; - char *hexstr = NULL; - - hexstr = OPENSSL_buf2hexstr(val, (long)len); - if (hexstr == NULL) - return 0; - ret = BIO_printf(bio, "%s = %s\n", label, hexstr); - OPENSSL_free(hexstr); - return ret; -} - /* * Outputs a smtc related config file. * Returns 1 if the config file is written otherwise it returns 0 on error. @@ -156,34 +201,46 @@ static int write_config_smtc_section(BIO *out, SMTC_CONF *sc) || BIO_printf(out, "activate = 1\n") <= 0 || BIO_printf(out, "%s = %s\n", OSSL_PROV_SMTC_PARAM_MODULE_PATH, sc->module_path) <= 0 - || !print_hex(out, OSSL_PROV_SMTC_PARAM_MODULE_MAC, sc->module_mac, - sc->module_mac_len)) + || BIO_printf(out, "%s = %s\n", OSSL_PROV_SMTC_PARAM_MODULE_SIG, + sc->sig) <= 0) goto end; - if (sc->show_selftest) { - if (BIO_printf(out, "%s = 1\n", OSSL_PROV_SMTC_PARAM_SHOW_SELFTEST) - <= 0) - goto end; - } else { - if (BIO_printf(out, "%s = 0\n", OSSL_PROV_SMTC_PARAM_SHOW_SELFTEST) - <= 0) - goto end; - } + if (sc->kek && BIO_printf(out, "%s = %s\n", OSSL_PROV_SMTC_PARAM_AUTH_KEK, + sc->kek) <= 0) + goto end; -#ifndef OPENSSL_NO_SMTC_DEBUG - if (sc->verify_pass == 0) { - if (BIO_printf(out, "%s = 0\n", OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_PASS) - <= 0) - goto end; - } else { -#endif - if (!print_hex(out, OSSL_PROV_SMTC_PARAM_ADMIN_SALT, sc->admin_salt, - sizeof(sc->admin_salt)) - || !print_hex(out, OSSL_PROV_SMTC_PARAM_ADMIN_PASS, - sc->admin_pass, sizeof(sc->admin_pass))) + if (sc->eng && BIO_printf(out, "%s = %s\n", OSSL_PROV_SMTC_PARAM_ENGINE, + sc->eng) <= 0) + goto end; + + if (sc->key && BIO_printf(out, "%s = %s\n", OSSL_PROV_SMTC_PARAM_AUTH_KEY, + sc->key) <= 0) + goto end; + + if (sc->salt && BIO_printf(out, "%s = %s\n", OSSL_PROV_SMTC_PARAM_AUTH_SALT, + sc->salt) <= 0) + goto end; + + if (sc->syslog && BIO_printf(out, "%s = %s\n", OSSL_PROV_SMTC_PARAM_SYSLOG, + sc->syslog) <= 0) + goto end; + + if (sc->rand_poweron_test + && BIO_printf(out, "%s = %s\n", + OSSL_PROV_SMTC_PARAM_RANDOMNESS_POWERON_TEST, + sc->rand_poweron_test) <= 0) goto end; + #ifndef OPENSSL_NO_SMTC_DEBUG - } + if (sc->verify_sig && BIO_printf(out, "%s = %s\n", + OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_SIG, + sc->verify_sig) <= 0) + goto end; + + if (sc->verify_pass && BIO_printf(out, "%s = %s\n", + OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_PASS, + sc->verify_pass) <= 0) + goto end; #endif ret = 1; @@ -219,39 +276,45 @@ static CONF *generate_config_and_load(const char *prov_name, SMTC_CONF *sc) int mod_main(int argc, char **argv) { - int ret = 1; -#ifndef OPENSSL_NO_SMTC_DEBUG - int no_pass = 0; -#endif + int ret = 1, ok = 0, reset = 0, i, install = 0, pass = 0; char *prog; + unsigned char *sig = NULL, *auth_key = NULL; + int siglen = 0; + const char *sigfile = NULL, *kek_file = NULL; OPTION_CHOICE o; - int self_test = 0; - BIO *module_bio = NULL, *fout = NULL; - char *out_fname = NULL; - EVP_MAC *mac = NULL; - const char *mac_name = "HMAC"; - const char *prov_name = "smtc"; - SMTC_CONF sc = { - .section = "smtc_sect", - .show_selftest = 0, -#ifndef OPENSSL_NO_SMTC_DEBUG - .verify_pass = 1, + unsigned char buf[BUFSIZE]; + int self_test = 0, get_status = 0, status = 0; + BIO *module_bio = NULL, *fout = NULL, *kek_bio = NULL; +#ifndef OPENSSL_NO_ATF_SLIBCE + const char *eng_name = "atf_slibce"; +#else + const char *eng_name = NULL; #endif - }; - STACK_OF(OPENSSL_STRING) *opts = NULL; - unsigned char *read_buffer = NULL; - EVP_MAC_CTX *ctx = NULL, *ctx2 = NULL; + const char *prov_name = "smtc", *sec_name = "smtc_sect"; + const char *conf_file = OPENSSL_info(OPENSSL_INFO_SMTC_MODULE_CONF); + const char *auth_kek = OPENSSL_info(OPENSSL_INFO_SMTC_AUTH_KEK); + SMTC_CONF sc; CONF *conf = NULL; + long eline; + EVP_PKEY *kek = NULL; + ENGINE *engine = NULL; + unsigned char auth_salt[SMTC_AUTH_SALT_LEN]; + size_t auth_key_len; + OSSL_PROVIDER *prov = NULL; +#ifndef OPENSSL_NO_SMTC_DEBUG + int no_verify = 0, no_auth = 0, no_rand_poweron_test = 0; +#endif - if ((opts = sk_OPENSSL_STRING_new_null()) == NULL) - goto end; + memset(&sc, 0, sizeof(sc)); + sc.section = sec_name; + sc.syslog = "1"; prog = opt_init(argc, argv, mod_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: - opthelp: +opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto cleanup; case OPT_HELP: @@ -261,155 +324,275 @@ int mod_main(int argc, char **argv) case OPT_TEST: self_test = 1; break; + case OPT_STATUS: + get_status = 1; + break; + case OPT_RESET: + reset = 1; + break; case OPT_PROV_NAME: prov_name = opt_arg(); break; case OPT_MODULE: sc.module_path = opt_arg(); break; - case OPT_SECTION_NAME: - sc.section = opt_arg(); + case OPT_PASS: + pass = 1; break; - case OPT_SHOW_SELFTEST: - sc.show_selftest = 1; + case OPT_SIGFILE: + sigfile = opt_arg(); break; -#ifndef OPENSSL_NO_SMTC_DEBUG - case OPT_NO_PASS: - no_pass = 1; - sc.verify_pass = 0; + case OPT_INSTALL: + install = 1; break; -#endif case OPT_OUT: - out_fname = opt_arg(); + conf_file = opt_arg(); break; - case OPT_R_CASES: - if (!opt_rand(o)) - goto end; + case OPT_KEK: + kek_file = opt_arg(); + break; + case OPT_ENGINE: + eng_name = opt_arg(); + engine = setup_engine(eng_name, 1); + break; +#ifndef OPENSSL_NO_SMTC_DEBUG + case OPT_NO_VERIFY: + no_verify = 1; break; + case OPT_NO_AUTH: + no_auth = 1; + break; + case OPT_NO_RAND_POWERON_TEST: + no_rand_poweron_test = 1; + break; +#endif } } + argc = opt_num_rest(); - argv = opt_rest(); + if (argc != 0) + goto opthelp; - if (self_test) { - if (OSSL_PROVIDER_available(app_get0_libctx(), "smtc")) { - OSSL_PROVIDER *prov = OSSL_PROVIDER_load(app_get0_libctx(), "smtc"); - if (prov == NULL) { - BIO_printf(bio_err, "Failed to load SMTC provider\n"); + if (reset || self_test || get_status) { + prov = OSSL_PROVIDER_load(app_get0_libctx(), "smtc"); + if (prov == NULL) { + BIO_printf(bio_err, "Failed to load SMTC provider\n"); + goto end; + } + + if (reset) { + if (OSSL_PROVIDER_reset(prov) != 1) { + BIO_printf(bio_err, "Failed to reset SMTC provider\n"); goto end; } + } + if (self_test) { if (OSSL_PROVIDER_self_test(prov) != 1) { - OSSL_PROVIDER_unload(prov); - BIO_printf(bio_err, "SMTC provider self test failed\n"); + BIO_printf(bio_err, "self test failed\n"); goto end; } - OSSL_PROVIDER_unload(prov); + BIO_printf(bio_out, "self test success\n"); + } + + if (get_status) { + status = OSSL_PROVIDER_status(prov); - ret = 0; - goto end; - } else { - BIO_printf(bio_err, "SMTC provider not available\n"); - goto end; + BIO_printf(bio_out, "status: %sactive\n", status ? "" : "in"); } + + ok = 1; + goto end; } + if (install) { + if (sigfile) { + BIO *sigbio = BIO_new_file(sigfile, "rb"); + + if (sigbio == NULL) { + BIO_printf(bio_err, "Can't open signature file %s\n", sigfile); + goto end; + } + siglen = bio_to_mem(&sig, 4096, sigbio); + BIO_free(sigbio); + + if (siglen < 0) { + BIO_printf(bio_err, "Error reading signature data\n"); + goto end; + } + + sc.sig = OPENSSL_buf2hexstr(sig, siglen); + if (sc.sig == NULL) + goto end; + } + #ifndef OPENSSL_NO_SMTC_DEBUG - if (!no_pass) + if (no_verify) + sc.verify_sig = "0"; + + if (no_auth) + sc.verify_pass = "0"; + + if (no_rand_poweron_test) + sc.rand_poweron_test = "0"; #endif - if (!setup_password(sc.admin_salt, sc.admin_pass)) - goto end; + sc.eng = eng_name; - if (sc.module_path == NULL) - goto opthelp; + if (sc.module_path == NULL) + goto opthelp; - if (!sk_OPENSSL_STRING_push(opts, "digest:SM3")) - goto end; - if (!sk_OPENSSL_STRING_push(opts, "hexkey:" SMTC_KEY_STRING)) - goto end; + if (kek_file) { + kek_bio = bio_open_default(kek_file, 'r', FORMAT_TEXT); + if (kek_bio == NULL) { + BIO_printf(bio_err, "Failed to open file %s\n", kek_file); + goto end; + } - module_bio = bio_open_default(sc.module_path, 'r', FORMAT_BINARY); - if (module_bio == NULL) { - BIO_printf(bio_err, "Failed to open module file\n"); - goto end; - } + fout = bio_open_default(auth_kek, 'w', FORMAT_TEXT); + if (fout == NULL) { + BIO_printf(bio_err, "Failed to open file %s\n", auth_kek); + goto end; + } - read_buffer = app_malloc(BUFSIZE, "I/O buffer"); - if (read_buffer == NULL) - goto end; + while (BIO_pending(kek_bio) || !BIO_eof(kek_bio)) { + ret = BIO_read(kek_bio, buf, BUFSIZE); + + if (ret < 0) { + BIO_printf(bio_err, "Read Error in '%s'\n", kek_file); + ERR_print_errors(bio_err); + goto end; + } + if (ret == 0) + break; + + if (BIO_write(fout, buf, ret) != ret) { + BIO_printf(bio_err, "Write Error in '%s'\n", auth_kek); + ERR_print_errors(bio_err); + goto end; + } + } - mac = EVP_MAC_fetch(app_get0_libctx(), mac_name, app_get0_propq()); - if (mac == NULL) { - BIO_printf(bio_err, "Unable to get MAC of type %s\n", mac_name); - goto end; - } + sc.kek = auth_kek; + } + + conf = generate_config_and_load(prov_name, &sc); + if (conf == NULL) + goto end; + + fout = bio_open_default(conf_file, 'w', FORMAT_TEXT); + if (fout == NULL) { + BIO_printf(bio_err, "Failed to open file\n"); + goto end; + } + if (!write_config_smtc_section(fout, &sc)) + goto end; + + BIO_printf(bio_err, "INSTALL PASSED\n"); - ctx = EVP_MAC_CTX_new(mac); - if (ctx == NULL) { - BIO_printf(bio_err, "Unable to create MAC CTX for module check\n"); + ok = 1; goto end; } - if (opts != NULL) { - int ok = 1; - OSSL_PARAM *params - = app_params_new_from_opts(opts, EVP_MAC_settable_ctx_params(mac)); + if (pass) { + conf = NCONF_new(NCONF_default()); - if (params == NULL) + if (NCONF_load(conf, conf_file, &eline) != 1) { + BIO_printf(bio_err, "Failed to load config file %s\n", conf_file); goto end; + } + + STACK_OF(CONF_VALUE) *sect = NCONF_get_section(conf, sec_name); + for (i = 0; i < sk_CONF_VALUE_num(sect); i++) { + CONF_VALUE *cv = sk_CONF_VALUE_value(sect, i); + + if (strcmp(cv->name, OSSL_PROV_SMTC_PARAM_MODULE_PATH) == 0) + sc.module_path = cv->value; + else if (strcmp(cv->name, OSSL_PROV_SMTC_PARAM_MODULE_SIG) == 0) + sc.sig = cv->value; + else if (strcmp(cv->name, OSSL_PROV_SMTC_PARAM_AUTH_KEK) == 0) + sc.kek = cv->value; + else if (strcmp(cv->name, OSSL_PROV_SMTC_PARAM_ENGINE) == 0) + sc.eng = cv->value; + else if (strcmp(cv->name, OSSL_PROV_SMTC_PARAM_SYSLOG) == 0) + sc.syslog = cv->value; + else if (strcmp(cv->name, + OSSL_PROV_SMTC_PARAM_RANDOMNESS_POWERON_TEST) == 0) + sc.rand_poweron_test = cv->value; + } - if (!EVP_MAC_CTX_set_params(ctx, params)) { - BIO_printf(bio_err, "MAC parameter error\n"); - ERR_print_errors(bio_err); - ok = 0; + if (sc.eng) { + engine = ENGINE_by_id(sc.eng); + if (engine == NULL) { + BIO_printf(bio_err, "Failed to load engine %s\n", sc.eng); + goto end; + } } - app_params_free(params); - if (!ok) + + kek = load_key(sc.kek, FORMAT_PEM, 0, NULL, engine, + "key encryption key"); + if (kek == NULL) goto end; - } - ctx2 = EVP_MAC_CTX_dup(ctx); - if (ctx2 == NULL) { - BIO_printf(bio_err, "Unable to create MAC CTX for install indicator\n"); - goto end; - } + if (!setup_password(kek, auth_salt, &auth_key, &auth_key_len)) { + BIO_printf(bio_err, "Failed to setup password!\n"); + goto end; + } - sc.module_mac_len = sizeof(sc.module_mac); - if (!do_mac(ctx, read_buffer, module_bio, sc.module_mac, &sc.module_mac_len)) - goto end; + sc.key = OPENSSL_buf2hexstr(auth_key, auth_key_len); + if (sc.key == NULL) + goto end; - conf = generate_config_and_load(prov_name, &sc); - if (conf == NULL) - goto end; + sc.salt = OPENSSL_buf2hexstr(auth_salt, sizeof(auth_salt)); + if (sc.salt == NULL) + goto end; - fout = out_fname == NULL ? dup_bio_out(FORMAT_TEXT) - : bio_open_default(out_fname, 'w', FORMAT_TEXT); - if (fout == NULL) { - BIO_printf(bio_err, "Failed to open file\n"); - goto end; - } - if (!write_config_smtc_section(fout, &sc)) - goto end; + fout = bio_open_default(conf_file, 'w', FORMAT_TEXT); + if (fout == NULL) { + BIO_printf(bio_err, "Failed to open file %s\n", conf_file); + goto end; + } - BIO_printf(bio_err, "INSTALL PASSED\n"); + if (!write_config_smtc_section(fout, &sc)) { + BIO_printf(bio_err, "Failed to write config file %s\n", conf_file); + goto end; + } + } - ret = 0; + ok = 1; end: - if (ret == 1) + if (ok == 0) { ERR_print_errors(bio_err); + ret = 1; + } else { + /* Exit the process after reset module */ + if (reset) + ret = -1; + else + ret = 0; + } cleanup: + if (install) + OPENSSL_free(sc.sig); + + if (prov) + OSSL_PROVIDER_unload(prov); + + release_engine(engine); + EVP_PKEY_free(kek); + OPENSSL_free(auth_key); + OPENSSL_free(sig); + OPENSSL_free(sc.key); + OPENSSL_free(sc.salt); BIO_free(fout); BIO_free(module_bio); - sk_OPENSSL_STRING_free(opts); - EVP_MAC_free(mac); - EVP_MAC_CTX_free(ctx2); - EVP_MAC_CTX_free(ctx); - OPENSSL_free(read_buffer); + BIO_free(kek_bio); + if (conf != NULL) { NCONF_free(conf); CONF_modules_unload(1); } + return ret; } diff --git a/apps/openssl.c b/apps/openssl.c index e23515772..293a698f0 100644 --- a/apps/openssl.c +++ b/apps/openssl.c @@ -28,6 +28,9 @@ #include "apps.h" #include "progs.h" +/* Special sentinel to exit the program. */ +#define EXIT_THE_PROGRAM (-1) + /* * The LHASH callbacks ("hash" & "cmp") have been replaced by functions with * the base prototypes (we cast each variable inside the function to the @@ -236,11 +239,12 @@ int main(int argc, char *argv[]) { FUNCTION f, *fp; LHASH_OF(FUNCTION) *prog = NULL; - char *pname; - const char *fname; + char *p, *pname; + char buf[1024]; + const char *prompt, *fname; ARGS arg; int global_help = 0; - int ret = 0; + int first, n, i, ret = 0; arg.argv = NULL; arg.size = 0; @@ -289,11 +293,81 @@ int main(int argc, char *argv[]) argv[0] = pname; } - /* If there's a command, run with that, otherwise "help". */ - ret = argc == 0 || global_help - ? do_cmd(prog, 1, help_argv) - : do_cmd(prog, argc, argv); + if (global_help) { + ret = do_cmd(prog, 1, help_argv); + goto end; + } + + if (argc != 0) { + ret = do_cmd(prog, argc, argv); + goto end; + } + + /* interactive mode */ + for (;;) { + ret = 0; + /* Read a line, continue reading if line ends with \ */ + for (p = buf, n = sizeof(buf), i = 0, first = 1; n > 0; first = 0) { + prompt = first ? "Tongsuo> " : "> "; + p[0] = '\0'; +#ifndef READLINE + fputs(prompt, stdout); + fflush(stdout); + if (!fgets(p, n, stdin)) + goto end; + if (p[0] == '\0') + goto end; + i = strlen(p); + if (i <= 1) + break; + if (p[i - 2] != '\\') + break; + i -= 2; + p += i; + n -= i; +#else + { + extern char *readline(const char *); + extern void add_history(const char *cp); + char *text; + + text = readline(prompt); + if (text == NULL) + goto end; + i = strlen(text); + if (i == 0 || i > n) + break; + if (text[i - 1] != '\\') { + p += strlen(strcpy(p, text)); + free(text); + add_history(buf); + break; + } + + text[i - 1] = '\0'; + p += strlen(strcpy(p, text)); + free(text); + n -= i; + } +#endif + } + if (!chopup_args(&arg, buf)) { + BIO_printf(bio_err, "Can't parse (no memory?)\n"); + break; + } + + ret = do_cmd(prog, arg.argc, arg.argv); + if (ret == EXIT_THE_PROGRAM) { + ret = 0; + goto end; + } + if (ret != 0) + BIO_printf(bio_err, "error in %s\n", arg.argv[0]); + (void)BIO_flush(bio_out); + (void)BIO_flush(bio_err); + } + ret = 1; end: OPENSSL_free(default_config_file); lh_FUNCTION_free(prog); @@ -396,28 +470,6 @@ static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]) if (argc <= 0 || argv[0] == NULL) return 0; -#ifdef SMTC_MODULE - /* Every app should run smtc self test firstly except mod, version and help */ - if (strcmp(argv[0], "mod") != 0 - && strcmp(argv[0], "version") != 0 - && strcmp(argv[0], "help") != 0) { - if (OSSL_PROVIDER_available(app_get0_libctx(), "smtc")) { - OSSL_PROVIDER *prov = OSSL_PROVIDER_load(app_get0_libctx(), "smtc"); - if (prov == NULL) { - BIO_printf(bio_err, "Failed to load smtc provider\n"); - return 0; - } - - if (OSSL_PROVIDER_self_test(prov) != 1) { - OSSL_PROVIDER_unload(prov); - BIO_printf(bio_err, "smtc self test failed\n"); - return 0; - } - - OSSL_PROVIDER_unload(prov); - } - } -#endif memset(&f, 0, sizeof(f)); f.name = argv[0]; fp = lh_FUNCTION_retrieve(prog, &f); @@ -451,6 +503,11 @@ static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]) return 1; } + if (strcmp(argv[0], "quit") == 0 || strcmp(argv[0], "q") == 0 || + strcmp(argv[0], "exit") == 0 || strcmp(argv[0], "bye") == 0) + /* Special value to mean "exit the program. */ + return EXIT_THE_PROGRAM; + BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n", argv[0]); return 1; diff --git a/apps/rand.c b/apps/rand.c index cbf495d5b..47be38976 100644 --- a/apps/rand.c +++ b/apps/rand.c @@ -17,10 +17,12 @@ #include #include #include +#include +#include "crypto/rand.h" typedef enum OPTION_choice { OPT_COMMON, - OPT_OUT, OPT_ENGINE, OPT_BASE64, OPT_HEX, + OPT_OUT, OPT_ENGINE, OPT_BASE64, OPT_HEX, OPT_ENTROPY, OPT_SOURCE, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; @@ -37,6 +39,8 @@ const OPTIONS rand_options[] = { {"out", OPT_OUT, '>', "Output file"}, {"base64", OPT_BASE64, '-', "Base64 encode output"}, {"hex", OPT_HEX, '-', "Hex encode output"}, + {"entropy", OPT_ENTROPY, '-', "Output entropy instead of random data"}, + {"source", OPT_SOURCE, 's', "Specify the entropy source"}, OPT_R_OPTIONS, OPT_PROV_OPTIONS, @@ -46,13 +50,48 @@ const OPTIONS rand_options[] = { {NULL} }; +static int opt_rand_source(const char *name) +{ + int ret = 0; + + if (strcmp(name, "getrandom") == 0) + ret = RAND_ENTROPY_SOURCE_GETRANDOM; + else if (strcmp(name, "devrandom") == 0) + ret = RAND_ENTROPY_SOURCE_DEVRANDOM; + else if (strcmp(name, "rdtsc") == 0) + ret = RAND_ENTROPY_SOURCE_RDTSC; + else if (strcmp(name, "rdcpu") == 0) + ret = RAND_ENTROPY_SOURCE_RDCPU; + else if (strcmp(name, "egd") == 0) + ret = RAND_ENTROPY_SOURCE_EGD; + else if (strcmp(name, "bcryptgenrandom") == 0) + ret = RAND_ENTROPY_SOURCE_BCRYPTGENRANDOM; + else if (strcmp(name, "cryptgenrandom_def_prov") == 0) + ret = RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_DEF_PROV; + else if (strcmp(name, "cryptgenrandom_intel_prov") == 0) + ret = RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_INTEL_PROV; + else if (strcmp(name, "rtcode") == 0) + ret = RAND_ENTROPY_SOURCE_RTCODE; + else if (strcmp(name, "rtmem") == 0) + ret = RAND_ENTROPY_SOURCE_RTMEM; + else if (strcmp(name, "rtsock") == 0) + ret = RAND_ENTROPY_SOURCE_RTSOCK; + else + BIO_printf(bio_err, "Unknown entropy source '%s'\n", name); + + return ret; +} + int rand_main(int argc, char **argv) { ENGINE *e = NULL; BIO *out = NULL; + int source = 0; char *outfile = NULL, *prog; OPTION_CHOICE o; - int format = FORMAT_BINARY, i, num = -1, r, ret = 1; + unsigned char *ent_buf = NULL, *p; + int format = FORMAT_BINARY, i, num = -1, r, ret = 1, entropy = 0; + size_t ent_len = 0; prog = opt_init(argc, argv, rand_options); while ((o = opt_next()) != OPT_EOF) { @@ -82,6 +121,13 @@ int rand_main(int argc, char **argv) case OPT_HEX: format = FORMAT_TEXT; break; + case OPT_ENTROPY: + entropy = 1; + break; + case OPT_SOURCE: + source |= opt_rand_source(opt_arg()); + RAND_set_entropy_source(source); + break; case OPT_PROV_CASES: if (!opt_provider(o)) goto end; @@ -114,24 +160,45 @@ int rand_main(int argc, char **argv) } while (num > 0) { - unsigned char buf[4096]; + /* When getting entropy from EGD, buf size must be less than 256 */ + unsigned char buf[255]; int chunk; chunk = num; if (chunk > (int)sizeof(buf)) chunk = sizeof(buf); - r = RAND_bytes(buf, chunk); - if (r <= 0) - goto end; + + if (entropy) { + ent_buf = TSAPI_GetEntropy(chunk, &ent_len); + if (ent_buf == NULL) + goto end; + } else { + r = RAND_bytes(buf, chunk); + if (r <= 0) + goto end; + } + + if (entropy) { + p = ent_buf; + chunk = ent_len; + } else { + p = buf; + } + if (format != FORMAT_TEXT) { - if (BIO_write(out, buf, chunk) != chunk) + if (BIO_write(out, p, chunk) != chunk) goto end; } else { for (i = 0; i < chunk; i++) - if (BIO_printf(out, "%02x", buf[i]) != 2) + if (BIO_printf(out, "%02x", p[i]) != 2) goto end; } num -= chunk; + + if (entropy) { + TSAPI_FreeEntropy(ent_buf, ent_len); + ent_buf = NULL; + } } if (format == FORMAT_TEXT) BIO_puts(out, "\n"); @@ -145,5 +212,6 @@ int rand_main(int argc, char **argv) ERR_print_errors(bio_err); release_engine(e); BIO_free_all(out); + TSAPI_FreeEntropy(ent_buf, ent_len); return ret; } diff --git a/apps/s_server.c b/apps/s_server.c index 088e403ab..e6243ed9d 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -1898,8 +1898,6 @@ int s_server_main(int argc, char *argv[]) if (s_key_file == NULL) s_key_file = s_cert_file; - - if (!load_excert(&exc)) goto end; diff --git a/apps/sdf.c b/apps/sdf.c new file mode 100644 index 000000000..475c1db95 --- /dev/null +++ b/apps/sdf.c @@ -0,0 +1,543 @@ +/* + * Copyright 2024 The Tongsuo 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://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt + */ +#include "internal/deprecated.h" +#include +#include +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" + +typedef enum OPTION_choice { + OPT_ERR = -1, + OPT_EOF = 0, + OPT_HELP, + OPT_IN, + OPT_INKEY, + OPT_INDEX, + OPT_GENSM2KEY, + OPT_DELSM2KEY, + OPT_UPDATESM2KEY, + OPT_EXPORTSM2PUBKEY, + OPT_EXPORTSM2KEY, + OPT_EXPORTSM2KEYWITHEVLP, + OPT_IMPORTSM2KEY, + OPT_IMPORTSM2KEYWITHEVLP, + OPT_LOGIN, + OPT_ENCRYPT, + OPT_DECRYPT, + OPT_PEERKEY, + OPT_TYPE, + OPT_OUT, + OPT_KEYOUT, + OPT_DEKOUT, + OPT_INDEK, + OPT_IV, + OPT_ISK, + OPT_ISKTYPE, + OPT_ALGORITHM, +} OPTION_CHOICE; + +/* + * Examples: + * + * Encrypt data with SM4 key which is encrypted with ISK: + * sdf -encrypt -algorithm sm4-cbc -inkey sm4key.enc -isk index -isktype sm2 -iv aabbcc -in data.txt -out data.enc + * + * Generate SM2 key pair with the index: + * sdf -gensm2key -index 1 + * + * Delete SM2 key pair with the index: + * sdf -delsm2key -index 1 + * + * Update SM2 key pair with the index: + * sdf -updatesm2key -index 1 + * + * Encrypt data with SM2 key with the index: + * sdf -encrypt -algorithm sm2 -index 1 -in data.txt -out data.enc + * + * Import SM2 key with the index, sm2 key is encrypted by sm4 key(indek), + * sm4 key is encrypted by ISK, default is 0: + * sdf -importsm2keywithevlp -type enc -index 7 -inkey sm2_enc.keyenc -indek sm4.keyenc + * + * Export SM2 key with the index: + * sdf -exportsm2key -index 1 -keyout sm2key.pem + * + * Export SM2 public key with the index: + * sdf -exportsm2pubkey -index 1 -keyout sm2pubkey.pem + */ + +const OPTIONS sdf_options[] = { + OPT_SECTION("General"), + {"help", OPT_HELP, '-', "Display this summary"}, + {"encrypt", OPT_ENCRYPT, '-', "Encrypt file"}, + {"decrypt", OPT_DECRYPT, '-', "Decrypt file"}, + {"importsm2key", OPT_IMPORTSM2KEY, '-', "Import SM2 key with the index"}, + {"importsm2keywithevlp", OPT_IMPORTSM2KEYWITHEVLP, '-', "Import SM2 key with digital envelope"}, + {"gensm2key", OPT_GENSM2KEY, '-', "Generate SM2 key pair with the index"}, + {"delsm2key", OPT_DELSM2KEY, '-', "Delete SM2 key pair with the index"}, + {"updatesm2key", OPT_UPDATESM2KEY, '-', "Update SM2 key pair with the index"}, + {"exportsm2key", OPT_EXPORTSM2KEY, '-', "Export SM2 key with the index"}, + {"exportsm2pubkey", OPT_EXPORTSM2PUBKEY, '-', "Export SM2 public key with the index"}, + {"exportsm2keywithevlp", OPT_EXPORTSM2KEYWITHEVLP, '-', "Export SM2 key with digital envelope"}, + {"login", OPT_LOGIN, 's', "Login with username:password"}, + + OPT_SECTION("Input"), + {"inkey", OPT_INKEY, 's', "Input key file"}, + {"index", OPT_INDEX, 's', "Specify the index of key"}, + {"peerkey", OPT_PEERKEY, 's', "Peer public key file used in exporting SM2 key with digital envelope"}, + {"type", OPT_TYPE, 's', "sign: signature key, enc: encryption key"}, + {"indek", OPT_INDEK, '>', "Input digital envelope key"}, + {"isk", OPT_ISK, 's', "Index of ISK key"}, + {"isktype", OPT_ISKTYPE, 's', "ISK type, sm2: SM2 key, rsa: RSA key"}, + {"iv", OPT_IV, 's', "IV in hex format"}, + {"algorithm", OPT_ALGORITHM, 's', "Algorithm to use"}, + {"in", OPT_IN, '>', "Input file"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file"}, + {"keyout", OPT_KEYOUT, '>', "Output key file"}, + {"dekout", OPT_DEKOUT, '>', "Output digital envelope key"}, + + {NULL} +}; + +int sdf_main(int argc, char **argv) +{ + char *prog; + OPTION_CHOICE o; + BIO *outkey = NULL, *outdek = NULL, *key_bio = NULL; + BIO *in = NULL, *out = NULL; + int ret = 1, index = -1, sign = 1, keylen = 0, deklen = 0, mode = 0; + int isk = -1; + int gensm2 = 0, delsm2 = 0, updatesm2 = 0; + int exportsm2pubkey = 0, exportsm2keywithevlp = 0, importsm2keywithevlp = 0; + int exportsm2key = 0, importsm2key = 0, encrypt = 0, decrypt = 0; + unsigned char *inkey = NULL, *indek = NULL, *inbuf = NULL, *outbuf = NULL; + char *p = NULL; + char *login = NULL; + char *outkeyfile = NULL, *peerkey_file = NULL, *indekfile = NULL; + char *outdekfile = NULL, *inkeyfile = NULL; + char *infile = NULL, *outfile = NULL; + const char *user = "admin", *password = "123123", *hexiv = NULL, *algo = NULL; + const char *isktype = "sm2"; + unsigned char *iv = NULL; + EVP_PKEY *pkey = NULL, *peer = NULL; + unsigned char *priv = NULL, *pub = NULL, *outevlp = NULL; + size_t privlen = 0, publen = 0, outevlplen = 0; + int inbuflen = -1; + size_t outbuflen = 0; + + prog = opt_init(argc, argv, sdf_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(sdf_options); + ret = 0; + goto end; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_INKEY: + inkeyfile = opt_arg(); + break; + case OPT_GENSM2KEY: + gensm2 = 1; + break; + case OPT_DELSM2KEY: + delsm2 = 1; + break; + case OPT_UPDATESM2KEY: + updatesm2 = 1; + break; + case OPT_INDEX: + index = atoi(opt_arg()); + break; + case OPT_LOGIN: + login = opt_arg(); + break; + case OPT_EXPORTSM2KEY: + exportsm2key = 1; + break; + case OPT_EXPORTSM2PUBKEY: + exportsm2pubkey = 1; + break; + case OPT_EXPORTSM2KEYWITHEVLP: + exportsm2keywithevlp = 1; + break; + case OPT_IMPORTSM2KEY: + importsm2key = 1; + break; + case OPT_IMPORTSM2KEYWITHEVLP: + importsm2keywithevlp = 1; + break; + case OPT_PEERKEY: + peerkey_file = opt_arg(); + break; + case OPT_TYPE: + if (strcmp(opt_arg(), "sign") == 0) + sign = 1; + else if (strcmp(opt_arg(), "enc") == 0) + sign = 0; + else + goto opthelp; + break; + case OPT_KEYOUT: + outkeyfile = opt_arg(); + break; + case OPT_INDEK: + indekfile = opt_arg(); + break; + case OPT_DEKOUT: + outdekfile = opt_arg(); + break; + case OPT_ENCRYPT: + encrypt = 1; + break; + case OPT_DECRYPT: + decrypt = 1; + break; + case OPT_IV: + hexiv = opt_arg(); + break; + case OPT_ALGORITHM: + algo = opt_arg(); + break; + case OPT_ISK: + isk = atoi(opt_arg()); + break; + case OPT_ISKTYPE: + isktype = opt_arg(); + break; + } + } + + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + if (login) { + user = login; + p = strchr(login, ':'); + if (p == NULL) { + BIO_printf(bio_err, "No password found"); + goto end; + } + + password = p + 1; + *p = '\0'; + } + + if (gensm2) { + if (!TSAPI_GenerateSM2KeyWithIndex(index, sign, user, password)) { + BIO_printf(bio_err, "Failed to generate SM2 key pair with index %d\n", index); + goto end; + } + + ret = 0; + goto end; + } + + if (delsm2) { + if (!TSAPI_DelSm2KeyWithIndex(index, sign, user, password)) { + BIO_printf(bio_err, "Failed to delete SM2 key pair with index %d\n", index); + goto end; + } + + ret = 0; + goto end; + } + + if (updatesm2) { + if (!TSAPI_UpdateSm2KeyWithIndex(index, sign, user, password)) { + BIO_printf(bio_err, "Failed to update SM2 key pair with index %d\n", index); + goto end; + } + + ret = 0; + goto end; + } + + if (outkeyfile) { + outkey = bio_open_default(outkeyfile, 'w', FORMAT_BINARY); + if (outkey == NULL) + goto end; + } + + if (exportsm2key) { + pkey = TSAPI_ExportSM2KeyWithIndex(index, sign, user, password); + if (pkey == NULL) { + BIO_printf(bio_err, "Failed to export SM2 pubkey with index %d\n", index); + goto end; + } + + if (!PEM_write_bio_PrivateKey(outkey, pkey, NULL, NULL, 0, NULL, NULL)) { + BIO_printf(bio_err, "Failed to write SM2 key\n"); + ERR_print_errors(bio_err); + goto end; + } + + ret = 0; + goto end; + } + + if (exportsm2pubkey) { + pkey = TSAPI_ExportSM2PubKeyWithIndex(index, sign); + if (pkey == NULL) { + BIO_printf(bio_err, "Failed to export SM2 pubkey with index %d\n", index); + goto end; + } + + if (!PEM_write_bio_PUBKEY(outkey, pkey)) { + BIO_printf(bio_err, "Failed to write SM2 pubkey"); + goto end; + } + + ret = 0; + goto end; + } + + if (exportsm2keywithevlp) { + peer = load_pubkey(peerkey_file, FORMAT_PEM, 0, NULL, NULL, "peer key"); + if (peer == NULL) { + BIO_printf(bio_err, "Error reading peer key %s\n", peerkey_file); + return 0; + } + + if (!TSAPI_ExportSM2KeyWithEvlp(index, sign, user, password, peer, &priv, + &privlen, &pub, &publen, &outevlp, + &outevlplen)) { + BIO_printf(bio_err, "Failed to export SM2 key with digital envelope\n"); + goto end; + } + + if (outkey == NULL) { + BIO_printf(bio_err, "No output file specified\n"); + goto end; + } + + if (BIO_write(outkey, pub, publen) != (int)publen + || BIO_write(outkey, priv, privlen) != (int)privlen) { + BIO_printf(bio_err, "Failed to write public or private key\n"); + goto end; + } + + if (outdekfile == NULL) { + BIO_printf(bio_err, "No digital envelope file specified\n"); + goto end; + } + + outdek = bio_open_default(outdekfile, 'w', FORMAT_BINARY); + if (outdek == NULL) + goto end; + + if (BIO_write(outdek, outevlp, outevlplen) != (int)outevlplen) { + BIO_printf(bio_err, "Failed to write digital envelope\n"); + goto end; + } + + ret = 0; + goto end; + } + + if (importsm2key) { + pkey = load_key(inkeyfile, FORMAT_PEM, 0, NULL, NULL, "key"); + + if (pkey == NULL) { + BIO_printf(bio_err, "Error reading key %s\n", inkeyfile); + goto end; + } + + if (!TSAPI_ImportSM2Key(index, sign, user, password, pkey)) { + BIO_printf(bio_err, "Failed to import SM2 key\n"); + goto end; + } + + ret = 0; + goto end; + } + + if (inkeyfile) { + key_bio = BIO_new(BIO_s_file()); + if (key_bio == NULL) { + BIO_printf(bio_err, "Error creating key BIO\n"); + goto end; + } + + if (BIO_read_filename(key_bio, inkeyfile) <= 0) { + BIO_printf(bio_err, "Error reading key file %s\n", inkeyfile); + goto end; + } + + keylen = bio_to_mem(&inkey, 4096, key_bio); + BIO_free(key_bio); + key_bio = NULL; + + if (keylen < 0) { + BIO_printf(bio_err, "Error reading key\n"); + goto end; + } + } + + if (indekfile) { + key_bio = BIO_new(BIO_s_file()); + if (key_bio == NULL) { + BIO_printf(bio_err, "Error creating key BIO\n"); + goto end; + } + + if (BIO_read_filename(key_bio, indekfile) <= 0) { + BIO_printf(bio_err, "Error reading key file %s\n", indekfile); + goto end; + } + + deklen = bio_to_mem(&indek, 4096, key_bio); + BIO_free(key_bio); + key_bio = NULL; + + if (deklen < 0) { + BIO_printf(bio_err, "Error reading key\n"); + goto end; + } + } + + if (importsm2keywithevlp) { + if (inkey == NULL || indek == NULL) { + BIO_printf(bio_err, "No key or digital envelope specified\n"); + goto end; + } + + if (!TSAPI_ImportSM2KeyWithEvlp(index, sign, user, password, inkey, + keylen, indek, deklen)) { + BIO_printf(bio_err, "Failed to import SM2 key with digital envelope\n"); + goto end; + } + + ret = 0; + goto end; + } + + if (infile) { + in = bio_open_default(infile, 'r', FORMAT_BINARY); + if (in == NULL) + goto end; + + /* Note: Only supports files less than 1GB */ + inbuflen = bio_to_mem(&inbuf, 1024 * 1024 * 1024, in); + if (inbuflen < 0) { + BIO_printf(bio_err, "Error reading input\n"); + goto end; + } + } + + if (outfile) { + out = bio_open_default(outfile, 'w', FORMAT_BINARY); + if (out == NULL) + goto end; + } + + if (encrypt || decrypt) { + if (inbuf == NULL || inbuflen < 0 || out == NULL || algo == NULL) { + BIO_printf(bio_err, "No input, output or algorithm specified\n"); + goto end; + } + + if (OPENSSL_strcasecmp(algo, "sm2") == 0) { + if (index < 0) { + BIO_printf(bio_err, "No SM2 key index specified\n"); + goto end; + } + + if (encrypt) + outbuf = TSAPI_SM2EncryptWithISK(index, inbuf, inbuflen, + &outbuflen); + else + outbuf = TSAPI_SM2DecryptWithISK(index, inbuf, inbuflen, + &outbuflen); + } else { + if (OPENSSL_strcasecmp(algo, "sm4-ecb") == 0) + mode = OSSL_SGD_SM4_ECB; + else if (OPENSSL_strcasecmp(algo, "sm4-cbc") == 0) + mode = OSSL_SGD_SM4_CBC; + else if (OPENSSL_strcasecmp(algo, "sm4-cfb") == 0) + mode = OSSL_SGD_SM4_CFB; + else if (OPENSSL_strcasecmp(algo, "sm4-ofb") == 0) + mode = OSSL_SGD_SM4_OFB; + else { + BIO_printf(bio_err, "Unknown algorithm %s\n", algo); + goto end; + } + + if (hexiv) { + iv = OPENSSL_hexstr2buf(hexiv, NULL); + if (iv == NULL) { + BIO_printf(bio_err, "Error reading IV\n"); + goto end; + } + } + + if (OPENSSL_strcasecmp(isktype, "sm2") == 0) { + if (encrypt) { + if ((outbuf = TSAPI_SM4Encrypt(mode, inkey, keylen, isk, iv, + inbuf, inbuflen, &outbuflen)) + == NULL) { + BIO_printf(bio_err, "Failed to encrypt data\n"); + goto end; + } + } else { + if ((outbuf = TSAPI_SM4Decrypt(mode, inkey, keylen, isk, iv, + inbuf, inbuflen, &outbuflen)) + == NULL) { + BIO_printf(bio_err, "Failed to decrypt data\n"); + goto end; + } + } + } else { + BIO_printf(bio_err, "Unknown ISK type %s\n", isktype); + goto end; + } + } + + if (BIO_write(out, outbuf, outbuflen) != (int)outbuflen) { + BIO_printf(bio_err, "Failed to write output\n"); + goto end; + } + + ret = 0; + goto end; + } + + ret = 0; +end: + OPENSSL_free(iv); + OPENSSL_free(inbuf); + OPENSSL_free(outbuf); + BIO_free(in); + BIO_free(out); + OPENSSL_free(inkey); + BIO_free(outdek); + BIO_free(key_bio); + EVP_PKEY_free(pkey); + EVP_PKEY_free(peer); + BIO_free(outkey); + OPENSSL_free(priv); + OPENSSL_free(pub); + OPENSSL_free(outevlp); + return ret; +} diff --git a/apps/speed.c b/apps/speed.c index e6aaa466c..d4e35f4b8 100644 --- a/apps/speed.c +++ b/apps/speed.c @@ -30,6 +30,7 @@ #define EdDSA_SECONDS PKEY_SECONDS #define SM2_SECONDS PKEY_SECONDS #define FFDH_SECONDS PKEY_SECONDS +#define KEYGEN_SECONDS PKEY_SECONDS /* We need to use some deprecated APIs */ #define OPENSSL_SUPPRESS_DEPRECATED @@ -48,6 +49,8 @@ #include #include #include +#include +#include #if !defined(OPENSSL_SYS_MSDOS) # include #endif @@ -121,6 +124,7 @@ typedef struct openssl_speed_sec_st { int ec_elgamal; int paillier; int bulletproofs; + int keygen; } openssl_speed_sec_t; static volatile int run = 0; @@ -260,7 +264,7 @@ typedef enum OPTION_choice { OPT_COMMON, OPT_ELAPSED, OPT_EVP, OPT_HMAC, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI, OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM, OPT_PROV_ENUM, - OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC + OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC, OPT_KEYGEN, OPT_SDF } OPTION_CHOICE; const OPTIONS speed_options[] = { @@ -291,6 +295,8 @@ const OPTIONS speed_options[] = { "Time decryption instead of encryption (only EVP)"}, {"aead", OPT_AEAD, '-', "Benchmark EVP-named AEAD cipher in TLS-like sequence"}, + {"keygen", OPT_KEYGEN, 's', "Time the key generation using the specified algorithm"}, + {"sdf", OPT_SDF, 's', "Time the SDF operations using the specified operation"}, OPT_SECTION("Timing"), {"elapsed", OPT_ELAPSED, '-', @@ -316,7 +322,7 @@ enum { D_CBC_DES, D_EDE3_DES, D_RC4, D_CBC_RC5, D_CBC_128_AES, D_CBC_192_AES, D_CBC_256_AES, - D_EVP, D_GHASH, D_RAND, D_EVP_CMAC, D_SM3, D_CBC_SM4, + D_EVP, D_GHASH, D_RAND, D_EVP_CMAC, D_SM3, D_CBC_SM4, D_ECB_SM4, D_EEA3_128_ZUC, D_EIA3_128_ZUC, D_SM2_ENCRYPT, D_SM2_DECRYPT, D_SM2_THRESHOLD_DECRYPT, ALGOR_NUM }; @@ -327,7 +333,7 @@ static const char *names[ALGOR_NUM] = { "des-cbc", "des-ede3", "rc4", "rc5-cbc", "aes-128-cbc", "aes-192-cbc", "aes-256-cbc", - "evp", "ghash", "rand", "cmac", "sm3", "sm4", + "evp", "ghash", "rand", "cmac", "sm3", "sm4-cbc", "sm4-ecb", "zuc-128-eea3", "zuc-128-eia3", "sm2-encrypt", "sm2-decrypt", "sm2-thr-dec", }; @@ -354,6 +360,7 @@ static const OPT_PAIR doit_choices[] = { #ifndef OPENSSL_NO_SM4 {"sm4-cbc", D_CBC_SM4}, {"sm4", D_CBC_SM4}, + {"sm4-ecb", D_ECB_SM4}, #endif #ifndef OPENSSL_NO_ZUC {"zuc-128-eea3", D_EEA3_128_ZUC}, @@ -646,9 +653,34 @@ static double bulletproofs_results[BULLETPROOFS_NUM][BULLETPROOFS_BITS_NUM][BULL #endif /* OPENSSL_NO_BULLETPROOFS */ +enum { + R_SM2, KEYGEN_NUM +}; +static const OPT_PAIR keygen_choices[KEYGEN_NUM] = { + {"sm2", R_SM2}, +}; + +static double keygen_results[KEYGEN_NUM]; + +enum { + R_GenerateKey, SDF_NUM +}; +static const OPT_PAIR sdf_choices[SDF_NUM] = { + {"GenerateKey", R_GenerateKey}, +}; + +static double sdf_results[SDF_NUM]; + #define COND(unused_cond) (run && count < INT_MAX) #define COUNT(d) (count) +typedef struct { + void *hSessionHandle; + void *hKeyHandle; +} HANDLE_PAIR; + +DEFINE_STACK_OF(HANDLE_PAIR) + typedef struct loopargs_st { ASYNC_JOB *inprogress_job; ASYNC_WAIT_CTX *wait_ctx; @@ -710,6 +742,10 @@ typedef struct loopargs_st { #endif EVP_CIPHER_CTX *ctx; EVP_MAC_CTX *mctx; + + void *hDeviceHandle; + void *hSessionHandle; + STACK_OF(HANDLE_PAIR) *key_handles; } loopargs_t; static int run_benchmark(int async_jobs, int (*loop_function) (void *), loopargs_t * loopargs); @@ -1379,6 +1415,24 @@ static int SM2_decrypt_loop(void *args) return count; } + +static int SM2_keygen_loop(void *args) +{ + int count; + + for (count = 0; COND(keygen_results[testnum]); count++) { + if (EVP_PKEY_Q_keygen(app_get0_libctx(), app_get0_propq(), "SM2") + == NULL) { + BIO_printf(bio_err, "SM2 keygen failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + + return count; +} + # ifndef OPENSSL_NO_SM2_THRESHOLD static long sm2_threshold_c[2]; @@ -1697,6 +1751,43 @@ static int BULLETPROOFS_loop(void *args) } #endif /* OPENSSL_NO_BULLETPROOFS */ +static void sdf_destroy_key(HANDLE_PAIR *pair) +{ + (void)TSAPI_SDF_DestroyKey(pair->hSessionHandle, pair->hKeyHandle); +} + +static int SDF_GenerateKey_loop(void *args) +{ + HANDLE_PAIR *pair = NULL; + loopargs_t *tempargs = *(loopargs_t **)args; + void *hSessionHandle = tempargs->hSessionHandle; + void *pkeyHandle = NULL; + int ret, count; + + for (count = 0; COND(1); count++) { + ret = TSAPI_SDF_GenerateKey(hSessionHandle, OSSL_SDFE_SYM_KEY_TYPE_SM4, + 1, 16, &pkeyHandle); + if (ret != OSSL_SDR_OK) { + BIO_printf(bio_err, "SDF_GenerateKey failed with %d\n", ret); + count = -1; + break; + } + + pair = OPENSSL_zalloc(sizeof(HANDLE_PAIR)); + if (pair == NULL) { + BIO_printf(bio_err, "Memory allocation failed\n"); + count = -1; + break; + } + pair->hSessionHandle = hSessionHandle; + pair->hKeyHandle = pkeyHandle; + + sk_HANDLE_PAIR_push(tempargs->key_handles, pair); + } + + return count; +} + static int run_benchmark(int async_jobs, int (*loop_function) (void *), loopargs_t * loopargs) { @@ -1943,7 +2034,8 @@ int speed_main(int argc, char **argv) OPTION_CHOICE o; int async_init = 0, multiblock = 0, pr_header = 0; uint8_t doit[ALGOR_NUM] = { 0 }; - int ret = 1, misalign = 0, lengths_single = 0, aead = 0; + int ret = 1, misalign = 0, lengths_single = 0, aead = 0, keygen = 0; + int sdf = 0; long count = 0; unsigned int size_num = SIZE_NUM; unsigned int i, k, loopargs_len = 0, async_jobs = 0; @@ -1959,7 +2051,8 @@ int speed_main(int argc, char **argv) ECDSA_SECONDS, ECDH_SECONDS, EdDSA_SECONDS, SM2_SECONDS, FFDH_SECONDS, EC_ELGAMAL_SECONDS, - PAILLIER_SECONDS, BULLETPROOFS_SECONDS }; + PAILLIER_SECONDS, BULLETPROOFS_SECONDS, + KEYGEN_SECONDS,}; static const unsigned char key32[32] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, @@ -2140,6 +2233,8 @@ int speed_main(int argc, char **argv) uint8_t ecdsa_doit[ECDSA_NUM] = { 0 }; uint8_t ecdh_doit[EC_NUM] = { 0 }; uint8_t eddsa_doit[EdDSA_NUM] = { 0 }; + uint8_t keygen_doit[KEYGEN_NUM] = { 0 }; + uint8_t sdf_doit[SDF_NUM] = { 0 }; /* checks declarated curves against choices list. */ OPENSSL_assert(ed_curves[EdDSA_NUM - 1].nid == NID_ED448); @@ -2278,7 +2373,8 @@ int speed_main(int argc, char **argv) case OPT_SECONDS: seconds.sym = seconds.rsa = seconds.dsa = seconds.ecdsa = seconds.ecdh = seconds.eddsa - = seconds.sm2 = seconds.ffdh = atoi(opt_arg()); + = seconds.sm2 = seconds.ffdh = seconds.keygen + = atoi(opt_arg()); break; case OPT_BYTES: lengths_single = atoi(opt_arg()); @@ -2287,6 +2383,22 @@ int speed_main(int argc, char **argv) break; case OPT_AEAD: aead = 1; + break; + case OPT_KEYGEN: + keygen = 1; + if (opt_found(opt_arg(), keygen_choices, &i)) { + keygen_doit[i] = 1; + break; + } + + break; + case OPT_SDF: + sdf = 1; + if (opt_found(opt_arg(), sdf_choices, &i)) { + sdf_doit[i] = 1; + break; + } + break; } } @@ -2543,6 +2655,7 @@ int speed_main(int argc, char **argv) loopargs[i].secret_ff_a = app_malloc(MAX_FFDH_SIZE, "FFDH secret a"); loopargs[i].secret_ff_b = app_malloc(MAX_FFDH_SIZE, "FFDH secret b"); #endif + loopargs[i].key_handles = sk_HANDLE_PAIR_new_null(); } #ifndef NO_FORK @@ -2554,7 +2667,8 @@ int speed_main(int argc, char **argv) e = setup_engine(engine_id, 0); /* No parameters; turn on everything. */ - if (argc == 0 && !doit[D_EVP] && !doit[D_HMAC] && !doit[D_EVP_CMAC]) { + if (argc == 0 && !doit[D_EVP] && !doit[D_HMAC] && !doit[D_EVP_CMAC] + && !keygen && !sdf) { memset(doit, 1, sizeof(doit)); doit[D_EVP] = doit[D_EVP_CMAC] = 0; ERR_set_mark(); @@ -2604,6 +2718,8 @@ int speed_main(int argc, char **argv) memset(sm2_threshold_doit, 1, sizeof(sm2_threshold_doit)); # endif #endif + memset(keygen_doit, 1, sizeof(keygen_doit)); + memset(sdf_doit, 1, sizeof(sdf_doit)); } for (i = 0; i < ALGOR_NUM; i++) if (doit[i]) @@ -2966,27 +3082,31 @@ int speed_main(int argc, char **argv) } #ifndef OPENSSL_NO_SM4 - if (doit[D_CBC_SM4]) { - int st = 1; + for (k = 0; k < 2; k++) { + algindex = D_CBC_SM4 + k; - keylen = 16; - for (i = 0; st && i < loopargs_len; i++) { - loopargs[i].ctx = init_evp_cipher_ctx(names[D_CBC_SM4], - key32, keylen); - st = loopargs[i].ctx != NULL; - } + if (doit[algindex]) { + int st = 1; - for (testnum = 0; st && testnum < size_num; testnum++) { - print_message(names[D_CBC_SM4], c[D_CBC_SM4][testnum], - lengths[testnum], seconds.sym); - Time_F(START); - count = - run_benchmark(async_jobs, EVP_Cipher_loop, loopargs); - d = Time_F(STOP); - print_result(D_CBC_SM4, testnum, count, d); + keylen = 16; + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].ctx = init_evp_cipher_ctx(names[algindex], + key32, keylen); + st = loopargs[i].ctx != NULL; + } + + for (testnum = 0; st && testnum < size_num; testnum++) { + print_message(names[algindex], c[algindex][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = + run_benchmark(async_jobs, EVP_Cipher_loop, loopargs); + d = Time_F(STOP); + print_result(algindex, testnum, count, d); + } + for (i = 0; i < loopargs_len; i++) + EVP_CIPHER_CTX_free(loopargs[i].ctx); } - for (i = 0; i < loopargs_len; i++) - EVP_CIPHER_CTX_free(loopargs[i].ctx); } #endif @@ -3715,47 +3835,57 @@ int speed_main(int argc, char **argv) for (i = 0; st && i < loopargs_len; i++) { EVP_PKEY *pkey = NULL, *pubkey = NULL; - OSSL_PARAM *pub_params = NULL; EVP_PKEY_CTX *ctx = NULL; + BIO *tmpbio = NULL; st = 0; pkey = EVP_PKEY_Q_keygen(app_get0_libctx(), app_get0_propq(), "SM2"); if (pkey == NULL) break; - if (!EVP_PKEY_todata(pkey, EVP_PKEY_PUBLIC_KEY, &pub_params)) { + if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) + break; + + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ctx == NULL) { EVP_PKEY_free(pkey); break; } - ctx = EVP_PKEY_CTX_new_from_name(NULL, "SM2", NULL); - if (ctx == NULL) { + tmpbio = BIO_new(BIO_s_mem()); + if (tmpbio == NULL) + break; + + if (!PEM_write_bio_PUBKEY(tmpbio, pkey)) { EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + BIO_free(tmpbio); break; } - if (EVP_PKEY_fromdata_init(ctx) <= 0 - || EVP_PKEY_fromdata(ctx, &pubkey, EVP_PKEY_PUBLIC_KEY, - pub_params) <= 0) { + if (!PEM_read_bio_PUBKEY(tmpbio, &pubkey, NULL, NULL)) { EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); + BIO_free(tmpbio); break; } EVP_PKEY_CTX_free(ctx); + BIO_free(tmpbio); loopargs[i].sm2_enc_pctx = EVP_PKEY_CTX_new(pubkey, NULL); if (loopargs[i].sm2_enc_pctx == NULL) { EVP_PKEY_free(pkey); + EVP_PKEY_free(pubkey); break; } + EVP_PKEY_free(pubkey); loopargs[i].sm2_dec_pctx = EVP_PKEY_CTX_new(pkey, NULL); if (loopargs[i].sm2_dec_pctx == NULL) { EVP_PKEY_free(pkey); break; } - EVP_PKEY_free(pkey); if (EVP_PKEY_encrypt_init(loopargs[i].sm2_enc_pctx) <= 0) @@ -3956,7 +4086,6 @@ int speed_main(int argc, char **argv) for (i = 0; i < loopargs_len; i++) { EVP_PKEY_CTX *sm2_pctx = NULL; EVP_PKEY_CTX *sm2_vfy_pctx = NULL; - EVP_PKEY_CTX *pctx = NULL; st = 0; loopargs[i].sm2_ctx[testnum] = EVP_MD_CTX_new(); @@ -3967,16 +4096,12 @@ int speed_main(int argc, char **argv) sm2_pkey = NULL; - st = !((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2, NULL)) == NULL - || EVP_PKEY_keygen_init(pctx) <= 0 - || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, - sm2_curves[testnum].nid) <= 0 - || EVP_PKEY_keygen(pctx, &sm2_pkey) <= 0); - EVP_PKEY_CTX_free(pctx); - if (st == 0) + sm2_pkey = EVP_PKEY_Q_keygen(app_get0_libctx(), app_get0_propq(), "SM2"); + if (sm2_pkey == NULL) break; - st = 0; /* set back to zero */ + if (!EVP_PKEY_set_alias_type(sm2_pkey, EVP_PKEY_SM2)) + break; /* attach it sooner to rely on main final cleanup */ loopargs[i].sm2_pkey[testnum] = sm2_pkey; loopargs[i].sigsize = EVP_PKEY_get_size(sm2_pkey); @@ -4769,6 +4894,73 @@ int speed_main(int argc, char **argv) } #endif /* OPENSSL_NO_BULLETPROOFS */ + for (testnum = 0; testnum < KEYGEN_NUM; testnum++) { + if (!keygen_doit[testnum]) + continue; + + if (testnum == R_SM2) { + pkey_print_message("keygen", "sm2", 0, 128, seconds.keygen); + Time_F(START); +#ifndef OPENSSL_NO_SM2 + count = run_benchmark(async_jobs, SM2_keygen_loop, loopargs); +#else + count = 0; +#endif + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+F14:%ld:%s:%.2f\n" + : "%ld %s keygen in %.2fs\n", + count, keygen_choices[testnum].name, d); + keygen_results[testnum] = (double)count / d; + } + } + + for (testnum = 0; testnum < SDF_NUM; testnum++) { + int st = 1; + int res; + + if (!sdf_doit[testnum]) + continue; + + for (i = 0; i < loopargs_len; i++) { + st = 0; + + res = TSAPI_SDF_OpenDevice(&loopargs[i].hDeviceHandle); + if (res != OSSL_SDR_OK) { + BIO_printf(bio_err, "TSAPI_SDF_OpenDevice failed with %d\n", ret); + break; + } + + res = TSAPI_SDF_OpenSession(loopargs[i].hDeviceHandle, + &loopargs[i].hSessionHandle); + if (res != OSSL_SDR_OK) { + BIO_printf(bio_err, "TSAPI_SDF_OpenSession failed with %d\n", ret); + break; + } + + st = 1; + } + + if (st == 0) { + BIO_printf(bio_err, "SDF failure.\n"); + op_count = 1; + } else { + + if (testnum == R_GenerateKey) { + pkey_print_message("GenerateKey", "sm4", 0, 128, + seconds.keygen); + Time_F(START); + count = run_benchmark(async_jobs, SDF_GenerateKey_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+F15:%ld:%s:%.2f\n" + : "%ld %s keygen in %.2fs\n", + count, sdf_choices[testnum].name, d); + sdf_results[testnum] = (double)count / d; + } + } + } + #ifndef NO_FORK show_res: #endif @@ -5060,6 +5252,48 @@ int speed_main(int argc, char **argv) } #endif + testnum = 1; + for (k = 0; k < KEYGEN_NUM; k++) { + if (!keygen_doit[k]) + continue; + + if (testnum && !mr) { + printf("%30sop op/s\n", " "); + testnum = 0; + } + + if (mr) + printf("+F14:%u:%s:%f:%f\n", + k, keygen_choices[k].name, keygen_results[k], + 1.0 / keygen_results[k]); + else + printf("128 bits keygen (%s) %8.4fs %8.1f\n", + keygen_choices[k].name, 1.0 / keygen_results[k], + keygen_results[k]); + } + + testnum = 1; + for (k = 0; k < SDF_NUM; k++) { + if (!sdf_doit[k]) + continue; + + if (testnum && !mr) { + printf("%30sop op/s\n", " "); + testnum = 0; + } + + if (k == R_GenerateKey) { + if (mr) + printf("+F15:%u:%s:%f:%f\n", + k, sdf_choices[k].name, sdf_results[k], + 1.0 / sdf_results[k]); + else + printf("128 bits keygen (%s) %8.4fs %8.1f\n", + sdf_choices[k].name, 1.0 / sdf_results[k], + sdf_results[k]); + } + } + ret = 0; end: @@ -5156,6 +5390,14 @@ int speed_main(int argc, char **argv) #endif OPENSSL_free(loopargs[i].secret_a); OPENSSL_free(loopargs[i].secret_b); + + sk_HANDLE_PAIR_pop_free(loopargs[i].key_handles, sdf_destroy_key); + + if (loopargs[i].hSessionHandle != NULL) + TSAPI_SDF_CloseSession(loopargs[i].hSessionHandle); + + if (loopargs[i].hDeviceHandle != NULL) + TSAPI_SDF_CloseDevice(loopargs[i].hDeviceHandle); } OPENSSL_free(evp_hmac_name); OPENSSL_free(evp_cmac_name); diff --git a/apps/version.c b/apps/version.c index 874542349..63be8bf83 100644 --- a/apps/version.c +++ b/apps/version.c @@ -167,7 +167,6 @@ int version_main(int argc, char **argv) } #ifdef SMTC_MODULE if (smtc) { - printf("%s\n", OpenSSL_version(TONGSUO_VERSION)); printf("%s\n", OpenSSL_version(TONGSUO_SMTC_INFO)); } #endif diff --git a/crypto/bio/bss_log.c b/crypto/bio/bss_log.c index 66d8f8868..9f379b8c3 100644 --- a/crypto/bio/bss_log.c +++ b/crypto/bio/bss_log.c @@ -22,30 +22,12 @@ #include "bio_local.h" #include "internal/cryptlib.h" -#if defined(OPENSSL_SYS_WINCE) -#elif defined(OPENSSL_SYS_WIN32) -#elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG) -# include -#endif - +#include #include #include #ifndef NO_SYSLOG -# if defined(OPENSSL_SYS_WIN32) -# define LOG_EMERG 0 -# define LOG_ALERT 1 -# define LOG_CRIT 2 -# define LOG_ERR 3 -# define LOG_WARNING 4 -# define LOG_NOTICE 5 -# define LOG_INFO 6 -# define LOG_DEBUG 7 - -# define LOG_DAEMON (3<<3) -# endif - static int slg_write(BIO *h, const char *buf, int num); static int slg_puts(BIO *h, const char *str); static long slg_ctrl(BIO *h, int cmd, long arg1, void *arg2); diff --git a/crypto/build.info b/crypto/build.info index db0808cac..35b77e29a 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -6,7 +6,7 @@ SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 conf \ siphash sm3 des aes rc4 rc5 zuc \ sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \ err comp http ocsp cms ts srp cmac ct async ess crmf cmp encode_decode \ - ffc paillier zkp + ffc paillier zkp sdf tsapi LIBS=../libcrypto @@ -96,7 +96,7 @@ SOURCE[../libcrypto]=$UTIL_COMMON \ mem.c mem_sec.c \ cversion.c info.c cpt_err.c ebcdic.c uid.c o_time.c o_dir.c \ o_fopen.c getenv.c o_init.c init.c trace.c provider.c provider_child.c \ - punycode.c passphrase.c + punycode.c passphrase.c o_syslog.c SOURCE[../providers/libfips.a]=$UTIL_COMMON SOURCE[../libcrypto]=$UPLINKSRC @@ -128,3 +128,14 @@ INCLUDE[s390xcpuid.o]=. IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}] SHARED_SOURCE[../libcrypto]=dllmain.c ENDIF + +{- use File::Spec::Functions; + our $ex_lib = $withargs{sdf_lib} && + (file_name_is_absolute($withargs{sdf_lib}) ? + $withargs{sdf_lib} : catfile(updir(), $withargs{sdf_lib})); + "" +-} + +IF[{- !$disabled{sdf_lib} -}] + DEPEND[../libcrypto]={- $ex_lib -} +ENDIF diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index bd9bd818d..d1973c0eb 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1,4 +1,4 @@ -# Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1999-2024 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 @@ -651,7 +651,6 @@ ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR:101:ess signing cert v2 add error ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE:108:\ missing signing certificate attribute EVP_R_AES_KEY_SETUP_FAILED:143:aes key setup failed -EVP_R_ARIA_KEY_SETUP_FAILED:176:aria key setup failed EVP_R_BAD_ALGORITHM_NAME:200:bad algorithm name EVP_R_BAD_DECRYPT:100:bad decrypt EVP_R_BAD_KEY_LENGTH:195:bad key length @@ -990,6 +989,7 @@ PROV_R_FIPS_MODULE_IN_ERROR_STATE:225:fips module in error state PROV_R_GENERATE_ERROR:191:generate error PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:165:\ illegal or unsupported padding mode +PROV_R_INCORRECT_PASSWORD:231:incorrect password PROV_R_INDICATOR_INTEGRITY_FAILURE:210:indicator integrity failure PROV_R_INSUFFICIENT_DRBG_STRENGTH:181:insufficient drbg strength PROV_R_INVALID_AAD:108:invalid aad @@ -1069,6 +1069,9 @@ PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT:229:\ seed sources must not have a parent PROV_R_SELF_TEST_KAT_FAILURE:215:self test kat failure PROV_R_SELF_TEST_POST_FAILURE:216:self test post failure +PROV_R_SMTC_MODULE_CONDITIONAL_ERROR:232:smtc module conditional error +PROV_R_SMTC_MODULE_ENTERING_ERROR_STATE:350:smtc module entering error state +PROV_R_SMTC_MODULE_IN_ERROR_STATE:351:smtc module in error state PROV_R_TAG_NOT_NEEDED:120:tag not needed PROV_R_TAG_NOT_SET:119:tag not set PROV_R_TOO_MANY_RECORDS:126:too many records diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c index 76a6814b4..1d9534716 100644 --- a/crypto/evp/m_sigver.c +++ b/crypto/evp/m_sigver.c @@ -63,10 +63,16 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, if (ctx->pctx == NULL) { reinit = 0; - if (e == NULL) - ctx->pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, props); - else + if (e == NULL) { +#ifdef SMTC_MODULE + if (ver) + ctx->pctx = EVP_PKEY_CTX_new_from_pkey_provided(libctx, pkey, props); + else +#endif + ctx->pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, props); + } else { ctx->pctx = EVP_PKEY_CTX_new(pkey, e); + } } if (ctx->pctx == NULL) return 0; diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c index 8e4940ed5..48e222631 100644 --- a/crypto/evp/pmeth_gn.c +++ b/crypto/evp/pmeth_gn.c @@ -230,6 +230,11 @@ int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) default: goto not_supported; } + +# ifndef OPENSSL_NO_SM2 + if (ret > 0 && EVP_PKEY_CTX_is_a(ctx, "SM2")) + ret = EVP_PKEY_set_alias_type(*ppkey, EVP_PKEY_SM2); +# endif #endif end: @@ -271,6 +276,10 @@ int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); return -1; } + +#ifdef SMTC_MODULE + OSSL_syslog(LOG_INFO, "Creating a key pair\n"); +#endif return EVP_PKEY_generate(ctx, ppkey); } diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 26d3e902d..a9cac26e3 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -375,6 +375,82 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OSSL_LIB_CTX *libctx, EVP_PKEY *pkey, return int_ctx_new(libctx, pkey, NULL, NULL, propquery, -1); } +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey_provided(OSSL_LIB_CTX *libctx, + EVP_PKEY *pkey, + const char *propquery) +{ + EVP_PKEY_CTX *ret = NULL; + + if (pkey == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (!evp_pkey_is_provided(pkey)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY); + return NULL; + } + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (propquery != NULL) { + ret->propquery = OPENSSL_strdup(propquery); + if (ret->propquery == NULL) { + OPENSSL_free(ret); + return NULL; + } + } + + ret->libctx = libctx; + ret->operation = EVP_PKEY_OP_UNDEFINED; + ret->keymgmt = pkey->keymgmt; + EVP_KEYMGMT_up_ref(pkey->keymgmt); + + ret->keytype = EVP_KEYMGMT_get0_name(ret->keymgmt); + ret->pkey = pkey; + EVP_PKEY_up_ref(pkey); + + return ret; +} + +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name_provided(OSSL_LIB_CTX *libctx, + const char *name, + const char *propquery) +{ + EVP_PKEY_CTX *ret = NULL; + EVP_KEYMGMT *keymgmt; + + keymgmt = EVP_KEYMGMT_fetch(libctx, name, propquery); + if (keymgmt == NULL) + return NULL; + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + EVP_KEYMGMT_free(keymgmt); + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (propquery != NULL) { + ret->propquery = OPENSSL_strdup(propquery); + if (ret->propquery == NULL) { + OPENSSL_free(ret); + EVP_KEYMGMT_free(keymgmt); + return NULL; + } + } + + ret->operation = EVP_PKEY_OP_UNDEFINED; + ret->keymgmt = keymgmt; + ret->keytype = EVP_KEYMGMT_get0_name(keymgmt); + + return ret; +} + void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx) { if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) { diff --git a/crypto/info.c b/crypto/info.c index 69142d396..5984426fc 100644 --- a/crypto/info.c +++ b/crypto/info.c @@ -152,8 +152,14 @@ DEFINE_RUN_ONCE_STATIC(init_info_strings) #ifdef OPENSSL_RAND_SEED_OS add_seeds_string("os-specific"); #endif -#ifdef OPENSSL_RAND_SEED_RTC - add_seeds_string("real-time-clock"); +#ifdef OPENSSL_RAND_SEED_RTCODE + add_seeds_string("real-time-code"); +#endif +#ifdef OPENSSL_RAND_SEED_RTMEM + add_seeds_string("real-time-memory"); +#endif +#ifdef OPENSSL_RAND_SEED_RTSOCK + add_seeds_string("real-time-socket"); #endif seed_sources = seeds; } @@ -200,6 +206,12 @@ const char *OPENSSL_info(int t) if (ossl_cpu_info_str[0] != '\0') return ossl_cpu_info_str + strlen(CPUINFO_PREFIX); break; +#ifdef SMTC_MODULE + case OPENSSL_INFO_SMTC_MODULE_CONF: + return SMTC_MODULE_CONF; + case OPENSSL_INFO_SMTC_AUTH_KEK: + return SMTC_AUTH_KEK; +#endif default: break; } diff --git a/crypto/init.c b/crypto/init.c index f4df1d983..184ac8d8d 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -33,6 +33,7 @@ #include /* for OSSL_CMP_log_close() */ #include #include "crypto/ctype.h" +#include "internal/sdf.h" static int stopped = 0; static uint64_t optsdone = 0; @@ -445,6 +446,9 @@ void OPENSSL_cleanup(void) OSSL_CMP_log_close(); #endif + OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_sdf_lib_cleanup()\n"); + ossl_sdf_lib_cleanup(); + OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_trace_cleanup()\n"); ossl_trace_cleanup(); diff --git a/crypto/o_syslog.c b/crypto/o_syslog.c new file mode 100644 index 000000000..49ce4b437 --- /dev/null +++ b/crypto/o_syslog.c @@ -0,0 +1,80 @@ +/* + * Copyright 2024 The Tongsuo 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://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt + */ + +#include +#include +#include +#include "internal/nelem.h" + +static int logging = 0; + +void OSSL_enable_syslog(void) +{ + logging = 1; +} + +void OSSL_disable_syslog(void) +{ + logging = 0; +} + +void OSSL_syslog(int priority, const char *message, ...) +{ + va_list args; + unsigned char buf[4096]; + BIO *bio = NULL; + size_t i; + int written = 0, ret; + const struct { + int log_level; + const char *str; + } mapping[] = { + { LOG_EMERG, "EMERG" }, + { LOG_ALERT, "ALERT" }, + { LOG_CRIT, "CRIT" }, + { LOG_ERR, "ERROR" }, + { LOG_WARNING, "WARNING" }, + { LOG_NOTICE, "NOTICE" }, + { LOG_INFO, "INFO" }, + { LOG_DEBUG, "DEBUG" }, + }; + + if (logging == 0) + return; + + bio = BIO_new(BIO_s_log()); + if (bio == NULL) + return; + + for (i = 0; i < OSSL_NELEM(mapping); i++) { + if (mapping[i].log_level == priority) { + ret = BIO_snprintf((char *)buf, sizeof(buf), "%s ", mapping[i].str); + if (ret < 0) + goto end; + + written += ret; + break; + } + } + + va_start(args, message); + ret = BIO_vsnprintf((char *)buf, sizeof(buf) - written, message, args); + va_end(args); + + if (ret < 0) + goto end; + + written += ret; + + if (BIO_write(bio, buf, written) != written) + goto end; + +end: + BIO_free(bio); +} diff --git a/crypto/provider.c b/crypto/provider.c index 114b42692..e2001a2db 100644 --- a/crypto/provider.c +++ b/crypto/provider.c @@ -99,6 +99,16 @@ const OSSL_DISPATCH *OSSL_PROVIDER_get0_dispatch(const OSSL_PROVIDER *prov) return ossl_provider_get0_dispatch(prov); } +int OSSL_PROVIDER_reset(OSSL_PROVIDER *prov) +{ + return ossl_provider_reset(prov); +} + +int OSSL_PROVIDER_status(const OSSL_PROVIDER *prov) +{ + return ossl_provider_status(prov); +} + int OSSL_PROVIDER_self_test(const OSSL_PROVIDER *prov) { return ossl_provider_self_test(prov); diff --git a/crypto/provider_core.c b/crypto/provider_core.c index 177358f05..0c439ed6c 100644 --- a/crypto/provider_core.c +++ b/crypto/provider_core.c @@ -172,6 +172,8 @@ struct ossl_provider_st { OSSL_FUNC_provider_self_test_fn *self_test; OSSL_FUNC_provider_query_operation_fn *query_operation; OSSL_FUNC_provider_unquery_operation_fn *unquery_operation; + OSSL_FUNC_provider_status_fn *status; + OSSL_FUNC_provider_reset_fn *reset; /* * Cache of bit to indicate of query_operation() has been called on @@ -944,6 +946,12 @@ static int provider_init(OSSL_PROVIDER *prov) prov->unquery_operation = OSSL_FUNC_provider_unquery_operation(provider_dispatch); break; + case OSSL_FUNC_PROVIDER_STATUS: + prov->status = OSSL_FUNC_provider_status(provider_dispatch); + break; + case OSSL_FUNC_PROVIDER_RESET: + prov->reset = OSSL_FUNC_provider_reset(provider_dispatch); + break; #ifndef OPENSSL_NO_ERR # ifndef FIPS_MODULE case OSSL_FUNC_PROVIDER_GET_REASON_STRINGS: @@ -1492,6 +1500,22 @@ int ossl_provider_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[]) ? 0 : prov->get_params(prov->provctx, params); } +int ossl_provider_reset(OSSL_PROVIDER *prov) +{ + if (prov->reset == NULL) + return 1; + + return prov->reset(prov->provctx); +} + +int ossl_provider_status(const OSSL_PROVIDER *prov) +{ + if (prov->status == NULL) + return 1; + + return prov->status(prov->provctx); +} + int ossl_provider_self_test(const OSSL_PROVIDER *prov) { int ret; diff --git a/crypto/provider_predefined.c b/crypto/provider_predefined.c index 938c1ba9a..8fdc37b07 100644 --- a/crypto/provider_predefined.c +++ b/crypto/provider_predefined.c @@ -17,13 +17,19 @@ OSSL_provider_init_fn ossl_fips_intern_provider_init; #ifdef STATIC_LEGACY OSSL_provider_init_fn ossl_legacy_provider_init; #endif -#ifdef STATIC_SMTC +#ifdef SMTC_MODULE +# ifdef STATIC_SMTC OSSL_provider_init_fn ossl_smtc_provider_init; +# endif #endif const OSSL_PROVIDER_INFO ossl_predefined_providers[] = { #ifdef FIPS_MODULE { "fips", NULL, ossl_fips_intern_provider_init, NULL, 1 }, +#elif defined(SMTC_MODULE) +# ifdef STATIC_SMTC + { "smtc", NULL, ossl_smtc_provider_init, NULL, 0 }, +# endif #else { "default", NULL, ossl_default_provider_init, NULL, 1 }, # ifdef STATIC_LEGACY @@ -31,9 +37,6 @@ const OSSL_PROVIDER_INFO ossl_predefined_providers[] = { # endif { "base", NULL, ossl_base_provider_init, NULL, 0 }, { "null", NULL, ossl_null_provider_init, NULL, 0 }, -# ifdef STATIC_SMTC - { "smtc", NULL, ossl_smtc_provider_init, NULL, 0 }, -# endif #endif { NULL, NULL, NULL, NULL, 0 } }; diff --git a/crypto/rand/prov_seed.c b/crypto/rand/prov_seed.c index afa85ab76..486153ec8 100644 --- a/crypto/rand/prov_seed.c +++ b/crypto/rand/prov_seed.c @@ -38,6 +38,34 @@ size_t ossl_rand_get_entropy(ossl_unused OSSL_CORE_HANDLE *handle, return ret; } +size_t ossl_rand_get_entropy_from_source(unsigned int source, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len) +{ + size_t ret = 0; + size_t entropy_available; + RAND_POOL *pool; + + pool = ossl_rand_pool_new(entropy, 1, min_len, max_len); + if (pool == NULL) { + ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE); + return 0; + } + + pool->entropy_source = source; + + /* Get entropy by polling system entropy sources. */ + entropy_available = ossl_pool_acquire_entropy(pool); + + if (entropy_available > 0) { + ret = ossl_rand_pool_length(pool); + *pout = ossl_rand_pool_detach(pool); + } + + ossl_rand_pool_free(pool); + return ret; +} + void ossl_rand_cleanup_entropy(ossl_unused OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len) { diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index a00514e52..13092eadf 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -564,7 +564,11 @@ static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent, if (dgbl == NULL) return NULL; +#ifdef SMTC_MODULE + name = dgbl->rng_name != NULL ? dgbl->rng_name : "HASH-DRBG"; +#else name = dgbl->rng_name != NULL ? dgbl->rng_name : "CTR-DRBG"; +#endif rand = EVP_RAND_fetch(libctx, name, dgbl->rng_propq); if (rand == NULL) { ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG); @@ -581,12 +585,22 @@ static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent, * Rather than trying to decode the DRBG settings, just pass them through * and rely on the other end to ignore those it doesn't care about. */ +#ifdef SMTC_MODULE + cipher = dgbl->rng_digest != NULL ? dgbl->rng_digest : "SM3"; + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_DIGEST, + cipher, 0); + + if (dgbl->rng_cipher != NULL) + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER, + dgbl->rng_cipher, 0); +#else cipher = dgbl->rng_cipher != NULL ? dgbl->rng_cipher : "AES-256-CTR"; *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER, cipher, 0); if (dgbl->rng_digest != NULL) *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_DIGEST, dgbl->rng_digest, 0); +#endif if (dgbl->rng_propq != NULL) *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, dgbl->rng_propq, 0); @@ -808,6 +822,11 @@ void ossl_random_add_conf_module(void) CONF_module_add("random", random_conf_init, random_conf_deinit); } +void RAND_set_entropy_source(unsigned int type) +{ + ossl_rand_pool_set_default_entropy_source(type); +} + int RAND_set_DRBG_type(OSSL_LIB_CTX *ctx, const char *drbg, const char *propq, const char *cipher, const char *digest) { diff --git a/crypto/rand/rand_pool.c b/crypto/rand/rand_pool.c index 55f14be60..4dae4a93c 100644 --- a/crypto/rand/rand_pool.c +++ b/crypto/rand/rand_pool.c @@ -16,6 +16,8 @@ #include "internal/thread_once.h" #include "crypto/rand_pool.h" +static unsigned int default_entropy_source = 0xFFFFFFFF; + /* * Allocate memory and initialize a new random pool */ @@ -49,6 +51,7 @@ RAND_POOL *ossl_rand_pool_new(int entropy_requested, int secure, pool->entropy_requested = entropy_requested; pool->secure = secure; + pool->entropy_source = default_entropy_source; return pool; err: @@ -410,3 +413,8 @@ int ossl_rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy) return 1; } + +void ossl_rand_pool_set_default_entropy_source(unsigned int source) +{ + default_entropy_source = source; +} diff --git a/crypto/sdf/build.info b/crypto/sdf/build.info new file mode 100644 index 000000000..b847b6587 --- /dev/null +++ b/crypto/sdf/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + sdf_lib.c sdf_meth.c \ No newline at end of file diff --git a/crypto/sdf/sdf_lib.c b/crypto/sdf/sdf_lib.c new file mode 100644 index 000000000..ce8824196 --- /dev/null +++ b/crypto/sdf/sdf_lib.c @@ -0,0 +1,416 @@ +/* + * Copyright 2024 The Tongsuo 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://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt + */ + +#include +#include +#include +#include "internal/thread_once.h" +#include "internal/dso.h" +#include "internal/sdf.h" +#include "sdf_local.h" + +#ifdef SDF_LIB +# ifdef SDF_LIB_SHARED +static DSO *sdf_dso = NULL; +# else +extern int SDF_OpenDevice(void **phDeviceHandle) __attribute__((weak)); +extern int SDF_CloseDevice(void *hDeviceHandle) __attribute__((weak)); +extern int SDF_OpenSession(void *hDeviceHandle, void **phSessionHandle) __attribute__((weak)); +extern int SDF_CloseSession(void *hSessionHandle) __attribute__((weak)); + +extern int SDF_GenerateRandom(void *hSessionHandle, unsigned int uiLength, + unsigned char *pucRandom) __attribute__((weak)); + +extern int SDF_GetPrivateKeyAccessRight(void *hSessionHandle, + unsigned int uiKeyIndex, unsigned char *pucPassword, + unsigned int uiPwdLength); + +extern int SDF_ReleasePrivateKeyAccessRight(void *hSessionHandle, + unsigned int uiKeyIndex); + +extern int SDF_ImportKeyWithISK_ECC(void *hSessionHandle, + unsigned int uiISKIndex, OSSL_ECCCipher *pucKey, + void **phKeyHandle) __attribute__((weak)); + +extern int SDF_ImportKeyWithKEK(void *hSessionHandle, + unsigned int uiAlgID, unsigned int uiKEKIndex, unsigned char *pucKey, + unsigned int puiKeyLength, void **phKeyHandle) __attribute__((weak)); + +extern int SDF_ExportSignPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, OSSL_ECCrefPublicKey *pucPublicKey) + __attribute__((weak)); + +extern int SDF_ExportEncPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, OSSL_ECCrefPublicKey *pucPublicKey) + __attribute__((weak)); + +extern int SDF_DestroyKey(void *hSessionHandle, void *hKeyHandle) + __attribute__((weak)); + +extern int SDF_InternalEncrypt_ECC(void *hSessionHandle, + unsigned int uiISKIndex, unsigned char *pucData, unsigned int uiDataLength, + OSSL_ECCCipher * pucEncData); + +extern int SDF_InternalDecrypt_ECC(void *hSessionHandle, + unsigned int uiISKIndex, OSSL_ECCCipher *pucEncData, + unsigned char *pucData, unsigned int *puiDataLength); + +extern int SDF_InternalSign_ECC(void * hSessionHandle, unsigned int uiISKIndex, + unsigned char * pucData, unsigned int uiDataLength, + OSSL_ECCSignature * pucSignature); + +extern int SDF_Encrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucData, + unsigned int uiDataLength, unsigned char *pucEncData, + unsigned int *puiEncDataLength) __attribute__((weak)); + +extern int SDF_Decrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucEncData, + unsigned int uiEncDataLength, unsigned char *pucData, + unsigned int *puiDataLength) __attribute__((weak)); + +extern int SDF_CalculateMAC(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucData, + unsigned int uiDataLength, unsigned char *pucMac, + unsigned int *puiMACLength) __attribute__((weak)); + +extern int SDFE_GenerateKey(void *hSessionHandle, uint8_t type, uint8_t no_kek, + uint32_t len, void **pkey_handle) __attribute__((weak)); +# endif + +static CRYPTO_ONCE sdf_lib_once = CRYPTO_ONCE_STATIC_INIT; +static SDF_METHOD sdfm; + +DEFINE_RUN_ONCE_STATIC(ossl_sdf_lib_init) +{ +# ifdef SDF_LIB_SHARED +# ifndef LIBSDF +# define LIBSDF "sdf" +# endif + + sdf_dso = DSO_load(NULL, LIBSDF, NULL, 0); + if (sdf_dso != NULL) { + sdfm.OpenDevice = DSO_bind_func(sdf_dso, "SDF_OpenDevice"); + sdfm.CloseDevice = DSO_bind_func(sdf_dso, "SDF_CloseDevice"); + sdfm.OpenSession = DSO_bind_func(sdf_dso, "SDF_OpenSession"); + sdfm.CloseSession = DSO_bind_func(sdf_dso, "SDF_CloseSession"); + sdfm.GenerateRandom = DSO_bind_func(sdf_dso, "SDF_GenerateRandom"); + sdfm.GetPrivateKeyAccessRight = DSO_bind_func(sdf_dso, "SDF_GetPrivateKeyAccessRight"); + sdfm.ReleasePrivateKeyAccessRight = DSO_bind_func(sdf_dso, "SDF_ReleasePrivateKeyAccessRight"); + sdfm.ImportKeyWithISK_ECC = DSO_bind_func(sdf_dso, "SDF_ImportKeyWithISK_ECC"); + sdfm.ImportKeyWithKEK = DSO_bind_func(sdf_dso, "SDF_ImportKeyWithKEK"); + sdfm.ExportSignPublicKey_ECC = DSO_bind_func(sdf_dso, "SDF_ExportSignPublicKey_ECC"); + sdfm.ExportEncPublicKey_ECC = DSO_bind_func(sdf_dso, "SDF_ExportEncPublicKey_ECC"); + sdfm.DestroyKey = DSO_bind_func(sdf_dso, "SDF_DestroyKey"); + sdfm.InternalEncrypt_ECC = DSO_bind_func(sdf_dso, "SDF_InternalEncrypt_ECC"); + sdfm.InternalDecrypt_ECC = DSO_bind_func(sdf_dso, "SDF_InternalDecrypt_ECC"); + sdfm.InternalSign_ECC = DSO_bind_func(sdf_dso, "SDF_InternalSign_ECC"); + sdfm.Encrypt = DSO_bind_func(sdf_dso, "SDF_Encrypt"); + sdfm.Decrypt = DSO_bind_func(sdf_dso, "SDF_Decrypt"); + sdfm.CalculateMAC = DSO_bind_func(sdf_dso, "SDF_CalculateMAC"); + sdfm.GenerateKey = DSO_bind_func(sdf_dso, "SDFE_GenerateKey"); + } +# else + sdfm.OpenDevice = SDF_OpenDevice; + sdfm.CloseDevice = SDF_CloseDevice; + sdfm.OpenSession = SDF_OpenSession; + sdfm.CloseSession = SDF_CloseSession; + sdfm.GenerateRandom = SDF_GenerateRandom; + sdfm.GetPrivateKeyAccessRight = SDF_GetPrivateKeyAccessRight; + sdfm.ReleasePrivateKeyAccessRight = SDF_ReleasePrivateKeyAccessRight; + sdfm.ImportKeyWithISK_ECC = SDF_ImportKeyWithISK_ECC; + sdfm.ImportKeyWithKEK = SDF_ImportKeyWithKEK; + sdfm.ExportSignPublicKey_ECC = SDF_ExportSignPublicKey_ECC; + sdfm.ExportEncPublicKey_ECC = SDF_ExportEncPublicKey_ECC; + sdfm.DestroyKey = SDF_DestroyKey; + sdfm.InternalEncrypt_ECC = SDF_InternalEncrypt_ECC; + sdfm.InternalDecrypt_ECC = SDF_InternalDecrypt_ECC; + sdfm.InternalSign_ECC = SDF_InternalSign_ECC; + sdfm.Encrypt = SDF_Encrypt; + sdfm.Decrypt = SDF_Decrypt; + sdfm.CalculateMAC = SDF_CalculateMAC; + sdfm.GenerateKey = SDFE_GenerateKey; +# endif + return 1; +} +#endif + +void ossl_sdf_lib_cleanup(void) +{ +#ifdef SDF_LIB_SHARED + DSO_free(sdf_dso); + sdf_dso = NULL; +#endif +} + +static const SDF_METHOD *sdf_get_method(void) +{ + const SDF_METHOD *meth = &ts_sdf_meth; + +#ifdef SDF_LIB + if (RUN_ONCE(&sdf_lib_once, ossl_sdf_lib_init)) + meth = &sdfm; +#endif + + return meth; +} + +int TSAPI_SDF_OpenDevice(void **phDeviceHandle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->OpenDevice == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->OpenDevice(phDeviceHandle); +} + +int TSAPI_SDF_CloseDevice(void *hDeviceHandle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (hDeviceHandle == NULL) + return OSSL_SDR_OK; + + if (meth == NULL || meth->CloseDevice == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->CloseDevice(hDeviceHandle); +} + +int TSAPI_SDF_OpenSession(void *hDeviceHandle, void **phSessionHandle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->OpenSession == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->OpenSession(hDeviceHandle, phSessionHandle); +} + +int TSAPI_SDF_CloseSession(void *hSessionHandle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (hSessionHandle == NULL) + return OSSL_SDR_OK; + + if (meth == NULL || meth->CloseSession == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->CloseSession(hSessionHandle); +} + +int TSAPI_SDF_GenerateRandom(void *hSessionHandle, unsigned int uiLength, + unsigned char *pucRandom) +{ +#define MAX_RANDOM_LEN (2048) + int ret; + unsigned int len; + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->GenerateRandom == NULL) + return OSSL_SDR_NOTSUPPORT; + + do { + if (uiLength > MAX_RANDOM_LEN) + len = MAX_RANDOM_LEN; + else + len = uiLength; + + if ((ret = meth->GenerateRandom(hSessionHandle, len, pucRandom)) != 0) + return ret; + + uiLength -= len; + pucRandom += len; + } while (uiLength > 0); + + return OSSL_SDR_OK; +} + +int TSAPI_SDF_GetPrivateKeyAccessRight(void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucPassword, + unsigned int uiPwdLength) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->GetPrivateKeyAccessRight == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->GetPrivateKeyAccessRight(hSessionHandle, uiKeyIndex, + pucPassword, uiPwdLength); +} + +int TSAPI_SDF_ReleasePrivateKeyAccessRight(void *hSessionHandle, + unsigned int uiKeyIndex) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->ReleasePrivateKeyAccessRight == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->ReleasePrivateKeyAccessRight(hSessionHandle, uiKeyIndex); +} + +int TSAPI_SDF_ImportKeyWithISK_ECC(void *hSessionHandle, + unsigned int uiISKIndex, + OSSL_ECCCipher *pucKey, + void **phKeyHandle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->ImportKeyWithISK_ECC == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->ImportKeyWithISK_ECC(hSessionHandle, uiISKIndex, pucKey, + phKeyHandle); +} + +int TSAPI_SDF_ImportKeyWithKEK(void *hSessionHandle, unsigned int uiAlgID, + unsigned int uiKEKIndex, unsigned char *pucKey, + unsigned int puiKeyLength, void **phKeyHandle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->ImportKeyWithKEK == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->ImportKeyWithKEK(hSessionHandle, uiAlgID, uiKEKIndex, pucKey, + puiKeyLength, phKeyHandle); +} + +int TSAPI_SDF_Encrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, + unsigned char *pucData, unsigned int uiDataLength, + unsigned char *pucEncData, unsigned int *puiEncDataLength) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->Encrypt == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->Encrypt(hSessionHandle, hKeyHandle, uiAlgID, pucIV, pucData, + uiDataLength, pucEncData, puiEncDataLength); +} + +int TSAPI_SDF_Decrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, + unsigned char *pucEncData, unsigned int uiEncDataLength, + unsigned char *pucData, unsigned int *puiDataLength) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->Decrypt == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->Decrypt(hSessionHandle, hKeyHandle, uiAlgID, pucIV, + pucEncData, uiEncDataLength, pucData, puiDataLength); +} + +int TSAPI_SDF_CalculateMAC(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, + unsigned char *pucData, unsigned int uiDataLength, + unsigned char *pucMac, unsigned int *puiMACLength) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->CalculateMAC == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->CalculateMAC(hSessionHandle, hKeyHandle, uiAlgID, pucIV, + pucData, uiDataLength, pucMac, puiMACLength); +} + +int TSAPI_SDF_GenerateKey(void *hSessionHandle, uint8_t type, uint8_t no_kek, + uint32_t len, void **pkey_handle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->GenerateKey == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->GenerateKey(hSessionHandle, type, no_kek, len, pkey_handle); +} + +int TSAPI_SDF_DestroyKey(void *hSessionHandle, void *hKeyHandle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->DestroyKey == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->DestroyKey(hSessionHandle, hKeyHandle); +} + +int TSAPI_SDF_ExportSignPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, + OSSL_ECCrefPublicKey *pucPublicKey) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->ExportSignPublicKey_ECC == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->ExportSignPublicKey_ECC(hSessionHandle, uiKeyIndex, pucPublicKey); +} + +int TSAPI_SDF_ExportEncPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, + OSSL_ECCrefPublicKey *pucPublicKey) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->ExportEncPublicKey_ECC == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->ExportEncPublicKey_ECC(hSessionHandle, uiKeyIndex, pucPublicKey); +} + +int TSAPI_SDF_InternalEncrypt_ECC(void *hSessionHandle, unsigned int uiISKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + OSSL_ECCCipher *pucEncData) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->InternalEncrypt_ECC == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->InternalEncrypt_ECC(hSessionHandle, uiISKIndex, pucData, + uiDataLength, pucEncData); +} + +int TSAPI_SDF_InternalDecrypt_ECC(void *hSessionHandle, unsigned int uiISKIndex, + OSSL_ECCCipher *pucEncData, + unsigned char *pucData, + unsigned int *puiDataLength) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->InternalDecrypt_ECC == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->InternalDecrypt_ECC(hSessionHandle, uiISKIndex, pucEncData, + pucData, puiDataLength); +} + +int TSAPI_SDF_InternalSign_ECC(void *hSessionHandle, unsigned int uiISKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + OSSL_ECCSignature *pucSignature) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->InternalSign_ECC == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->InternalSign_ECC(hSessionHandle, uiISKIndex, pucData, + uiDataLength, pucSignature); +} diff --git a/crypto/sdf/sdf_local.h b/crypto/sdf/sdf_local.h new file mode 100644 index 000000000..f2187c504 --- /dev/null +++ b/crypto/sdf/sdf_local.h @@ -0,0 +1,130 @@ +/* + * Copyright 2024 The Tongsuo 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://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt + */ + +#ifndef OSSL_CRYPTO_SDF_LOCAL_H +# define OSSL_CRYPTO_SDF_LOCAL_H + +# include +# include + +# define OSSL_ECCref_MAX_BITS 512 +# define OSSL_ECCref_MAX_LEN ((OSSL_ECCref_MAX_BITS + 7) / 8) + +# pragma pack(1) +struct OSSL_ECCrefPrivateKey_st { + unsigned int bits; + unsigned char K[OSSL_ECCref_MAX_LEN]; +}; + +struct OSSL_ECCrefPublicKey_st{ + unsigned int bits; + unsigned char x[OSSL_ECCref_MAX_LEN]; + unsigned char y[OSSL_ECCref_MAX_LEN]; +}; + +struct OSSL_ECCCipher_st { + unsigned char x[OSSL_ECCref_MAX_LEN]; + unsigned char y[OSSL_ECCref_MAX_LEN]; + unsigned char M[32]; + unsigned int L; + unsigned char C[1]; +}; + +struct OSSL_ECCSignature_st { + unsigned char r[OSSL_ECCref_MAX_LEN]; + unsigned char s[OSSL_ECCref_MAX_LEN]; +}; +# pragma pack() + +typedef int (*SDF_OpenDevice_fn)(void **phDeviceHandle); +typedef int (*SDF_CloseDevice_fn)(void *hDeviceHandle); +typedef int (*SDF_OpenSession_fn)(void *hDeviceHandle, void **phSessionHandle); +typedef int (*SDF_CloseSession_fn)(void *hSessionHandle); +typedef int (*SDF_GenerateRandom_fn)(void *hSessionHandle, + unsigned int uiLength, unsigned char *pucRandom); + +typedef int (*SDF_GetPrivateKeyAccessRight_fn)(void *hSessionHandle, + unsigned int uiKeyIndex, unsigned char *pucPassword, + unsigned int uiPwdLength); + +typedef int (*SDF_ReleasePrivateKeyAccessRight_fn)(void *hSessionHandle, + unsigned int uiKeyIndex); + +typedef int (*SDF_ImportKeyWithISK_ECC_fn)(void *hSessionHandle, + unsigned int uiISKIndex, OSSL_ECCCipher *pucKey, void **phKeyHandle); + +typedef int (*SDF_ImportKeyWithKEK_fn)(void *hSessionHandle, + unsigned int uiAlgID, unsigned int uiKEKIndex, unsigned char *pucKey, + unsigned int puiKeyLength, void **phKeyHandle); + +typedef int (*SDF_DestroyKey_fn)(void *hSessionHandle, void *hKeyHandle); + +typedef int (*SDF_Encrypt_fn)(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucData, + unsigned int uiDataLength, unsigned char *pucEncData, + unsigned int *puiEncDataLength); + +typedef int (*SDF_Decrypt_fn)(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucEncData, + unsigned int uiEncDataLength, unsigned char *pucData, + unsigned int *puiDataLength); + +typedef int (*SDF_CalculateMAC_fn)(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucData, + unsigned int uiDataLength, unsigned char *pucMac, + unsigned int *puiMACLength); + +typedef int (*SDF_GenerateKey_fn)(void *hSessionHandle, uint8_t type, + uint8_t no_kek, uint32_t len, void **pkey_handle); + +typedef int (*SDF_ExportSignPublicKey_ECC_fn)(void *hSessionHandle, + unsigned int uiKeyIndex, OSSL_ECCrefPublicKey *pucPublicKey); + +typedef int (*SDF_ExportEncPublicKey_ECC_fn)(void *hSessionHandle, + unsigned int uiKeyIndex, OSSL_ECCrefPublicKey *pucPublicKey); + +typedef int (*SDF_InternalEncrypt_ECC_fn)(void *hSessionHandle, + unsigned int uiISKIndex, unsigned char *pucData, unsigned int uiDataLength, + OSSL_ECCCipher *pucEncData); +typedef int (*SDF_InternalDecrypt_ECC_fn)(void *hSessionHandle, + unsigned int uiISKIndex, OSSL_ECCCipher *pucEncData, unsigned char *pucData, + unsigned int *puiDataLength); + +typedef int (*SDF_InternalSign_ECC_fn)(void *hSessionHandle, + unsigned int uiISKIndex, unsigned char *pucData, unsigned int uiDataLength, + OSSL_ECCSignature *pucSignature); +/* + * Returns 0 for success, others for error code + */ +struct sdf_method_st { + SDF_OpenDevice_fn OpenDevice; + SDF_CloseDevice_fn CloseDevice; + SDF_OpenSession_fn OpenSession; + SDF_CloseSession_fn CloseSession; + SDF_GenerateRandom_fn GenerateRandom; + SDF_GetPrivateKeyAccessRight_fn GetPrivateKeyAccessRight; + SDF_ReleasePrivateKeyAccessRight_fn ReleasePrivateKeyAccessRight; + SDF_ImportKeyWithISK_ECC_fn ImportKeyWithISK_ECC; + SDF_ImportKeyWithKEK_fn ImportKeyWithKEK; + SDF_ExportSignPublicKey_ECC_fn ExportSignPublicKey_ECC; + SDF_ExportEncPublicKey_ECC_fn ExportEncPublicKey_ECC; + SDF_DestroyKey_fn DestroyKey; + SDF_InternalEncrypt_ECC_fn InternalEncrypt_ECC; + SDF_InternalDecrypt_ECC_fn InternalDecrypt_ECC; + SDF_InternalSign_ECC_fn InternalSign_ECC; + SDF_Encrypt_fn Encrypt; + SDF_Decrypt_fn Decrypt; + SDF_CalculateMAC_fn CalculateMAC; + + /* SDF Ext API */ + SDF_GenerateKey_fn GenerateKey; +}; + +extern SDF_METHOD ts_sdf_meth; +#endif diff --git a/crypto/sdf/sdf_meth.c b/crypto/sdf/sdf_meth.c new file mode 100644 index 000000000..d28bc8f8b --- /dev/null +++ b/crypto/sdf/sdf_meth.c @@ -0,0 +1,168 @@ +/* + * Copyright 2024 The Tongsuo 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://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt + */ + +#include +#include +#include "sdf_local.h" + +static int x_OpenDevice(void **phDeviceHandle) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_CloseDevice(void *hDeviceHandle) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_OpenSession(void *hDeviceHandle, void **phSessionHandle) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_CloseSession(void *hSessionHandle) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_GenerateRandom(void *hSessionHandle, unsigned int uiLength, + unsigned char *pucRandom) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_GetPrivateKeyAccessRight(void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucPassword, + unsigned int uiPwdLength) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_ReleasePrivateKeyAccessRight(void *hSessionHandlek, + unsigned int uiKeyIndex) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_ImportKeyWithISK_ECC(void *hSessionHandle, + unsigned int uiISKIndex, + OSSL_ECCCipher *pucKey, + void **phKeyHandle) +{ + return OSSL_SDR_NOTSUPPORT; +} + + +static int x_ImportKeyWithKEK(void *hSessionHandle, unsigned int uiAlgID, + unsigned int uiKEKIndex, unsigned char *pucKey, + unsigned int puiKeyLength, void **phKeyHandle) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_ExportSignPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, + OSSL_ECCrefPublicKey *pucPublicKey) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_ExportEncPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, + OSSL_ECCrefPublicKey *pucPublicKey) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_DestroyKey(void *hSessionHandle, void *hKeyHandle) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_InternalEncrypt_ECC(void *hSessionHandle, unsigned int uiISKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + OSSL_ECCCipher *pucEncData) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_InternalDecrypt_ECC(void *hSessionHandle, unsigned int uiISKIndex, + OSSL_ECCCipher *pucEncData, + unsigned char *pucData, + unsigned int *puiDataLength) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_InternalSign_ECC(void *hSessionHandle, unsigned int uiISKIndex, + unsigned char * pucData, + unsigned int uiDataLength, + OSSL_ECCSignature *pucSignature) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_Encrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, + unsigned char *pucData, + unsigned int uiDataLength, + unsigned char *pucEncData, + unsigned int *puiEncDataLength) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_Decrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, + unsigned char *pucEncData, unsigned int uiEncDataLength, + unsigned char *pucData, + unsigned int *puiDataLength) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_CalculateMAC(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, + unsigned char *pucData, unsigned int uiDataLength, + unsigned char *pucMac, unsigned int *puiMACLength) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_GenerateKey(void *hSessionHandle, uint8_t type, uint8_t no_kek, + uint32_t len, void **pkey_handle) +{ + return OSSL_SDR_NOTSUPPORT; +} + +SDF_METHOD ts_sdf_meth = { + x_OpenDevice, + x_CloseDevice, + x_OpenSession, + x_CloseSession, + x_GenerateRandom, + x_GetPrivateKeyAccessRight, + x_ReleasePrivateKeyAccessRight, + x_ImportKeyWithISK_ECC, + x_ImportKeyWithKEK, + x_ExportSignPublicKey_ECC, + x_ExportEncPublicKey_ECC, + x_DestroyKey, + x_InternalEncrypt_ECC, + x_InternalDecrypt_ECC, + x_InternalSign_ECC, + x_Encrypt, + x_Decrypt, + x_CalculateMAC, + + /* SDF Ext API */ + x_GenerateKey, +}; diff --git a/crypto/sm2/sm2_crypt.c b/crypto/sm2/sm2_crypt.c index 177df5bac..d899318d3 100644 --- a/crypto/sm2/sm2_crypt.c +++ b/crypto/sm2/sm2_crypt.c @@ -392,6 +392,62 @@ int ossl_sm2_decrypt(const EC_KEY *key, return rc; } +unsigned char *ossl_sm2_ciphertext_encode(const BIGNUM *C1x, const BIGNUM *C1y, + const uint8_t *C2_data, size_t C2_len, + const uint8_t *C3_data, size_t C3_len, + size_t *ciphertext_len) +{ + unsigned char *ciphertext_buf = NULL; + struct SM2_Ciphertext_st ctext_struct; + int ciphertext_leni; + + if (C1x == NULL || C1y == NULL || C2_data == NULL || C3_data == NULL) { + ERR_raise(ERR_LIB_SM2, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + memset(&ctext_struct, 0, sizeof(ctext_struct)); + + ctext_struct.C1x = (BIGNUM *)C1x; + ctext_struct.C1y = (BIGNUM *)C1y; + ctext_struct.C2 = ASN1_OCTET_STRING_new(); + + if (ctext_struct.C2 == NULL) { + ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + goto end; + } + + if (!ASN1_OCTET_STRING_set(ctext_struct.C2, C2_data, C2_len)) + goto end; + + ctext_struct.C3 = ASN1_OCTET_STRING_new(); + + if (ctext_struct.C3 == NULL) { + ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + goto end; + } + + if (!ASN1_OCTET_STRING_set(ctext_struct.C3, C3_data, C3_len)) + goto end; + + ciphertext_leni = i2d_SM2_Ciphertext(&ctext_struct, &ciphertext_buf); + /* Ensure cast to size_t is safe */ + if (ciphertext_leni < 0) { + ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); + goto end; + } + *ciphertext_len = (size_t)ciphertext_leni; + + end: + if (ctext_struct.C2 != NULL) + ASN1_OCTET_STRING_free(ctext_struct.C2); + + if (ctext_struct.C3 != NULL) + ASN1_OCTET_STRING_free(ctext_struct.C3); + + return ciphertext_buf; +} + int ossl_sm2_ciphertext_decode(const uint8_t *ciphertext, size_t ciphertext_len, EC_POINT **C1p, uint8_t **C2_data, size_t *C2_len, uint8_t **C3_data, diff --git a/crypto/trace.c b/crypto/trace.c index d790409a2..051b72425 100644 --- a/crypto/trace.c +++ b/crypto/trace.c @@ -138,7 +138,10 @@ static const struct trace_category_st trace_categories[] = { TRACE_CATEGORY_(STORE), TRACE_CATEGORY_(DECODER), TRACE_CATEGORY_(ENCODER), - TRACE_CATEGORY_(REF_COUNT) + TRACE_CATEGORY_(REF_COUNT), +#ifdef SMTC_MODULE + TRACE_CATEGORY_(SMTC), +#endif }; const char *OSSL_trace_get_category_name(int num) diff --git a/crypto/tsapi/build.info b/crypto/tsapi/build.info new file mode 100644 index 000000000..703ddc366 --- /dev/null +++ b/crypto/tsapi/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + tsapi_lib.c \ No newline at end of file diff --git a/crypto/tsapi/tsapi_lib.c b/crypto/tsapi/tsapi_lib.c new file mode 100644 index 000000000..cf66021ab --- /dev/null +++ b/crypto/tsapi/tsapi_lib.c @@ -0,0 +1,1322 @@ +/* + * Copyright 2024 The Tongsuo 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://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt + */ + +#include "internal/deprecated.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal/e_os.h" +#include "crypto/rand.h" +#include "crypto/sm2.h" +#include "../sdf/sdf_local.h" +#ifdef SDF_LIB +# include "sdfe_api.h" +#endif + +unsigned char *TSAPI_GetEntropy(int entropy, size_t *outlen) +{ + unsigned char *out = NULL; + size_t len; + + len = ossl_rand_get_entropy(NULL, &out, entropy, entropy, entropy * 4); + if (len == 0) { + *outlen = 0; + return NULL; + } + + *outlen = len; + return out; +} + +void TSAPI_FreeEntropy(unsigned char *ent, size_t len) +{ + ossl_rand_cleanup_entropy(NULL, ent, len); +} + +unsigned char *TSAPI_RandBytes(size_t len) +{ + unsigned char *buf = OPENSSL_malloc(len); + + if (buf == NULL) + return NULL; + + if (RAND_bytes(buf, (int)len) <= 0) { + OPENSSL_free(buf); + return NULL; + } + + return buf; +} + +char *TSAPI_Version(void) +{ + int ret; + int buflen = 1 + strlen(OpenSSL_version(TONGSUO_VERSION)) + 1 +#ifdef SMTC_MODULE + + strlen(OpenSSL_version(TONGSUO_SMTC_INFO)) + 1 +#endif + ; + char *buf = OPENSSL_malloc(buflen); + + ret = BIO_snprintf((char *)buf, buflen, "%s\n", + OpenSSL_version(TONGSUO_VERSION)); + if (ret < 0) { + OPENSSL_free(buf); + return NULL; + } + +#ifdef SMTC_MODULE + ret = BIO_snprintf(buf + ret, buflen - ret, "%s\n", + OpenSSL_version(TONGSUO_SMTC_INFO)); + if (ret < 0) { + OPENSSL_free(buf); + return NULL; + } +#endif + + return buf; +} + +#ifndef OPENSSL_NO_SM2 +int TSAPI_DelSm2KeyWithIndex(int index, int sign, const char *user, + const char *password) +{ + int ok = 0; +#ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_login_arg_t login_arg; + int area; + + if (sign) { + area = SDFE_ASYM_KEY_AREA_SIGN; + } else { + area = SDFE_ASYM_KEY_AREA_ENC; + } + + memset(&login_arg, 0, sizeof(login_arg)); + + login_arg.passwd = (uint8_t *)password; + if (password) + login_arg.passwd_len = strlen(password); + else + login_arg.passwd_len = 0; + + if (user) { + if (strlen(user) >= sizeof(login_arg.name)) + return 0; + + strcpy((char *)login_arg.name, user); + } + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + if (SDFE_DelECCKey(hSessionHandle, area, index) + != OSSL_SDR_OK) + goto end; + + ok = 1; +end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return ok; +} + +int TSAPI_GenerateSM2KeyWithIndex(int index, int sign, const char *user, + const char *password) +{ + int ok = 0; +#ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_login_arg_t login_arg; + int area; + + if (sign) + area = SDFE_ASYM_KEY_AREA_SIGN; + else + area = SDFE_ASYM_KEY_AREA_ENC; + + memset(&login_arg, 0, sizeof(login_arg)); + + login_arg.passwd = (uint8_t *)password; + if (password) + login_arg.passwd_len = strlen(password); + else + login_arg.passwd_len = 0; + + if (user) { + if (strlen(user) >= sizeof(login_arg.name)) + return 0; + + strcpy((char *)login_arg.name, user); + } + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + if (SDFE_GenECCKey(hSessionHandle, area, index, 0, NULL) != OSSL_SDR_OK) + goto end; + + ok = 1; +end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return ok; +} + +EVP_PKEY *TSAPI_EVP_PKEY_new_from_ECCrefKey(const OSSL_ECCrefPublicKey *pubkey, + const OSSL_ECCrefPrivateKey *privkey) +{ + int ok = 0; + EC_KEY *eckey = NULL; + EC_GROUP *group = NULL; + BN_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + BIGNUM *x = NULL, *y = NULL; + int bytes; + + if (pubkey == NULL) + return NULL; + + eckey = EC_KEY_new(); + if (eckey == NULL) + return NULL; + + group = EC_GROUP_new_by_curve_name(NID_sm2); + if (group == NULL) + goto end; + + if (!EC_KEY_set_group(eckey, group)) + goto end; + + bytes = (pubkey->bits + 7) / 8; + + ctx = BN_CTX_new(); + if (ctx == NULL) + goto end; + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + + if (BN_bin2bn(pubkey->x + sizeof(pubkey->x) - bytes, bytes, x) == NULL) + goto end; + + if (BN_bin2bn(pubkey->y + sizeof(pubkey->y) - bytes, bytes, y) == NULL) + goto end; + + if (!EC_KEY_set_public_key_affine_coordinates(eckey, x, y)) + goto end; + + if (privkey) { + bytes = (privkey->bits + 7) / 8; + if (BN_bin2bn(privkey->K + sizeof(privkey->K) - bytes, bytes, x) == NULL) + goto end; + + if (!EC_KEY_set_private_key(eckey, x)) + goto end; + } + + pkey = EVP_PKEY_new(); + if (pkey == NULL) + goto end; + + if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) + goto end; + + eckey = NULL; + + ok = 1; +end: + if (!ok) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + BN_CTX_end(ctx); + BN_CTX_free(ctx); + EC_GROUP_free(group); + EC_KEY_free(eckey); + return pkey; +} + +OSSL_ECCrefPublicKey *TSAPI_EVP_PKEY_get_ECCrefPublicKey(const EVP_PKEY *pkey) +{ + int ok = 0; + const EC_KEY *eckey = NULL; + const EC_GROUP *group = NULL; + const EC_POINT *point = NULL; + BIGNUM *x = NULL, *y = NULL; + BN_CTX *ctx = NULL; + OSSL_ECCrefPublicKey *outkey = NULL; + + if (pkey == NULL) + return NULL; + + eckey = EVP_PKEY_get0_EC_KEY(pkey); + if (eckey == NULL) + return NULL; + + group = EC_KEY_get0_group(eckey); + point = EC_KEY_get0_public_key(eckey); + if (group == NULL || point == NULL) + return NULL; + + ctx = BN_CTX_new(); + if (ctx == NULL) + return NULL; + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) + goto end; + + if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx)) + goto end; + + outkey = OPENSSL_zalloc(sizeof(*outkey)); + if (outkey == NULL) + goto end; + + outkey->bits = EVP_PKEY_get_bits(pkey); + + if (BN_bn2bin(x, outkey->x + sizeof(outkey->x) - BN_num_bytes(x)) < 0) + goto end; + if (BN_bn2bin(y, outkey->y + sizeof(outkey->y) - BN_num_bytes(y)) < 0) + goto end; + + ok = 1; +end: + if (!ok) { + OPENSSL_free(outkey); + outkey = NULL; + } + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return outkey; +} + +OSSL_ECCrefPrivateKey *TSAPI_EVP_PKEY_get_ECCrefPrivateKey(const EVP_PKEY *pkey) +{ + int ok = 0; + const EC_KEY *eckey = NULL; + const BIGNUM *priv = NULL; + OSSL_ECCrefPrivateKey *outkey = NULL; + + if (pkey == NULL) + return NULL; + + eckey = EVP_PKEY_get0_EC_KEY(pkey); + if (eckey == NULL) + return NULL; + + priv = EC_KEY_get0_private_key(eckey); + if (priv == NULL) + return NULL; + + outkey = OPENSSL_zalloc(sizeof(*outkey)); + if (outkey == NULL) + goto end; + + outkey->bits = EVP_PKEY_get_bits(pkey); + + if (BN_bn2bin(priv, outkey->K + sizeof(outkey->K) - BN_num_bytes(priv)) < 0) + goto end; + + ok = 1; +end: + if (!ok) { + OPENSSL_free(outkey); + outkey = NULL; + } + return outkey; +} + +int TSAPI_ImportSM2Key(int index, int sign, const char *user, + const char *password, const EVP_PKEY *sm2_pkey) +{ + int ok = 0; +#ifdef SDF_LIB + int area; + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + OSSL_ECCrefPrivateKey *privkey = NULL; + OSSL_ECCrefPublicKey *pubkey = NULL; + sdfe_asym_key_ecc_t sm2_key; + sdfe_login_arg_t login_arg; + + memset(&login_arg, 0, sizeof(login_arg)); + memset(&sm2_key, 0, sizeof(sm2_key)); + + login_arg.passwd = (uint8_t *)password; + if (password) + login_arg.passwd_len = strlen(password); + else + login_arg.passwd_len = 0; + + if (user) { + if (strlen(user) >= sizeof(login_arg.name)) + return 0; + + strcpy((char *)login_arg.name, user); + } + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + if (sign) + area = SDFE_ASYM_KEY_AREA_SIGN; + else + area = SDFE_ASYM_KEY_AREA_ENC; + + privkey = TSAPI_EVP_PKEY_get_ECCrefPrivateKey(sm2_pkey); + if (privkey == NULL) + goto end; + + pubkey = TSAPI_EVP_PKEY_get_ECCrefPublicKey(sm2_pkey); + if (pubkey == NULL) + goto end; + + sm2_key.area = area; + sm2_key.index = index; + sm2_key.type = SDFE_ASYM_KEY_TYPE_SM2; + sm2_key.privkey_bits = 256; + sm2_key.privkey_len = sm2_key.privkey_bits >> 3; + sm2_key.pubkey_bits = 256; + sm2_key.pubkey_len = (sm2_key.pubkey_bits >> 3) << 1; + + memcpy(sm2_key.pubkey, pubkey, sizeof(*pubkey)); + memcpy(sm2_key.privkey, privkey, sizeof(*privkey)); + + if (SDFE_ImportECCKey(hSessionHandle, &sm2_key, NULL) + != OSSL_SDR_OK) + goto end; + + ok = 1; +end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return ok; +} + +int TSAPI_ImportSM2KeyWithEvlp(int index, int sign, const char *user, + const char *password, unsigned char *key, + size_t keylen, unsigned char *dek, size_t deklen) +{ + int ok = 0; +#ifdef SDF_LIB + int area; + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_asym_key_ecc_t sm2_key; + sdfe_sym_key_evlp_t sym_key_evlp; + sdfe_login_arg_t login_arg; + + memset(&login_arg, 0, sizeof(login_arg)); + memset(&sm2_key, 0, sizeof(sm2_key)); + memset(&sym_key_evlp, 0, sizeof(sym_key_evlp)); + + login_arg.passwd = (uint8_t *)password; + if (password) + login_arg.passwd_len = strlen(password); + else + login_arg.passwd_len = 0; + + if (user) { + if (strlen(user) >= sizeof(login_arg.name)) + return 0; + + strcpy((char *)login_arg.name, user); + } + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + sym_key_evlp.flags = SDFE_SYM_KEY_EVLP_F_IMPORT_KEY_INDEX_VALID; + sym_key_evlp.asym_key_type = SDFE_ASYM_KEY_TYPE_SM2; + sym_key_evlp.sym_key_type = SDFE_SYM_KEY_TYPE_SM4; + sym_key_evlp.sym_key_len = 16; + sym_key_evlp.asym_key_index = 0; + + if (deklen > sizeof(sym_key_evlp.data)) + goto end; + sym_key_evlp.data_len = deklen; + memcpy(sym_key_evlp.data, dek, deklen); + + if (sign) + area = SDFE_ASYM_KEY_AREA_SIGN; + else + area = SDFE_ASYM_KEY_AREA_ENC; + + sm2_key.area = area; + sm2_key.index = index; + sm2_key.type = SDFE_ASYM_KEY_TYPE_SM2; + sm2_key.privkey_bits = 256; + sm2_key.privkey_len = sm2_key.privkey_bits >> 3; + sm2_key.pubkey_bits = 256; + sm2_key.pubkey_len = (sm2_key.pubkey_bits >> 3) << 1; + + if (keylen != sizeof(sm2_key.privkey) + sizeof(sm2_key.pubkey)) + goto end; + + memcpy(sm2_key.pubkey, key, sizeof(sm2_key.pubkey)); + memcpy(sm2_key.privkey, key + sizeof(sm2_key.pubkey), + sizeof(sm2_key.privkey)); + + if (SDFE_ImportECCKeyWithEvlp(hSessionHandle, &sm2_key, &sym_key_evlp, NULL) + != OSSL_SDR_OK) + goto end; + + ok = 1; +end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return ok; +} + +int TSAPI_ExportSM2KeyWithEvlp(int index, int sign, const char *user, + const char *password, EVP_PKEY *sm2_pkey, + unsigned char **priv, size_t *privlen, + unsigned char **pub, size_t *publen, + unsigned char **outevlp, size_t *outevlplen) + +{ + int ok = 0; +#ifdef SDF_LIB + int area; + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + OSSL_ECCrefPublicKey *pubkey = NULL; + sdfe_asym_key_ecc_t sm2_key; + sdfe_sym_key_evlp_t sym_key_evlp; + sdfe_login_arg_t login_arg; + + if (sign) + area = SDFE_ASYM_KEY_AREA_SIGN; + else + area = SDFE_ASYM_KEY_AREA_ENC; + + memset(&login_arg, 0, sizeof(login_arg)); + memset(&sm2_key, 0, sizeof(sm2_key)); + memset(&sym_key_evlp, 0, sizeof(sym_key_evlp)); + + login_arg.passwd = (uint8_t *)password; + if (password) + login_arg.passwd_len = strlen(password); + else + login_arg.passwd_len = 0; + + if (user) { + if (strlen(user) >= sizeof(login_arg.name)) + return 0; + + strcpy((char *)login_arg.name, user); + } + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + sm2_key.area = area; + sm2_key.index = index; + sm2_key.type = SDFE_ASYM_KEY_TYPE_SM2; + + sym_key_evlp.asym_key_type = SDFE_ASYM_KEY_TYPE_SM2; + sym_key_evlp.sym_key_type = SDFE_SYM_KEY_TYPE_SM4; + sym_key_evlp.sym_key_len = 16; + + pubkey = TSAPI_EVP_PKEY_get_ECCrefPublicKey(sm2_pkey); + if (pubkey == NULL) + goto end; + + if (SDFE_ExportECCKeyWithEvlp(hSessionHandle, &sm2_key, &sym_key_evlp, + (void *)pubkey) != OSSL_SDR_OK) + goto end; + + *outevlp = OPENSSL_malloc(sym_key_evlp.data_len); + if (*outevlp == NULL) + goto end; + + memcpy(*outevlp, sym_key_evlp.data, sym_key_evlp.data_len); + *outevlplen = sym_key_evlp.data_len; + + *priv = OPENSSL_malloc(sizeof(sm2_key.privkey)); + if (*priv == NULL) + goto end; + + memcpy(*priv, sm2_key.privkey, sizeof(sm2_key.privkey)); + *privlen = sizeof(sm2_key.privkey); + + *pub = OPENSSL_malloc(sizeof(sm2_key.pubkey)); + if (*pub == NULL) + goto end; + + memcpy(*pub, sm2_key.pubkey, sizeof(sm2_key.pubkey)); + *publen = sizeof(sm2_key.pubkey); + + ok = 1; +end: + if (!ok) { + OPENSSL_free(*priv); + OPENSSL_free(*pub); + OPENSSL_free(*outevlp); + *priv = NULL; + *pub = NULL; + *outevlp = NULL; + *privlen = 0; + *publen = 0; + *outevlplen = 0; + } + + OPENSSL_free(pubkey); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return ok; +} + +EVP_PKEY *TSAPI_ExportSM2KeyWithIndex(int index, int sign, const char *user, + const char *password) +{ + EVP_PKEY *pkey = NULL; +#ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_login_arg_t login_arg; + int area; + OSSL_ECCrefPrivateKey privkey; + OSSL_ECCrefPublicKey pubkey; + + if (sign) + area = SDFE_ASYM_KEY_AREA_SIGN; + else + area = SDFE_ASYM_KEY_AREA_ENC; + + memset(&login_arg, 0, sizeof(login_arg)); + + if (user) { + if (strlen(user) >= sizeof(login_arg.name)) + return 0; + + strcpy((char *)login_arg.name, user); + } + + login_arg.passwd = (uint8_t *)password; + if (password) + login_arg.passwd_len = strlen(password); + else + login_arg.passwd_len = 0; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + if (SDFE_ExportECCPrivKey(hSessionHandle, area, index, 0, NULL, + (ECCrefPrivateKey *)&privkey) != OSSL_SDR_OK) + goto end; + + if (sign && TSAPI_SDF_ExportSignPublicKey_ECC(hSessionHandle, index, + &pubkey) != OSSL_SDR_OK) + goto end; + + if (!sign && TSAPI_SDF_ExportEncPublicKey_ECC(hSessionHandle, index, + &pubkey) != OSSL_SDR_OK) + goto end; + + pkey = TSAPI_EVP_PKEY_new_from_ECCrefKey(&pubkey, &privkey); + if (pkey == NULL) + goto end; +end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return pkey; +} + +EVP_PKEY *TSAPI_ExportSM2PubKeyWithIndex(int index, int sign) +{ + EVP_PKEY *pkey = NULL; +#ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + OSSL_ECCrefPublicKey pubkey; + EC_GROUP *group = NULL; + EC_KEY *eckey = NULL; + BIGNUM *x = NULL, *y = NULL; + int nbytes; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (sign) { + if (TSAPI_SDF_ExportSignPublicKey_ECC(hSessionHandle, index, &pubkey) + != OSSL_SDR_OK) + goto end; + } else { + if (TSAPI_SDF_ExportEncPublicKey_ECC(hSessionHandle, index, &pubkey) + != OSSL_SDR_OK) + goto end; + } + + group = EC_GROUP_new_by_curve_name(NID_sm2); + if (group == NULL) + goto end; + + eckey = EC_KEY_new(); + if (eckey == NULL) + goto end; + + EC_KEY_set_group(eckey, group); + + nbytes = (pubkey.bits + 7) / 8; + + x = BN_bin2bn(pubkey.x + sizeof(pubkey.x) - nbytes, nbytes, NULL); + if (x == NULL) + goto end; + + y = BN_bin2bn(pubkey.y + sizeof(pubkey.y) - nbytes, nbytes, NULL); + if (y == NULL) + goto end; + + if (!EC_KEY_set_public_key_affine_coordinates(eckey, x, y)) + goto end; + + pkey = EVP_PKEY_new(); + if (pkey == NULL) + goto end; + + if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) { + EVP_PKEY_free(pkey); + goto end; + } + eckey = NULL; + +end: + EC_KEY_free(eckey); + EC_GROUP_free(group); + BN_free(x); + BN_free(y); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return pkey; +} + +int TSAPI_UpdateSm2KeyWithIndex(int index, int sign, const char *user, const char *password) +{ + int ok = 0; +#ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_login_arg_t login_arg; + int area; + + if (sign) + area = SDFE_ASYM_KEY_AREA_SIGN; + else + area = SDFE_ASYM_KEY_AREA_ENC; + + memset(&login_arg, 0, sizeof(login_arg)); + + if (user) { + if (strlen(user) >= sizeof(login_arg.name)) + return 0; + + strcpy((char *)login_arg.name, user); + } + + login_arg.passwd = (uint8_t *)password; + if (password) + login_arg.passwd_len = strlen(password); + else + login_arg.passwd_len = 0; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + if (SDFE_DelECCKey(hSessionHandle, area, index) + != OSSL_SDR_OK) + goto end; + + if (SDFE_GenECCKey(hSessionHandle, area, index, 0, NULL) + != OSSL_SDR_OK) + goto end; + + ok = 1; +end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return ok; +} + +EVP_PKEY *TSAPI_SM2Keygen(void) +{ + return EVP_PKEY_Q_keygen(NULL, NULL, "SM2"); +} + +# ifndef OPENSSL_NO_SM3 +int TSAPI_SM2Verify(EVP_PKEY *key, const unsigned char *tbs, size_t tbslen, + const unsigned char *sig, size_t siglen) +{ + int ok = 0; + EVP_MD_CTX *ctx = NULL; + + if (key == NULL || tbs == NULL || sig == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return 0; + + if (!EVP_DigestVerifyInit(ctx, NULL, EVP_sm3(), NULL, key) + || EVP_DigestVerify(ctx, sig, siglen, tbs, tbslen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + + ok = 1; +end: + EVP_MD_CTX_free(ctx); + return ok; +} + +unsigned char *TSAPI_SM2Sign(EVP_PKEY *key, const unsigned char *tbs, + size_t tbslen, size_t *siglen) +{ + unsigned char *sig = NULL; + size_t len; + EVP_MD_CTX *ctx = NULL; + + if (key == NULL || tbs == NULL || siglen == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return NULL; + + if (!EVP_DigestSignInit(ctx, NULL, EVP_sm3(), NULL, key) + || !EVP_DigestSign(ctx, NULL, &len, tbs, tbslen)) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + + sig = OPENSSL_malloc(len); + if (sig == NULL) + goto end; + + if (!EVP_DigestSign(ctx, sig, &len, tbs, tbslen)) { + OPENSSL_free(sig); + *siglen = 0; + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + + *siglen = len; +end: + EVP_MD_CTX_free(ctx); + return sig; +} +# endif + +static unsigned char *do_SM2Crypt(int enc, EVP_PKEY *key, + const unsigned char *in, size_t inlen, + size_t *outlen) +{ + EVP_PKEY_CTX *ctx = NULL; + size_t len = 0; + unsigned char *out = NULL; + + if (key == NULL || in == NULL || outlen == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (enc) { + ctx = EVP_PKEY_CTX_new_from_pkey_provided(NULL, key, NULL); + } else { + ctx = EVP_PKEY_CTX_new(key, NULL); + } + + if (ctx == NULL) + return NULL; + + if (enc) { + if (EVP_PKEY_encrypt_init(ctx) <= 0 + || EVP_PKEY_encrypt(ctx, NULL, &len, in, inlen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + } else { + if (EVP_PKEY_decrypt_init(ctx) <= 0 + || EVP_PKEY_decrypt(ctx, NULL, &len, in, inlen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + } + + out = OPENSSL_malloc(len); + if (out == NULL) + goto end; + + if (enc) { + if (EVP_PKEY_encrypt(ctx, out, &len, in, inlen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + OPENSSL_free(out); + out = NULL; + len = 0; + } + } else { + if (EVP_PKEY_decrypt(ctx, out, &len, in, inlen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + OPENSSL_free(out); + out = NULL; + len = 0; + } + } + + *outlen = len; +end: + EVP_PKEY_CTX_free(ctx); + return out; +} + +unsigned char *TSAPI_SM2DecryptWithISK(int isk, const unsigned char *in, + size_t inlen, size_t *outlen) +{ + unsigned char *out = NULL; +#ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + OSSL_ECCCipher *ecc = NULL; + unsigned int len; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + return NULL; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_GetPrivateKeyAccessRight(hSessionHandle, isk, NULL, 0) + != OSSL_SDR_OK) + goto end; + + ecc = TSAPI_SM2Ciphertext_to_ECCCipher(in, inlen); + if (ecc == NULL) + goto end; + + len = ecc->L; + out = OPENSSL_malloc(len); + if (out == NULL) + goto end; + + if (TSAPI_SDF_InternalDecrypt_ECC(hSessionHandle, isk, ecc, out, &len) + != OSSL_SDR_OK) { + OPENSSL_free(out); + out = NULL; + *outlen = 0; + goto end; + } + + *outlen = len; +end: + OPENSSL_free(ecc); + TSAPI_SDF_ReleasePrivateKeyAccessRight(hSessionHandle, isk); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return out; +} + +unsigned char *TSAPI_SM2EncryptWithISK(int isk, const unsigned char *in, + size_t inlen, size_t *outlen) +{ + unsigned char *out = NULL; +#ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + OSSL_ECCCipher *ecc = NULL; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + return NULL; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + ecc = OPENSSL_zalloc(sizeof(OSSL_ECCCipher) + inlen); + if (ecc == NULL) + goto end; + + if (TSAPI_SDF_InternalEncrypt_ECC(hSessionHandle, isk, (unsigned char *)in, + inlen, ecc) + != OSSL_SDR_OK) + goto end; + + out = TSAPI_ECCCipher_to_SM2Ciphertext(ecc, outlen); + +end: + OPENSSL_free(ecc); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return out; +} + +unsigned char *TSAPI_SM2Encrypt(EVP_PKEY *key, const unsigned char *in, + size_t inlen, size_t *outlen) +{ + return do_SM2Crypt(1, key, in, inlen, outlen); +} + +unsigned char *TSAPI_SM2Decrypt(EVP_PKEY *key, const unsigned char *in, + size_t inlen, size_t *outlen) +{ + return do_SM2Crypt(0, key, in, inlen, outlen); +} + +unsigned char *TSAPI_ECCCipher_to_SM2Ciphertext(const OSSL_ECCCipher *ecc, + size_t *ciphertext_len) +{ + BIGNUM *x = NULL, *y = NULL; + unsigned char *out = NULL; + + if (ecc == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if ((x = BN_bin2bn(ecc->x, sizeof(ecc->x), NULL)) == NULL + || (y = BN_bin2bn(ecc->y, sizeof(ecc->y), NULL)) == NULL) + goto end; + + out = ossl_sm2_ciphertext_encode(x, y, ecc->C, ecc->L, ecc->M, + sizeof(ecc->M), ciphertext_len); +end: + BN_free(x); + BN_free(y); + return out; + +} + +OSSL_ECCCipher *TSAPI_SM2Ciphertext_to_ECCCipher(const unsigned char *ciphertext, + size_t ciphertext_len) +{ + int ok = 0; + EC_POINT *C1 = NULL; + uint8_t *C2_data = NULL, *C3_data = NULL; + size_t C2_len, C3_len; + EC_GROUP *group = NULL; + BN_CTX *ctx = NULL; + BIGNUM *Cx = NULL, *Cy = NULL; + OSSL_ECCCipher *ecc = NULL; + + if (ciphertext == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (!ossl_sm2_ciphertext_decode(ciphertext, ciphertext_len, &C1, &C2_data, + &C2_len, &C3_data, &C3_len)) + goto end; + + ecc = OPENSSL_zalloc(sizeof(OSSL_ECCCipher) + C2_len); + if (ecc == NULL) + goto end; + + if (C3_len != sizeof(ecc->M)) + goto end; + + memcpy(ecc->M, C3_data, C3_len); + ecc->L = C2_len; + memcpy(ecc->C, C2_data, C2_len); + + group = EC_GROUP_new_by_curve_name(NID_sm2); + if (group == NULL) + goto end; + + ctx = BN_CTX_new(); + if (ctx == NULL) + goto end; + + BN_CTX_start(ctx); + Cx = BN_CTX_get(ctx); + Cy = BN_CTX_get(ctx); + if (Cy == NULL) + goto end; + + if (!EC_POINT_get_affine_coordinates(group, C1, Cx, Cy, NULL)) + goto end; + + if (BN_bn2bin(Cx, ecc->x + sizeof(ecc->x) - BN_num_bytes(Cx)) + != BN_num_bytes(Cx) + || BN_bn2bin(Cy, ecc->y + sizeof(ecc->y) - BN_num_bytes(Cy)) + != BN_num_bytes(Cy)) + goto end; + + ok = 1; +end: + if (!ok) { + OPENSSL_free(ecc); + ecc = NULL; + } + BN_CTX_end(ctx); + BN_CTX_free(ctx); + EC_POINT_free(C1); + OPENSSL_free(C2_data); + OPENSSL_free(C3_data); + return ecc; + +} +#endif + +#ifndef OPENSSL_NO_SM4 +static unsigned char *do_SM4Crypt(int mode, int enc, + const unsigned char *key, + size_t keylen, int isk, + const unsigned char *iv, + const unsigned char *in, size_t inlen, + size_t *outlen) +{ +# ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + void *hkeyHandle = NULL; + OSSL_ECCCipher *ecc = NULL; +# endif + const EVP_CIPHER *cipher = NULL; + EVP_CIPHER_CTX *ctx = NULL; + unsigned char *outbuf = NULL; + unsigned int len = 0; + int lenf = 0; + size_t max_out_len; + + if (isk < 0) { + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return 0; + + if (mode == OSSL_SGD_MODE_ECB) + cipher = EVP_sm4_ecb(); + else if (mode == OSSL_SGD_MODE_CBC) + cipher = EVP_sm4_cbc(); + else if (mode == OSSL_SGD_MODE_CFB) + cipher = EVP_sm4_cfb(); + else if (mode == OSSL_SGD_MODE_OFB) + cipher = EVP_sm4_ofb(); + else if (mode == OSSL_SGD_MODE_CTR) + cipher = EVP_sm4_ctr(); + else + goto end; + + if (!EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc) + || !EVP_CIPHER_CTX_set_padding(ctx, 0)) + goto end; + + max_out_len = inlen + EVP_CIPHER_CTX_get_block_size(ctx); + + outbuf = OPENSSL_malloc(max_out_len); + if (outbuf == NULL) + goto end; + + if (!EVP_CipherUpdate(ctx, outbuf, (int *)&len, in, inlen)) { + OPENSSL_free(outbuf); + outbuf = NULL; + len = 0; + goto end; + } + + if (!EVP_CipherFinal_ex(ctx, outbuf + len, &lenf)) { + OPENSSL_free(outbuf); + outbuf = NULL; + len = 0; + goto end; + } + + len += lenf; + } +# ifdef SDF_LIB + else { + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_GetPrivateKeyAccessRight(hSessionHandle, isk, NULL, 0) + != OSSL_SDR_OK) + goto end; + + ecc = TSAPI_SM2Ciphertext_to_ECCCipher(key, keylen); + if (ecc == NULL) + goto end; + + if (TSAPI_SDF_ImportKeyWithISK_ECC(hSessionHandle, isk, ecc, &hkeyHandle) + != OSSL_SDR_OK) + goto end; + + outbuf = (unsigned char *)OPENSSL_malloc(inlen + 128); + if (outbuf == NULL) + goto end; + + if (enc) { + if (TSAPI_SDF_Encrypt(hSessionHandle, hkeyHandle, + OSSL_SGD_SM4 | mode, + (unsigned char *)iv, (unsigned char *)in, + inlen, outbuf, &len) != OSSL_SDR_OK) { + OPENSSL_free(outbuf); + outbuf = NULL; + goto end; + } + } else { + if (TSAPI_SDF_Decrypt(hSessionHandle, hkeyHandle, + OSSL_SGD_SM4 | mode, + (unsigned char *)iv, (unsigned char *)in, + inlen, outbuf, &len) != OSSL_SDR_OK) { + OPENSSL_free(outbuf); + outbuf = NULL; + goto end; + } + } + } +# endif + *outlen = len; +end: + EVP_CIPHER_CTX_free(ctx); +# ifdef SDF_LIB + if (isk >= 0) { + TSAPI_SDF_DestroyKey(hSessionHandle, hkeyHandle); + TSAPI_SDF_ReleasePrivateKeyAccessRight(hSessionHandle, isk); + OPENSSL_free(ecc); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); + } +# endif + return outbuf; +} + +unsigned char *TSAPI_SM4Decrypt(int mode, const unsigned char *key, + size_t keylen, int isk, + const unsigned char *iv, + const unsigned char *in, size_t inlen, + size_t *outlen) +{ + return do_SM4Crypt(mode, 0, key, keylen, isk, iv, in, inlen, outlen); +} + +unsigned char *TSAPI_SM4Encrypt(int mode, const unsigned char *key, + size_t keylen, int isk, + const unsigned char *iv, + const unsigned char *in, size_t inlen, + size_t *outlen) +{ + return do_SM4Crypt(mode, 1, key, keylen, isk, iv, in, inlen, outlen); +} +#endif + +#ifndef OPENSSL_NO_SM3 +unsigned char *TSAPI_SM3(const void *data, size_t datalen, size_t *outlen) +{ + EVP_MD_CTX *ctx = NULL; + unsigned char *out = NULL; + unsigned int len = 0; + + if (data == NULL || outlen == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return NULL; + + if (!EVP_DigestInit_ex(ctx, EVP_sm3(), NULL) + || !EVP_DigestUpdate(ctx, data, datalen)) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + + out = OPENSSL_malloc(EVP_MD_CTX_get_size(ctx)); + if (out == NULL) + goto end; + + if (!EVP_DigestFinal_ex(ctx, out, &len)) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + OPENSSL_free(out); + out = NULL; + len = 0; + } + + *outlen = len; +end: + EVP_MD_CTX_free(ctx); + return out; +} +#endif diff --git a/crypto/x509/v3_skid.c b/crypto/x509/v3_skid.c index 18223f2ef..8a80a4d46 100644 --- a/crypto/x509/v3_skid.c +++ b/crypto/x509/v3_skid.c @@ -69,7 +69,11 @@ ASN1_OCTET_STRING *ossl_x509_pubkey_hash(X509_PUBKEY *pubkey) } if (!ossl_x509_PUBKEY_get0_libctx(&libctx, &propq, pubkey)) return NULL; - if ((md = EVP_MD_fetch(libctx, SN_sha1, propq)) == NULL) +#ifdef SMTC_MODULE + if ((md = EVP_MD_fetch(libctx, SN_sm3, propq)) == NULL) +#else + if ((md = EVP_MD_fetch(libctx, SN_sha1, NULL)) == NULL) +#endif return NULL; if ((oct = ASN1_OCTET_STRING_new()) == NULL) { EVP_MD_free(md); diff --git a/include/crypto/rand.h b/include/crypto/rand.h index fa3b5b2b9..7b062cf93 100644 --- a/include/crypto/rand.h +++ b/include/crypto/rand.h @@ -32,6 +32,18 @@ # endif # endif +#define RAND_ENTROPY_SOURCE_GETRANDOM 0x0001 +#define RAND_ENTROPY_SOURCE_DEVRANDOM 0x0002 +#define RAND_ENTROPY_SOURCE_RDTSC 0x0004 +#define RAND_ENTROPY_SOURCE_RDCPU 0x0008 +#define RAND_ENTROPY_SOURCE_EGD 0x0010 +#define RAND_ENTROPY_SOURCE_BCRYPTGENRANDOM 0x0020 +#define RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_DEF_PROV 0x0040 +#define RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_INTEL_PROV 0x0080 +#define RAND_ENTROPY_SOURCE_RTCODE 0x0100 +#define RAND_ENTROPY_SOURCE_RTMEM 0x0200 +#define RAND_ENTROPY_SOURCE_RTSOCK 0x0400 + /* * Defines related to seed sources */ @@ -111,6 +123,9 @@ void ossl_random_add_conf_module(void); size_t ossl_rand_get_entropy(ossl_unused OSSL_CORE_HANDLE *handle, unsigned char **pout, int entropy, size_t min_len, size_t max_len); +size_t ossl_rand_get_entropy_from_source(unsigned int source, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len); void ossl_rand_cleanup_entropy(ossl_unused OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len); size_t ossl_rand_get_nonce(ossl_unused OSSL_CORE_HANDLE *handle, diff --git a/include/crypto/rand_pool.h b/include/crypto/rand_pool.h index f4d1d954b..7be677965 100644 --- a/include/crypto/rand_pool.h +++ b/include/crypto/rand_pool.h @@ -32,9 +32,15 @@ * The factor 1.5 below is the pessimistic estimate for the extra amount * of entropy required when no get_nonce() callback is defined. */ -# define RAND_POOL_FACTOR 256 -# define RAND_POOL_MAX_LENGTH (RAND_POOL_FACTOR * \ - 3 * (RAND_DRBG_STRENGTH / 16)) + +# ifdef TONGSUO_RAND_GM_SRNG +/* As required by GM/T 0105-2021 section 5.3 */ +# define RAND_POOL_MAX_LENGTH 4096 +# else +# define RAND_POOL_FACTOR 256 +# define RAND_POOL_MAX_LENGTH (RAND_POOL_FACTOR * \ + 3 * (RAND_DRBG_STRENGTH / 16)) +# endif /* * = (RAND_POOL_FACTOR * \ * 1.5 * (RAND_DRBG_STRENGTH / 8)) @@ -57,7 +63,12 @@ * with 40 bytes. The value of forty eight is comfortably above this which * allows some slack in the platform specific values used. */ -# define RAND_POOL_MIN_ALLOCATION(secure) ((secure) ? 16 : 48) +# ifdef TONGSUO_RAND_GM_SRNG +/* GM/T 0105-2021 DRNG requires the entropy pool should at least 512 bytes. */ +# define RAND_POOL_MIN_ALLOCATION(secure) ((secure) ? 512 : 1024) +# else +# define RAND_POOL_MIN_ALLOCATION(secure) ((secure) ? 16 : 48) +# endif /* * The 'random pool' acts as a dumb container for collecting random @@ -80,6 +91,8 @@ typedef struct rand_pool_st { size_t alloc_len; /* current number of bytes allocated */ size_t entropy; /* current entropy count in bits */ size_t entropy_requested; /* requested entropy count in bits */ + + unsigned int entropy_source; } RAND_POOL; RAND_POOL *ossl_rand_pool_new(int entropy_requested, int secure, @@ -105,5 +118,5 @@ int ossl_rand_pool_add(RAND_POOL *pool, const unsigned char *buffer, size_t len, size_t entropy); unsigned char *ossl_rand_pool_add_begin(RAND_POOL *pool, size_t len); int ossl_rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy); - +void ossl_rand_pool_set_default_entropy_source(unsigned int source); #endif /* OSSL_PROVIDER_RAND_POOL_H */ diff --git a/include/crypto/sm2.h b/include/crypto/sm2.h index 108d821fb..22c9f7da8 100644 --- a/include/crypto/sm2.h +++ b/include/crypto/sm2.h @@ -79,6 +79,11 @@ int ossl_sm2_decrypt(const EC_KEY *key, const uint8_t *ciphertext, size_t ciphertext_len, uint8_t *ptext_buf, size_t *ptext_len); +unsigned char *ossl_sm2_ciphertext_encode(const BIGNUM *C1x, const BIGNUM *C1y, + const uint8_t *C2_data, size_t C2_len, + const uint8_t *C3_data, size_t C3_len, + size_t *ciphertext_len); + int ossl_sm2_ciphertext_decode(const uint8_t *ciphertext, size_t ciphertext_len, EC_POINT **C1p, uint8_t **C2p, size_t *C2_len, uint8_t **C3p, size_t *C3_len); diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h index bfd035781..be81384db 100644 --- a/include/internal/cryptlib.h +++ b/include/internal/cryptlib.h @@ -70,6 +70,11 @@ DEFINE_LHASH_OF(MEM); # define X509_PRIVATE_DIR OPENSSLDIR "/private" # define CTLOG_FILE OPENSSLDIR "/ct_log_list.cnf" +# ifdef SMTC_MODULE +# define SMTC_MODULE_CONF OPENSSLDIR "/smtcmodule.cnf" +# define SMTC_AUTH_KEK OPENSSLDIR "/auth_kek.pem" +# endif + # define X509_CERT_DIR_EVP "SSL_CERT_DIR" # define X509_CERT_FILE_EVP "SSL_CERT_FILE" # define CTLOG_FILE_EVP "CTLOG_FILE" diff --git a/include/internal/provider.h b/include/internal/provider.h index d09829d05..585bbbf34 100644 --- a/include/internal/provider.h +++ b/include/internal/provider.h @@ -87,6 +87,8 @@ int ossl_provider_get_capabilities(const OSSL_PROVIDER *prov, const char *capability, OSSL_CALLBACK *cb, void *arg); +int ossl_provider_reset(OSSL_PROVIDER *prov); +int ossl_provider_status(const OSSL_PROVIDER *prov); int ossl_provider_self_test(const OSSL_PROVIDER *prov); const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov, int operation_id, diff --git a/include/internal/sdf.h b/include/internal/sdf.h new file mode 100644 index 000000000..028f211e3 --- /dev/null +++ b/include/internal/sdf.h @@ -0,0 +1,16 @@ +/* + * Copyright 2024 The Tongsuo 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://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt + */ + +#ifndef OSSL_INTERNAL_SDF_H +# define OSSL_INTERNAL_SDF_H +# pragma once + +void ossl_sdf_lib_cleanup(void); + +#endif diff --git a/include/internal/smtc_names.h b/include/internal/smtc_names.h index fe67aae5c..0f934fd6e 100644 --- a/include/internal/smtc_names.h +++ b/include/internal/smtc_names.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Tongsuo Project Authors. All Rights Reserved. + * Copyright 2023-2024 The Tongsuo 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 @@ -13,17 +13,19 @@ # include -# define OSSL_PROV_SMTC_PARAM_MODULE_PATH "module-path" -# define OSSL_PROV_SMTC_PARAM_MODULE_MAC "module-mac" -# define OSSL_PROV_SMTC_PARAM_ADMIN_PASS "admin-pass" -# define OSSL_PROV_SMTC_PARAM_ADMIN_SALT "admin-salt" -# define OSSL_PROV_SMTC_PARAM_SHOW_SELFTEST "show-selftest" -# define OSSL_PROV_SMTC_PARAM_RNG_POWERON_TEST "rng-poweron-test" -# define OSSL_PROV_SMTC_PARAM_RNG_CONTINUOUS_TEST "rng-continuous-test" +# define OSSL_PROV_SMTC_PARAM_MODULE_PATH "module-path" +# define OSSL_PROV_SMTC_PARAM_MODULE_SIG "module-sig" +# define OSSL_PROV_SMTC_PARAM_AUTH_KEY "auth-key" +# define OSSL_PROV_SMTC_PARAM_AUTH_SALT "auth-salt" +# define OSSL_PROV_SMTC_PARAM_AUTH_KEK "auth-kek" +# define OSSL_PROV_SMTC_PARAM_ENGINE "engine" +# define OSSL_PROV_SMTC_PARAM_SYSLOG "syslog" +# define OSSL_PROV_SMTC_PARAM_RNG_POWERON_TEST "rng-poweron-test" +# define OSSL_PROV_SMTC_PARAM_RNG_CONTINUOUS_TEST "rng-continuous-test" # define OSSL_PROV_SMTC_PARAM_RANDOMNESS_POWERON_TEST "randomness-poweron-test" # ifndef OPENSSL_NO_SMTC_DEBUG -# define OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_MAC "verify-mac" +# define OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_SIG "verify-sig" # define OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_PASS "verify-pass" # endif diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h index 99fcda002..357dc2399 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -249,6 +249,12 @@ OSSL_CORE_MAKE_FUNC(int, provider_get_capabilities, (void *provctx, # define OSSL_FUNC_PROVIDER_SELF_TEST 1031 OSSL_CORE_MAKE_FUNC(int, provider_self_test, (void *provctx)) +# define OSSL_FUNC_PROVIDER_STATUS 1032 +OSSL_CORE_MAKE_FUNC(int, provider_status, (void *provctx)) + +# define OSSL_FUNC_PROVIDER_RESET 1033 +OSSL_CORE_MAKE_FUNC(int, provider_reset, (void *provctx)) + /* Operations */ # define OSSL_OP_DIGEST 1 diff --git a/include/openssl/crypto.h.in b/include/openssl/crypto.h.in index 47d91aedb..116f32ac4 100644 --- a/include/openssl/crypto.h.in +++ b/include/openssl/crypto.h.in @@ -53,10 +53,31 @@ use OpenSSL::stackhash qw(generate_stack_macros); # include # endif +#if defined(OPENSSL_SYS_WINCE) +#elif defined(OPENSSL_SYS_WIN32) +#elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG) +# include +#endif + #ifdef __cplusplus extern "C" { #endif +# ifndef NO_SYSLOG +# if defined(OPENSSL_SYS_WIN32) +# define LOG_EMERG 0 +# define LOG_ALERT 1 +# define LOG_CRIT 2 +# define LOG_ERR 3 +# define LOG_WARNING 4 +# define LOG_NOTICE 5 +# define LOG_INFO 6 +# define LOG_DEBUG 7 + +# define LOG_DAEMON (3<<3) +# endif +# endif + # ifndef OPENSSL_NO_DEPRECATED_1_1_0 # define SSLeay OpenSSL_version_num # define SSLeay_version OpenSSL_version @@ -184,6 +205,8 @@ const char *OPENSSL_info(int type); # define OPENSSL_INFO_LIST_SEPARATOR 1006 # define OPENSSL_INFO_SEED_SOURCE 1007 # define OPENSSL_INFO_CPU_SETTINGS 1008 +# define OPENSSL_INFO_SMTC_MODULE_CONF 1009 +# define OPENSSL_INFO_SMTC_AUTH_KEK 1010 int OPENSSL_issetugid(void); @@ -542,6 +565,10 @@ void OSSL_LIB_CTX_free(OSSL_LIB_CTX *); OSSL_LIB_CTX *OSSL_LIB_CTX_get0_global_default(void); OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *libctx); +void OSSL_enable_syslog(void); +void OSSL_disable_syslog(void); +void OSSL_syslog(int priority, const char *message, ...); + # ifdef __cplusplus } # endif diff --git a/include/openssl/evp.h b/include/openssl/evp.h index efa47dfc6..ec26e09af 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -1681,8 +1681,14 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e); EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OSSL_LIB_CTX *libctx, const char *name, const char *propquery); +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name_provided(OSSL_LIB_CTX *libctx, + const char *name, + const char *propquery); EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OSSL_LIB_CTX *libctx, EVP_PKEY *pkey, const char *propquery); +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey_provided(OSSL_LIB_CTX *libctx, + EVP_PKEY *pkey, + const char *propquery); EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx); void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); int EVP_PKEY_CTX_is_a(EVP_PKEY_CTX *ctx, const char *keytype); diff --git a/include/openssl/opensslv.h.in b/include/openssl/opensslv.h.in index dfc4e45b7..8c3d996d7 100644 --- a/include/openssl/opensslv.h.in +++ b/include/openssl/opensslv.h.in @@ -126,7 +126,7 @@ extern "C" { # define BABASSL_VERSION_NUMBER TONGSUO_VERSION_NUMBER # define BABASSL_VERSION_TEXT TONGSUO_VERSION_TEXT -# define TONGSUO_SMTC_INFO_STR "{- $config{TONGSUO_SMTC_INFO} -}" +# define TONGSUO_SMTC_INFO_STR "{- $config{tongsuo_smtc_info} -}" # ifdef __cplusplus } diff --git a/include/openssl/proverr.h b/include/openssl/proverr.h index ad67a8f89..75351fc98 100644 --- a/include/openssl/proverr.h +++ b/include/openssl/proverr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 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 @@ -48,6 +48,7 @@ # define PROV_R_FIPS_MODULE_IN_ERROR_STATE 225 # define PROV_R_GENERATE_ERROR 191 # define PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 165 +# define PROV_R_INCORRECT_PASSWORD 231 # define PROV_R_INDICATOR_INTEGRITY_FAILURE 210 # define PROV_R_INSUFFICIENT_DRBG_STRENGTH 181 # define PROV_R_INVALID_AAD 108 @@ -123,6 +124,9 @@ # define PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT 229 # define PROV_R_SELF_TEST_KAT_FAILURE 215 # define PROV_R_SELF_TEST_POST_FAILURE 216 +# define PROV_R_SMTC_MODULE_CONDITIONAL_ERROR 232 +# define PROV_R_SMTC_MODULE_ENTERING_ERROR_STATE 350 +# define PROV_R_SMTC_MODULE_IN_ERROR_STATE 351 # define PROV_R_TAG_NOT_NEEDED 120 # define PROV_R_TAG_NOT_SET 119 # define PROV_R_TOO_MANY_RECORDS 126 diff --git a/include/openssl/provider.h b/include/openssl/provider.h index dc86ff587..32cdf7838 100644 --- a/include/openssl/provider.h +++ b/include/openssl/provider.h @@ -32,6 +32,8 @@ int OSSL_PROVIDER_do_all(OSSL_LIB_CTX *ctx, 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_reset(OSSL_PROVIDER *prov); +int OSSL_PROVIDER_status(const OSSL_PROVIDER *prov); int OSSL_PROVIDER_self_test(const OSSL_PROVIDER *prov); int OSSL_PROVIDER_get_capabilities(const OSSL_PROVIDER *prov, const char *capability, diff --git a/include/openssl/rand.h b/include/openssl/rand.h index ad3054fd5..1673631c7 100644 --- a/include/openssl/rand.h +++ b/include/openssl/rand.h @@ -87,6 +87,7 @@ int RAND_set_DRBG_type(OSSL_LIB_CTX *ctx, const char *drbg, const char *propq, const char *cipher, const char *digest); int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed, const char *propq); +void RAND_set_entropy_source(unsigned int source); void RAND_seed(const void *buf, int num); void RAND_keep_random_devices_open(int keep); diff --git a/include/openssl/sdf.h b/include/openssl/sdf.h new file mode 100644 index 000000000..5d07bc2a4 --- /dev/null +++ b/include/openssl/sdf.h @@ -0,0 +1,118 @@ +/* + * Copyright 2024 The Tongsuo 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://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt + */ + +#ifndef OPENSSL_SDF_H +# define OPENSSL_SDF_H +# pragma once + +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +/* SDF error codes from GM/T 0018-2012 Appendix A */ +# define OSSL_SDR_OK 0 +# define OSSL_SDR_BASE 0x01000000 +# define OSSL_SDR_UNKNOWNERR (OSSL_SDR_BASE + 1) +# define OSSL_SDR_NOTSUPPORT (OSSL_SDR_BASE + 2) +# define OSSL_SDR_COMMFAIL (OSSL_SDR_BASE + 3) +# define OSSL_SDR_HARDFAIL (OSSL_SDR_BASE + 4) +# define OSSL_SDR_OPENDEVICE (OSSL_SDR_BASE + 5) +# define OSSL_SDR_OPENSESSION (OSSL_SDR_BASE + 6) +# define OSSL_SDR_PARDENY (OSSL_SDR_BASE + 7) +# define OSSL_SDR_KEYNOTEXIST (OSSL_SDR_BASE + 8) +# define OSSL_SDR_ALGNOTSUPPORT (OSSL_SDR_BASE + 9) +# define OSSL_SDR_ALGMODNOTSUPPORT (OSSL_SDR_BASE + 10) +# define OSSL_SDR_PKOPERR (OSSL_SDR_BASE + 11) +# define OSSL_SDR_SKOPERR (OSSL_SDR_BASE + 12) +# define OSSL_SDR_SIGNERR (OSSL_SDR_BASE + 13) +# define OSSL_SDR_VERIFYERR (OSSL_SDR_BASE + 14) +# define OSSL_SDR_SYMOPERR (OSSL_SDR_BASE + 15) +# define OSSL_SDR_STEPERR (OSSL_SDR_BASE + 16) +# define OSSL_SDR_FILESIZEERR (OSSL_SDR_BASE + 17) +# define OSSL_SDR_FILENOTEXIST (OSSL_SDR_BASE + 18) +# define OSSL_SDR_FILEOFSERR (OSSL_SDR_BASE + 19) +# define OSSL_SDR_KEYTYPEERR (OSSL_SDR_BASE + 20) +# define OSSL_SDR_KEYERR (OSSL_SDR_BASE + 21) +# define OSSL_SDR_ENCDATAERR (OSSL_SDR_BASE + 22) +# define OSSL_SDR_RANDERR (OSSL_SDR_BASE + 23) +# define OSSL_SDR_PRKRERR (OSSL_SDR_BASE + 24) +# define OSSL_SDR_MACERR (OSSL_SDR_BASE + 25) +# define OSSL_SDR_FILEEXISTS (OSSL_SDR_BASE + 26) +# define OSSL_SDR_FILEWERR (OSSL_SDR_BASE + 27) +# define OSSL_SDR_NOBUFFER (OSSL_SDR_BASE + 28) +# define OSSL_SDR_INARGERR (OSSL_SDR_BASE + 29) +# define OSSL_SDR_OUTARGERR (OSSL_SDR_BASE + 30) + +#define OSSL_SDFE_ASYM_KEY_TYPE_SM2 (0xa0) +#define OSSL_SDFE_SYM_KEY_TYPE_SM4 (0xb0) + +typedef struct OSSL_ECCCipher_st OSSL_ECCCipher; +typedef struct OSSL_ECCSignature_st OSSL_ECCSignature; +typedef struct OSSL_ECCrefPrivateKey_st OSSL_ECCrefPrivateKey; +typedef struct OSSL_ECCrefPublicKey_st OSSL_ECCrefPublicKey; +int TSAPI_SDF_OpenDevice(void **phDeviceHandle); +int TSAPI_SDF_CloseDevice(void *hDeviceHandle); +int TSAPI_SDF_OpenSession(void *hDeviceHandle, void **phSessionHandle); +int TSAPI_SDF_CloseSession(void *hSessionHandle); +int TSAPI_SDF_GenerateRandom(void *hSessionHandle, unsigned int uiLength, + unsigned char *pucRandom); +int TSAPI_SDF_GetPrivateKeyAccessRight(void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucPassword, + unsigned int uiPwdLength); +int TSAPI_SDF_ReleasePrivateKeyAccessRight(void *hSessionHandle, + unsigned int uiKeyIndex); +int TSAPI_SDF_ImportKeyWithISK_ECC(void *hSessionHandle, + unsigned int uiISKIndex, + OSSL_ECCCipher *pucKey, + void **phKeyHandle); +int TSAPI_SDF_ImportKeyWithKEK(void *hSessionHandle, unsigned int uiAlgID, + unsigned int uiKEKIndex, unsigned char *pucKey, unsigned int puiKeyLength, + void **phKeyHandle); +int TSAPI_SDF_ExportSignPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, + OSSL_ECCrefPublicKey *pucPublicKey); +int TSAPI_SDF_ExportEncPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, + OSSL_ECCrefPublicKey *pucPublicKey); +int TSAPI_SDF_DestroyKey(void *hSessionHandle, void *hKeyHandle); +int TSAPI_SDF_InternalEncrypt_ECC(void *hSessionHandle, unsigned int uiISKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + OSSL_ECCCipher *pucEncData); +int TSAPI_SDF_InternalDecrypt_ECC(void *hSessionHandle, unsigned int uiISKIndex, + OSSL_ECCCipher *pucEncData, + unsigned char *pucData, + unsigned int *puiDataLength); +int TSAPI_SDF_Encrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucData, + unsigned int uiDataLength, unsigned char *pucEncData, + unsigned int *puiEncDataLength); +int TSAPI_SDF_Decrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucEncData, + unsigned int uiEncDataLength, unsigned char *pucData, + unsigned int *puiDataLength); +int TSAPI_SDF_CalculateMAC(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucData, + unsigned int uiDataLength, unsigned char *pucMac, + unsigned int *puiMACLength); +int TSAPI_SDF_GenerateKey(void *hSessionHandle, uint8_t type, uint8_t no_kek, + uint32_t len, void **pkey_handle); +int TSAPI_SDF_InternalSign_ECC(void *hSessionHandle, unsigned int uiISKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + OSSL_ECCSignature *pucSignature); + +# ifdef __cplusplus +} +# endif +#endif /* OPENSSL_SDF_H */ diff --git a/include/openssl/self_test.h b/include/openssl/self_test.h index 357e1a9d2..7e7e4106a 100644 --- a/include/openssl/self_test.h +++ b/include/openssl/self_test.h @@ -32,6 +32,7 @@ extern "C" { # define OSSL_SELF_TEST_TYPE_PCT "Conditional_PCT" # define OSSL_SELF_TEST_TYPE_KAT_CIPHER "KAT_Cipher" # define OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER "KAT_AsymmetricCipher" +# define OSSL_SELF_TEST_TYPE_PCT_ASYM_CIPHER "PCT_AsymmetricCipher" # define OSSL_SELF_TEST_TYPE_KAT_DIGEST "KAT_Digest" # define OSSL_SELF_TEST_TYPE_KAT_SIGNATURE "KAT_Signature" # define OSSL_SELF_TEST_TYPE_PCT_SIGNATURE "PCT_Signature" @@ -42,6 +43,7 @@ extern "C" { /* Test event sub categories */ # define OSSL_SELF_TEST_DESC_NONE "None" # define OSSL_SELF_TEST_DESC_INTEGRITY_HMAC "HMAC" +# define OSSL_SELF_TEST_DESC_INTEGRITY_VERIFY "Verify_Integrity" # define OSSL_SELF_TEST_DESC_PCT_RSA_PKCS1 "RSA" # define OSSL_SELF_TEST_DESC_PCT_ECDSA "ECDSA" # define OSSL_SELF_TEST_DESC_PCT_DSA "DSA" @@ -56,6 +58,8 @@ extern "C" { # define OSSL_SELF_TEST_DESC_SIGN_DSA "DSA" # define OSSL_SELF_TEST_DESC_SIGN_RSA "RSA" # define OSSL_SELF_TEST_DESC_SIGN_SM2 "SM2" +# define OSSL_SELF_TEST_DESC_SIGN_SM2_SIGN "SM2_Sign" +# define OSSL_SELF_TEST_DESC_SIGN_SM2_VERIFY "SM2_Verify" # define OSSL_SELF_TEST_DESC_SIGN_ECDSA "ECDSA" # define OSSL_SELF_TEST_DESC_DRBG_CTR "CTR" # define OSSL_SELF_TEST_DESC_DRBG_HASH "HASH" @@ -76,6 +80,8 @@ extern "C" { # define OSSL_SELF_TEST_DESC_RNG "RNG" # define OSSL_SELF_TEST_DESC_ASYM_SM2_ENC "SM2_Encrypt" # define OSSL_SELF_TEST_DESC_ASYM_SM2_DEC "SM2_Decrypt" +# define OSSL_SELF_TEST_DESC_SM2_SIGN_PAIRWISE "SM2_Sign_Pairwise" +# define OSSL_SELF_TEST_DESC_SM2_ENC_PAIRWISE "SM2_Enc_Pairwise" void OSSL_SELF_TEST_set_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK *cb, diff --git a/include/openssl/sgd.h b/include/openssl/sgd.h new file mode 100644 index 000000000..e79267ff4 --- /dev/null +++ b/include/openssl/sgd.h @@ -0,0 +1,53 @@ +/* + * Copyright 2024 The Tongsuo 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://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt + */ + +#ifndef OPENSSL_SGD_H +# define OPENSSL_SGD_H +# pragma once + +# include +# ifndef OPENSSL_NO_DEPRECATED_3_0 +# define HEADER_SGD_H +# endif + +# ifdef __cplusplus +extern "C" { +# endif + +/* Defined in GM/T 0006-2012 */ +# define OSSL_SGD_MODE_ECB 0x00000001 +# define OSSL_SGD_MODE_CBC 0x00000002 +# define OSSL_SGD_MODE_CFB 0x00000004 +# define OSSL_SGD_MODE_OFB 0x00000008 +# define OSSL_SGD_MODE_MAC 0x00000010 +# define OSSL_SGD_MODE_CTR 0x00000020 +# define OSSL_SGD_MODE_XTS 0x00000040 + +# define OSSL_SGD_SM4 0x00000400 +# define OSSL_SGD_SM4_ECB (OSSL_SGD_SM4 | OSSL_SGD_MODE_ECB) +# define OSSL_SGD_SM4_CBC (OSSL_SGD_SM4 | OSSL_SGD_MODE_CBC) +# define OSSL_SGD_SM4_CFB (OSSL_SGD_SM4 | OSSL_SGD_MODE_CFB) +# define OSSL_SGD_SM4_OFB (OSSL_SGD_SM4 | OSSL_SGD_MODE_OFB) +# define OSSL_SGD_SM4_MAC (OSSL_SGD_SM4 | OSSL_SGD_MODE_MAC) + +# define OSSL_SGD_RSA 0x00010000 +# define OSSL_SGD_SM2 0x00020100 +# define OSSL_SGD_SM2_1 0x00020200 +# define OSSL_SGD_SM2_2 0x00020400 +# define OSSL_SGD_SM2_3 0x00020800 + +# define OSSL_SGD_SM3 0x00000001 + +# define OSSL_SGD_SM3_SM2 0x00020201 + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/include/openssl/trace.h b/include/openssl/trace.h index 282001336..d2a2d52ed 100644 --- a/include/openssl/trace.h +++ b/include/openssl/trace.h @@ -57,8 +57,9 @@ extern "C" { # define OSSL_TRACE_CATEGORY_DECODER 15 # define OSSL_TRACE_CATEGORY_ENCODER 16 # define OSSL_TRACE_CATEGORY_REF_COUNT 17 +# define OSSL_TRACE_CATEGORY_SMTC 18 /* Count of available categories. */ -# define OSSL_TRACE_CATEGORY_NUM 18 +# define OSSL_TRACE_CATEGORY_NUM 19 /* Returns the trace category number for the given |name| */ int OSSL_trace_get_category_num(const char *name); diff --git a/include/openssl/tsapi.h b/include/openssl/tsapi.h new file mode 100644 index 000000000..7d5adff78 --- /dev/null +++ b/include/openssl/tsapi.h @@ -0,0 +1,98 @@ +/* + * Copyright 2024 The Tongsuo 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://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt + */ + +#ifndef TONGSUO_API_H +# define TONGSUO_API_H +# pragma once + +# include +# ifndef OPENSSL_NO_DEPRECATED_3_0 +# define HEADER_TSAPI_H +# endif + +# include +# include +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +unsigned char *TSAPI_GetEntropy(int entropy, size_t *outlen); +void TSAPI_FreeEntropy(unsigned char *ent, size_t len); +char *TSAPI_Version(void); +unsigned char *TSAPI_RandBytes(size_t len); + +# ifndef OPENSSL_NO_SM2 +EVP_PKEY *TSAPI_SM2Keygen(void); +# ifndef OPENSSL_NO_SM3 +unsigned char *TSAPI_SM2Sign(EVP_PKEY *key, const unsigned char *tbs, + size_t tbslen, size_t *siglen); +int TSAPI_SM2Verify(EVP_PKEY *key, const unsigned char *tbs, size_t tbslen, + const unsigned char *sig, size_t siglen); +# endif +unsigned char *TSAPI_SM2Encrypt(EVP_PKEY *key, const unsigned char *in, + size_t inlen, size_t *outlen); +unsigned char *TSAPI_SM2Decrypt(EVP_PKEY *key, const unsigned char *in, + size_t inlen, size_t *outlen); +unsigned char *TSAPI_SM2EncryptWithISK(int isk, const unsigned char *in, + size_t inlen, size_t *outlen); +unsigned char *TSAPI_SM2DecryptWithISK(int isk, const unsigned char *in, + size_t inlen, size_t *outlen); +unsigned char *TSAPI_ECCCipher_to_SM2Ciphertext(const OSSL_ECCCipher *ecc, + size_t *ciphertext_len); +OSSL_ECCCipher *TSAPI_SM2Ciphertext_to_ECCCipher(const unsigned char *ciphertext, + size_t ciphertext_len); +int TSAPI_ImportSM2Key(int index, int sign, const char *user, + const char *password, const EVP_PKEY *sm2_pkey); +OSSL_ECCrefPublicKey *TSAPI_EVP_PKEY_get_ECCrefPublicKey(const EVP_PKEY *pkey); +OSSL_ECCrefPrivateKey *TSAPI_EVP_PKEY_get_ECCrefPrivateKey(const EVP_PKEY *pkey); +EVP_PKEY *TSAPI_ExportSM2KeyWithIndex(int index, int sign, const char *user, + const char *password); +EVP_PKEY *TSAPI_EVP_PKEY_new_from_ECCrefKey(const OSSL_ECCrefPublicKey *pubkey, + const OSSL_ECCrefPrivateKey *privkey); +int TSAPI_ImportSM2KeyWithEvlp(int index, int sign, const char *user, + const char *password, unsigned char *key, + size_t keylen, unsigned char *dek, + size_t deklen); +int TSAPI_ExportSM2KeyWithEvlp(int index, int sign, const char *user, + const char *password, EVP_PKEY *sm2_pubkey, + unsigned char **priv, size_t *privlen, + unsigned char **pub, size_t *publen, + unsigned char **outevlp, size_t *outevlplen); +int TSAPI_GenerateSM2KeyWithIndex(int index, int sign, const char *user, const char *password); +int TSAPI_DelSm2KeyWithIndex(int index, int sign, const char *user, + const char *password); +int TSAPI_UpdateSm2KeyWithIndex(int index, int sign, const char *user, + const char *password); +EVP_PKEY *TSAPI_ExportSM2PubKeyWithIndex(int index, int sign); +# endif + +# ifndef OPENSSL_NO_SM4 +unsigned char *TSAPI_SM4Encrypt(int mode, const unsigned char *key, + size_t keylen, int isk, + const unsigned char *iv, + const unsigned char *in, size_t inlen, + size_t *outlen); +unsigned char *TSAPI_SM4Decrypt(int mode, const unsigned char *key, + size_t keylen, int isk, + const unsigned char *iv, + const unsigned char *in, size_t inlen, + size_t *outlen); +# endif +# ifndef OPENSSL_NO_SM3 +unsigned char *TSAPI_SM3(const void *data, size_t datalen, size_t *outlen); +# endif + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/include/openssl/types.h b/include/openssl/types.h index 4e3bce468..ce5c076e6 100644 --- a/include/openssl/types.h +++ b/include/openssl/types.h @@ -244,6 +244,8 @@ typedef struct ossl_decoder_ctx_st OSSL_DECODER_CTX; typedef struct ossl_self_test_st OSSL_SELF_TEST; +typedef struct sdf_method_st SDF_METHOD; + #ifdef __cplusplus } #endif diff --git a/providers/build.info b/providers/build.info index 072bce04c..358f5d046 100644 --- a/providers/build.info +++ b/providers/build.info @@ -134,30 +134,26 @@ IF[{- !$disabled{smtc} -}] LIBS{noinst}=$LIBSMTC SUBDIRS=smtc - # Note: only support builtin module for now - IF[{- $disabled{module} -}] - # Become built in - $SMTCGOAL=../libcrypto - SOURCE[$SMTCGOAL]=$LIBSMTC - DEFINE[$SMTCGOAL]=STATIC_SMTC - DEFINE[$LIBSMTC]=STATIC_SMTC - ELSE - # TODO: become a module - $SMTCGOAL=smtc - MODULES=$SMTCGOAL - DEPEND[$SMTCGOAL]=$LIBSMTC - SOURCE[$SMTCGOAL]=smtc/smtc_entry.c - INCLUDE[$SMTCGOAL]=../include - IF[{- defined $target{shared_defflag} -}] - SOURCE[$SMTCGOAL]=smtc.ld - GENERATE[smtc.ld]=../util/providers.num - ENDIF - SOURCE[$LIBSMTC]=prov_running.c - ENDIF + # Note: only support builtin for now + $SMTCGOAL=../libcrypto + SOURCE[$SMTCGOAL]=$LIBSMTC + DEFINE[$SMTCGOAL]=STATIC_SMTC + DEFINE[$LIBSMTC]=STATIC_SMTC DEFINE[$SMTCGOAL]=SMTC_MODULE DEFINE[$LIBDEFAULT]=SMTC_MODULE DEFINE[../libssl]=SMTC_MODULE + +{- use File::Spec::Functions; + our $ex_lib = $withargs{atf_slibce_lib} && + (file_name_is_absolute($withargs{atf_slibce_lib}) ? + $withargs{atf_slibce_lib} : catfile(updir(), $withargs{atf_slibce_lib})); + "" +-} + + IF[{- !$disabled{atf_slibce} -}] + DEPEND[$SMTCGOAL]={- $ex_lib -} + ENDIF ENDIF # diff --git a/providers/common/include/prov/proverr.h b/providers/common/include/prov/proverr.h index 5084af201..34247ed2f 100644 --- a/providers/common/include/prov/proverr.h +++ b/providers/common/include/prov/proverr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2024 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 diff --git a/providers/common/include/prov/provider_util.h b/providers/common/include/prov/provider_util.h index dfe91f29b..b74e1373c 100644 --- a/providers/common/include/prov/provider_util.h +++ b/providers/common/include/prov/provider_util.h @@ -7,8 +7,11 @@ * https://www.openssl.org/source/license.html */ -#include -#include +#ifndef OSSL_PROV_PROVIDER_UTIL_H +# define OSSL_PROV_PROVIDER_UTIL_H + +# include +# include typedef struct { /* @@ -136,3 +139,4 @@ typedef struct ag_capable_st { */ void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in, OSSL_ALGORITHM *out); +#endif diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index 344c12211..e541100cf 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 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 @@ -62,6 +62,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_GENERATE_ERROR), "generate error"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE), "illegal or unsupported padding mode"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INCORRECT_PASSWORD), + "incorrect password"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INDICATOR_INTEGRITY_FAILURE), "indicator integrity failure"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INSUFFICIENT_DRBG_STRENGTH), @@ -177,6 +179,12 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { "self test kat failure"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SELF_TEST_POST_FAILURE), "self test post failure"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SMTC_MODULE_CONDITIONAL_ERROR), + "smtc module conditional error"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SMTC_MODULE_ENTERING_ERROR_STATE), + "smtc module entering error state"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SMTC_MODULE_IN_ERROR_STATE), + "smtc module in error state"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOT_NEEDED), "tag not needed"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOT_SET), "tag not set"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TOO_MANY_RECORDS), "too many records"}, diff --git a/providers/implementations/rands/drbg_hash.c b/providers/implementations/rands/drbg_hash.c index 617e75848..d473c6530 100644 --- a/providers/implementations/rands/drbg_hash.c +++ b/providers/implementations/rands/drbg_hash.c @@ -35,9 +35,6 @@ static OSSL_FUNC_rand_gettable_ctx_params_fn drbg_hash_gettable_ctx_params; static OSSL_FUNC_rand_get_ctx_params_fn drbg_hash_get_ctx_params; static OSSL_FUNC_rand_verify_zeroization_fn drbg_hash_verify_zeroization; -/* 888 bits from SP800-90Ar1 10.1 table 2 */ -#define HASH_PRNG_MAX_SEEDLEN (888/8) - /* 440 bits from SP800-90Ar1 10.1 table 2 */ #define HASH_PRNG_SMALL_SEEDLEN (440/8) @@ -45,15 +42,6 @@ static OSSL_FUNC_rand_verify_zeroization_fn drbg_hash_verify_zeroization; #define MAX_BLOCKLEN_USING_SMALL_SEEDLEN (256/8) #define INBYTE_IGNORE ((unsigned char)0xFF) -typedef struct rand_drbg_hash_st { - PROV_DIGEST digest; - EVP_MD_CTX *ctx; - size_t blocklen; - unsigned char V[HASH_PRNG_MAX_SEEDLEN]; - unsigned char C[HASH_PRNG_MAX_SEEDLEN]; - /* Temporary value storage: should always exceed max digest length */ - unsigned char vtmp[HASH_PRNG_MAX_SEEDLEN]; -} PROV_DRBG_HASH; /* * SP800-90Ar1 10.3.1 Derivation function using a Hash Function (Hash_df). @@ -309,8 +297,10 @@ static int drbg_hash_reseed(PROV_DRBG *drbg, adin, adin_len)) return 0; } else { - /* (Step 1-2) V = Hash_df(0x01 || V || entropy_input || additional_input) */ - /* V about to be updated so use C as output instead */ + /* + * (Step 1-2) V=Hash_df(0x01 || V || entropy_input || additional_input) + * V about to be updated so use C as output instead + */ if (!hash_df(drbg, hash->C, 0x01, hash->V, drbg->seedlen, ent, ent_len, adin, adin_len)) return 0; diff --git a/providers/implementations/rands/drbg_local.h b/providers/implementations/rands/drbg_local.h index a0877e379..bcdef411b 100644 --- a/providers/implementations/rands/drbg_local.h +++ b/providers/implementations/rands/drbg_local.h @@ -18,6 +18,7 @@ # include "internal/nelem.h" # include "internal/numbers.h" # include "prov/provider_ctx.h" +# include "prov/provider_util.h" /* How many times to read the TSC as a randomness source. */ # define TSC_READ_COUNT 4 @@ -49,13 +50,26 @@ */ # define DRBG_MAX_LENGTH INT32_MAX +/* 888 bits from SP800-90Ar1 10.1 table 2 */ +#define HASH_PRNG_MAX_SEEDLEN (888/8) + /* The default nonce */ -#ifdef CHARSET_EBCDIC -# define DRBG_DEFAULT_PERS_STRING { 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x53, \ +#ifdef TONGSUO_RAND_GM_SRNG +# ifdef CHARSET_EBCDIC +# define DRBG_DEFAULT_PERS_STRING { 0x54, 0x6f, 0x6e, 0x67, 0x73, 0x75, \ + 0x6f, 0x20, 0x47, 0x4d, 0x2f, 0x54, 0x20, 0x30, 0x31, 0x30, 0x35, 0x2d, \ + 0x32, 0x30, 0x32, 0x31, 0x20, 0x53, 0x52, 0x4e, 0x47, 0x00}; +# else +# define DRBG_DEFAULT_PERS_STRING "Tongsuo GM/T 0105-2021 SRNG" +# endif +#else +# ifdef CHARSET_EBCDIC +# define DRBG_DEFAULT_PERS_STRING { 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x53, \ 0x4c, 0x20, 0x4e, 0x49, 0x53, 0x54, 0x20, 0x53, 0x50, 0x20, 0x38, 0x30, \ 0x30, 0x2d, 0x39, 0x30, 0x41, 0x20, 0x44, 0x52, 0x42, 0x47, 0x00}; -#else -# define DRBG_DEFAULT_PERS_STRING "OpenSSL NIST SP 800-90A DRBG" +# else +# define DRBG_DEFAULT_PERS_STRING "OpenSSL NIST SP 800-90A DRBG" +# endif #endif typedef struct prov_drbg_st PROV_DRBG; @@ -178,6 +192,16 @@ struct prov_drbg_st { OSSL_CALLBACK *cleanup_nonce_fn; }; +typedef struct rand_drbg_hash_st { + PROV_DIGEST digest; + EVP_MD_CTX *ctx; + size_t blocklen; + unsigned char V[HASH_PRNG_MAX_SEEDLEN]; + unsigned char C[HASH_PRNG_MAX_SEEDLEN]; + /* Temporary value storage: should always exceed max digest length */ + unsigned char vtmp[HASH_PRNG_MAX_SEEDLEN]; +} PROV_DRBG_HASH; + PROV_DRBG *ossl_rand_drbg_new (void *provctx, void *parent, const OSSL_DISPATCH *parent_dispatch, int (*dnew)(PROV_DRBG *ctx), diff --git a/providers/implementations/rands/seeding/rand_unix.c b/providers/implementations/rands/seeding/rand_unix.c index 6fb13195a..847f250d8 100644 --- a/providers/implementations/rands/seeding/rand_unix.c +++ b/providers/implementations/rands/seeding/rand_unix.c @@ -102,7 +102,14 @@ static uint64_t get_timer_bits(void); # undef OPENSSL_RAND_SEED_RDTSC # undef OPENSSL_RAND_SEED_RDCPU # undef OPENSSL_RAND_SEED_EGD -# undef OPENSSL_RAND_SEED_RTC +# undef OPENSSL_RAND_SEED_RTCODE +# undef OPENSSL_RAND_SEED_RTMEM +# undef OPENSSL_RAND_SEED_RTSOCK +#endif + +#if defined(OPENSSL_RAND_SEED_RTSOCK) +# include +# include #endif #if defined(OPENSSL_SYS_UEFI) && !defined(OPENSSL_RAND_SEED_NONE) @@ -606,8 +613,8 @@ void ossl_rand_pool_keep_random_devices_open(int keep) # endif /* defined(OPENSSL_RAND_SEED_DEVRANDOM) */ -# if defined(OPENSSL_RAND_SEED_RTC) -static size_t ossl_prov_acquire_entropy_from_rtc1(RAND_POOL *pool) +# if defined(OPENSSL_RAND_SEED_RTCODE) +static size_t ossl_prov_acquire_entropy_from_rtcode(RAND_POOL *pool) { size_t i, k, bytes_needed; struct timespec ts; @@ -635,8 +642,9 @@ static size_t ossl_prov_acquire_entropy_from_rtc1(RAND_POOL *pool) } return ossl_rand_pool_entropy_available(pool); } - -static size_t ossl_prov_acquire_entropy_from_rtc2(RAND_POOL *pool) +# endif +# if defined(OPENSSL_RAND_SEED_RTMEM) +static size_t ossl_prov_acquire_entropy_from_rtmem(RAND_POOL *pool) { size_t i, k, bytes_needed; struct timespec ts; @@ -667,6 +675,55 @@ static size_t ossl_prov_acquire_entropy_from_rtc2(RAND_POOL *pool) } # endif +# if defined(OPENSSL_RAND_SEED_RTSOCK) +static size_t ossl_prov_acquire_entropy_from_rtsock(RAND_POOL *pool) +{ + int fd[2], ret; + long data; + size_t i, bytes_needed; + struct timespec ts; + unsigned char v; + + bytes_needed = ossl_rand_pool_bytes_needed(pool, 4 /*entropy_factor*/); + + for (i = 0; i < bytes_needed; i++) { + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd); + if (ret == -1) + break; + + data = random(); + + while ((ret = write(fd[0], &data, sizeof(data))) < 0 && errno == EINTR); + if (ret < 0) { + close(fd[0]); + close(fd[1]); + break; + } + + while ((ret = read(fd[1], &data, sizeof(data))) < 0 && errno == EINTR); + if (ret < 0) { + close(fd[0]); + close(fd[1]); + break; + } + + /* sleep for 1/65536 of a second (15 us). */ + ts.tv_sec = 0; + ts.tv_nsec = 15000; + nanosleep(&ts, NULL); + + /* Get wall clock time, take 8 bits. */ + clock_gettime(CLOCK_REALTIME, &ts); + v = (unsigned char)(ts.tv_nsec & 0xFF); + ossl_rand_pool_add(pool, &v, sizeof(v), 2); + + close(fd[0]); + close(fd[1]); + } + + return ossl_rand_pool_entropy_available(pool); +} +# endif /* * Try the various seeding methods in turn, exit when successful. * @@ -694,7 +751,7 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool) (void)entropy_available; /* avoid compiler warning */ # if defined(OPENSSL_RAND_SEED_GETRANDOM) - { + if (pool->entropy_source & RAND_ENTROPY_SOURCE_GETRANDOM) { size_t bytes_needed; unsigned char *buffer; ssize_t bytes; @@ -713,10 +770,11 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool) break; } } + + entropy_available = ossl_rand_pool_entropy_available(pool); + if (entropy_available > 0) + return entropy_available; } - entropy_available = ossl_rand_pool_entropy_available(pool); - if (entropy_available > 0) - return entropy_available; # endif # if defined(OPENSSL_RAND_SEED_LIBRANDOM) @@ -726,7 +784,8 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool) # endif # if defined(OPENSSL_RAND_SEED_DEVRANDOM) - if (wait_random_seeded()) { + if ((pool->entropy_source & RAND_ENTROPY_SOURCE_DEVRANDOM) + && wait_random_seeded()) { size_t bytes_needed; unsigned char *buffer; size_t i; @@ -766,19 +825,23 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool) # endif # if defined(OPENSSL_RAND_SEED_RDTSC) - entropy_available = ossl_prov_acquire_entropy_from_tsc(pool); - if (entropy_available > 0) - return entropy_available; + if (pool->entropy_source & RAND_ENTROPY_SOURCE_RDTSC) { + entropy_available = ossl_prov_acquire_entropy_from_tsc(pool); + if (entropy_available > 0) + return entropy_available; + } # endif # if defined(OPENSSL_RAND_SEED_RDCPU) - entropy_available = ossl_prov_acquire_entropy_from_cpu(pool); - if (entropy_available > 0) - return entropy_available; + if (pool->entropy_source & RAND_ENTROPY_SOURCE_RDCPU) { + entropy_available = ossl_prov_acquire_entropy_from_cpu(pool); + if (entropy_available > 0) + return entropy_available; + } # endif # if defined(OPENSSL_RAND_SEED_EGD) - { + if (pool->entropy_source & RAND_ENTROPY_SOURCE_EGD) { static const char *paths[] = { DEVRANDOM_EGD, NULL }; size_t bytes_needed; unsigned char *buffer; @@ -804,14 +867,28 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool) } # endif -# if defined(OPENSSL_RAND_SEED_RTC) - entropy_available = ossl_prov_acquire_entropy_from_rtc1(pool); - if (entropy_available > 0) - return entropy_available; +# if defined(OPENSSL_RAND_SEED_RTCODE) + if (pool->entropy_source & RAND_ENTROPY_SOURCE_RTCODE) { + entropy_available = ossl_prov_acquire_entropy_from_rtcode(pool); + if (entropy_available > 0) + return entropy_available; + } +# endif + +# if defined(OPENSSL_RAND_SEED_RTMEM) + if (pool->entropy_source & RAND_ENTROPY_SOURCE_RTMEM) { + entropy_available = ossl_prov_acquire_entropy_from_rtmem(pool); + if (entropy_available > 0) + return entropy_available; + } +# endif - entropy_available = ossl_prov_acquire_entropy_from_rtc2(pool); - if (entropy_available > 0) - return entropy_available; +# if defined(OPENSSL_RAND_SEED_RTSOCK) + if (pool->entropy_source & RAND_ENTROPY_SOURCE_RTSOCK) { + entropy_available = ossl_prov_acquire_entropy_from_rtsock(pool); + if (entropy_available > 0) + return entropy_available; + } # endif return ossl_rand_pool_entropy_available(pool); diff --git a/providers/implementations/rands/seeding/rand_win.c b/providers/implementations/rands/seeding/rand_win.c index 704705425..6bf741a28 100644 --- a/providers/implementations/rands/seeding/rand_win.c +++ b/providers/implementations/rands/seeding/rand_win.c @@ -53,69 +53,79 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool) # ifdef OPENSSL_RAND_SEED_RDTSC - entropy_available = ossl_prov_acquire_entropy_from_tsc(pool); - if (entropy_available > 0) - return entropy_available; + if (pool->entropy_source & RAND_ENTROPY_SOURCE_RDTSC) { + entropy_available = ossl_prov_acquire_entropy_from_tsc(pool); + if (entropy_available > 0) + return entropy_available; + } # endif # ifdef OPENSSL_RAND_SEED_RDCPU - entropy_available = ossl_prov_acquire_entropy_from_cpu(pool); - if (entropy_available > 0) - return entropy_available; + if (pool->entropy_source & RAND_ENTROPY_SOURCE_RDCPU) { + entropy_available = ossl_prov_acquire_entropy_from_cpu(pool); + if (entropy_available > 0) + return entropy_available; + } # endif # ifdef USE_BCRYPTGENRANDOM - bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); - buffer = ossl_rand_pool_add_begin(pool, bytes_needed); - if (buffer != NULL) { - size_t bytes = 0; - if (BCryptGenRandom(NULL, buffer, bytes_needed, - BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) - bytes = bytes_needed; - - ossl_rand_pool_add_end(pool, bytes, 8 * bytes); - entropy_available = ossl_rand_pool_entropy_available(pool); - } - if (entropy_available > 0) - return entropy_available; -# else - bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); - buffer = ossl_rand_pool_add_begin(pool, bytes_needed); - if (buffer != NULL) { - size_t bytes = 0; - /* poll the CryptoAPI PRNG */ - if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { - if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) + if (pool->entropy_source & RAND_ENTROPY_SOURCE_BCRYPTGENRANDOM) { + bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + buffer = ossl_rand_pool_add_begin(pool, bytes_needed); + if (buffer != NULL) { + size_t bytes = 0; + if (BCryptGenRandom(NULL, buffer, bytes_needed, + BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) bytes = bytes_needed; - CryptReleaseContext(hProvider, 0); + ossl_rand_pool_add_end(pool, bytes, 8 * bytes); + entropy_available = ossl_rand_pool_entropy_available(pool); } - - ossl_rand_pool_add_end(pool, bytes, 8 * bytes); - entropy_available = ossl_rand_pool_entropy_available(pool); + if (entropy_available > 0) + return entropy_available; + } +# else + if (pool->entropy_source & RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_DEF_PROV) { + bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + buffer = ossl_rand_pool_add_begin(pool, bytes_needed); + if (buffer != NULL) { + size_t bytes = 0; + /* poll the CryptoAPI PRNG */ + if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { + if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) + bytes = bytes_needed; + + CryptReleaseContext(hProvider, 0); + } + + ossl_rand_pool_add_end(pool, bytes, 8 * bytes); + entropy_available = ossl_rand_pool_entropy_available(pool); + } + if (entropy_available > 0) + return entropy_available; } - if (entropy_available > 0) - return entropy_available; - - bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); - buffer = ossl_rand_pool_add_begin(pool, bytes_needed); - if (buffer != NULL) { - size_t bytes = 0; - /* poll the Pentium PRG with CryptoAPI */ - if (CryptAcquireContextW(&hProvider, NULL, - INTEL_DEF_PROV, PROV_INTEL_SEC, - CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { - if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) - bytes = bytes_needed; - CryptReleaseContext(hProvider, 0); + if (pool->entropy_source & RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_INTEL_PROV) { + bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + buffer = ossl_rand_pool_add_begin(pool, bytes_needed); + if (buffer != NULL) { + size_t bytes = 0; + /* poll the Pentium PRG with CryptoAPI */ + if (CryptAcquireContextW(&hProvider, NULL, + INTEL_DEF_PROV, PROV_INTEL_SEC, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { + if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) + bytes = bytes_needed; + + CryptReleaseContext(hProvider, 0); + } + ossl_rand_pool_add_end(pool, bytes, 8 * bytes); + entropy_available = ossl_rand_pool_entropy_available(pool); } - ossl_rand_pool_add_end(pool, bytes, 8 * bytes); - entropy_available = ossl_rand_pool_entropy_available(pool); + if (entropy_available > 0) + return entropy_available; } - if (entropy_available > 0) - return entropy_available; # endif return ossl_rand_pool_entropy_available(pool); diff --git a/providers/implementations/rands/smtc_rng.c b/providers/implementations/rands/smtc_rng.c index e7c3aace0..8877966ff 100644 --- a/providers/implementations/rands/smtc_rng.c +++ b/providers/implementations/rands/smtc_rng.c @@ -24,20 +24,62 @@ #include "prov/seeding.h" #include "crypto/evp.h" -#define REPEAT_COUNT_TEST_THRESHOLD 26 typedef struct smtc_crng_test_global_st { CRYPTO_RWLOCK *lock; - unsigned char last_bit; + EVP_MD_CTX *md_ctx; + int sample; size_t cnt; } SMTC_CRNG_TEST_GLOBAL; -static int get_bit(const unsigned char *buf, int m) +/* Modified based on hash_df() in drbg_hash.c */ +static int sm3_df(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen, + const unsigned char *in, size_t inlen) { - if (m < 0) - return 0; + unsigned char vtmp[EVP_MAX_MD_SIZE]; + /* tmp = counter || num_bits_returned */ + unsigned char tmp[1 + 4]; + int tmp_sz = 0; + size_t blocklen = EVP_MD_get_size(EVP_sm3()); + size_t num_bits_returned = outlen * 8; + + /* counter = 1 (tmp[0] is the 8 bit counter) */ + tmp[tmp_sz++] = 1; + /* tmp[1..4] is the fixed 32 bit no_of_bits_to_return */ + tmp[tmp_sz++] = (unsigned char)((num_bits_returned >> 24) & 0xff); + tmp[tmp_sz++] = (unsigned char)((num_bits_returned >> 16) & 0xff); + tmp[tmp_sz++] = (unsigned char)((num_bits_returned >> 8) & 0xff); + tmp[tmp_sz++] = (unsigned char)(num_bits_returned & 0xff); + + for (;;) { + /* + * out = out || Hash(tmp || in) + * (where tmp = counter || num_bits_returned) + */ + if (!(EVP_DigestInit_ex(ctx, EVP_sm3(), NULL) + && EVP_DigestUpdate(ctx, tmp, tmp_sz) + && EVP_DigestUpdate(ctx, in, inlen))) + return 0; + + if (outlen < blocklen) { + if (!EVP_DigestFinal(ctx, vtmp, NULL)) + return 0; + memcpy(out, vtmp, outlen); + OPENSSL_cleanse(vtmp, blocklen); + break; + } else if(!EVP_DigestFinal(ctx, out, NULL)) { + return 0; + } + + outlen -= blocklen; + if (outlen == 0) + break; - return (buf[m / 8] << (m % 8) >> 7) & 1; + tmp[0]++; + out += blocklen; + } + + return 1; } static void rand_smtc_crng_ossl_ctx_free(void *vcrngt_glob) @@ -45,6 +87,7 @@ static void rand_smtc_crng_ossl_ctx_free(void *vcrngt_glob) SMTC_CRNG_TEST_GLOBAL *smtc_glob = vcrngt_glob; CRYPTO_THREAD_lock_free(smtc_glob->lock); + EVP_MD_CTX_free(smtc_glob->md_ctx); OPENSSL_free(smtc_glob); } @@ -55,11 +98,19 @@ static void *rand_smtc_crng_ossl_ctx_new(OSSL_LIB_CTX *ctx) if (smtc_glob == NULL) return NULL; + if ((smtc_glob->md_ctx = EVP_MD_CTX_new()) == NULL) { + OPENSSL_free(smtc_glob); + return NULL; + } + if ((smtc_glob->lock = CRYPTO_THREAD_lock_new()) == NULL) { OPENSSL_free(smtc_glob); return NULL; } + smtc_glob->sample = -1; + smtc_glob->cnt = 0; + return smtc_glob; } @@ -69,34 +120,26 @@ static const OSSL_LIB_CTX_METHOD rand_smtc_ossl_ctx_method = { rand_smtc_crng_ossl_ctx_free, }; +/* 1 + ceil(20/H) */ +#define REPEAT_COUNT_TEST_THRESHOLD 4 /* * GM/T 0105-2021 Appendix D.2, Repeat Count Test */ static int smtc_rng_repeat_count_test(SMTC_CRNG_TEST_GLOBAL *crngt, - unsigned char *pout, size_t len, - OSSL_SELF_TEST *st) + const unsigned char *entropy, size_t len) { - size_t i = 0; + size_t i; - if (len <= 0) + if (entropy == NULL || len == 0) return 0; - if (crngt->cnt == 0) { - crngt->last_bit = get_bit(pout, 0); - crngt->cnt = i = 1; - } - - for (; i < len * 8; i++) { - unsigned char bit = get_bit(pout, i); - if (bit == crngt->last_bit) { + for (i = 0; i < len; i++) { + if (entropy[i] == crngt->sample) { crngt->cnt++; - if (crngt->cnt >= REPEAT_COUNT_TEST_THRESHOLD) { - crngt->cnt = 0; - OSSL_SELF_TEST_oncorrupt_byte(st, &pout[i / 8]); + if (crngt->cnt >= REPEAT_COUNT_TEST_THRESHOLD) return 0; - } } else { - crngt->last_bit = bit; + crngt->sample = entropy[i]; crngt->cnt = 1; } } @@ -108,14 +151,15 @@ size_t ossl_smtc_get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy, size_t min_len, size_t max_len, int prediction_resistance) { - int crng_test_pass = 0; + unsigned char buf[CRNGT_BUFSIZ]; + int crng_test_pass = 1; OSSL_CALLBACK *stcb = NULL; void *stcbarg = NULL; + unsigned char *ent, *entp, *entbuf; + unsigned char *p = NULL; OSSL_SELF_TEST *st = NULL; - size_t ret - = ossl_prov_get_entropy(drbg->provctx, pout, entropy, min_len, max_len); - if (ret == 0) - return 0; + size_t bytes_needed; + size_t r = 0, s, t, n; OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx); SMTC_CRNG_TEST_GLOBAL *crngt_glob = ossl_lib_ctx_get_data( @@ -127,6 +171,20 @@ size_t ossl_smtc_get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy, if (!CRYPTO_THREAD_write_lock(crngt_glob->lock)) return 0; + /* + * Calculate how many bytes of seed material we require, rounded up + * to the nearest byte. + */ + bytes_needed = (entropy + 7) / 8; + if (bytes_needed < min_len) + bytes_needed = min_len; + if (bytes_needed > max_len) + goto unlock_return; + + entp = ent = OPENSSL_secure_malloc(bytes_needed); + if (ent == NULL) + goto unlock_return; + OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg); if (stcb != NULL) { st = OSSL_SELF_TEST_new(stcb, stcbarg); @@ -136,16 +194,52 @@ size_t ossl_smtc_get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy, OSSL_SELF_TEST_DESC_RNG); } - if (!smtc_rng_repeat_count_test(crngt_glob, *pout, ret, st)) { - ret = 0; - goto err; - } + for (t = bytes_needed; t > 0;) { + /* Care needs to be taken to avoid overrunning the buffer */ + s = t >= CRNGT_BUFSIZ ? CRNGT_BUFSIZ : t; + entbuf = t >= CRNGT_BUFSIZ ? entp : buf; + + n = ossl_prov_get_entropy(drbg->provctx, &p, 0, CRNGT_BUFSIZ, + CRNGT_BUFSIZ); + if (n == CRNGT_BUFSIZ) { + if (OSSL_SELF_TEST_oncorrupt_byte(st, p)) + memset(p, 0, n); + + if (!smtc_rng_repeat_count_test(crngt_glob, p, n)) { + ossl_set_error_state(OSSL_SELF_TEST_TYPE_CRNG); + crng_test_pass = 0; + goto err; + } + + if (!sm3_df(crngt_glob->md_ctx, entbuf, CRNGT_BUFSIZ, p, + CRNGT_BUFSIZ)) + goto err; + + ossl_prov_cleanup_entropy(drbg->provctx, p, n); + } + + if (n != 0) { + ossl_prov_cleanup_entropy(drbg->provctx, p, n); + p = NULL; + goto err; + } - crng_test_pass = 1; + if (t < CRNGT_BUFSIZ) + memcpy(entp, buf, t); -err: + entp += s; + t -= s; + } + r = bytes_needed; + *pout = ent; + ent = NULL; + + err: OSSL_SELF_TEST_onend(st, crng_test_pass); OSSL_SELF_TEST_free(st); + OPENSSL_secure_clear_free(ent, bytes_needed); + + unlock_return: CRYPTO_THREAD_unlock(crngt_glob->lock); - return ret; + return r; } diff --git a/providers/prov_running.c b/providers/prov_running.c index 379fd5d25..e51b7024f 100644 --- a/providers/prov_running.c +++ b/providers/prov_running.c @@ -10,6 +10,7 @@ #include #include "prov/providercommon.h" +#ifndef SMTC_MODULE /* By default, our providers don't have an error state */ void ossl_set_error_state(const char *type) { @@ -20,3 +21,4 @@ int ossl_prov_is_running(void) { return 1; } +#endif diff --git a/providers/smtc/README.md b/providers/smtc/README.md index 1a7f2ee22..79b3d5bcf 100644 --- a/providers/smtc/README.md +++ b/providers/smtc/README.md @@ -1,25 +1,23 @@ -# 构建SMTC +# Build SMTC + +build SMTC with atf_slibce and atf_sdf as follows: ``` -./config enable-smtc enable-ntls no-shared enable-ssl-trace --prefix=/opt/tongsuo -Wl,-rpath,/opt/tongsuo/lib64 +./config no-shared no-module enable-ntls enable-smtc enable-smtc-debug enable-ssl-trace enable-trace --debug --prefix=/path/to/tongsuo --libdir=/path/to/tongsuo/lib/ --api=1.1.1 --with-rand-seed=rtcode,rtmem,rtsock -DTONGSUO_RAND_GM_SRNG --strict-warnings enable-atf_slibce --with-atf_slibce-lib=../libatf_slibce.a --smtc-pubkey=/tmp/smtcpub.key enable-sdf-lib --with-sdf-lib=/atf-libs-static/libatf_sdf.a --with-sdf-include=/atf-includes/atf-sdf -make +make -j make install ``` -# 配置SMTC +# Install SMTC ``` -/opt/tongsuo/bin/tongsuo mod -module /opt/tongsuo/bin/tongsuo -provider_name smtc -section_name smtc_sect -show_selftest -out /opt/tongsuo/ssl/smtcmodule.cnf - -# 修改/opt/tongsuo/ssl/openssl.cnf,包含smtcmodule.cnf,设置smtc section -sed -i -e 's|^# .include smtcmodule.cnf|.include /opt/tongsuo/ssl/smtcmodule.cnf|;s/^# smtc = smtc_sect/smtc = smtc_sect/' /opt/tongsuo/ssl/openssl.cnf - +tongsuo mod -install -module /bin/tongsuo -sigfile signature.bin ``` -# SMTC自测试 +# SMTC Self Test ``` -/opt/tongsuo/bin/tongsuo mod -test +tongsuo mod -test ``` diff --git a/providers/smtc/self_test.c b/providers/smtc/self_test.c index e76027833..bf2118189 100644 --- a/providers/smtc/self_test.c +++ b/providers/smtc/self_test.c @@ -7,15 +7,23 @@ * https://www.openssl.org/source/license.html */ +#include "internal/deprecated.h" + #include +#include +#include #include #include #include +#include #include +#include #include "internal/cryptlib.h" #include +#include #include #include "crypto/evp.h" +#include "crypto/rand.h" #include "internal/e_os.h" #include "internal/thread_once.h" #include "prov/providercommon.h" @@ -25,18 +33,143 @@ #include "self_test.h" #include "self_test_rand.h" #include "../implementations/rands/drbg_local.h" -#include "../../crypto/evp/evp_local.h" +#include "crypto/evp/evp_local.h" +#include "crypto/evp/legacy_meth.h" /* The size of a temp buffer used to read in data */ -#define INTEGRITY_BUF_SIZE (4096) -#define MAX_MD_SIZE 64 -#define MAC_NAME "HMAC" -#define DIGEST_NAME "SM3" +#define INTEGRITY_BUF_SIZE 4096 +#define SMTC_PASSWD_LEN 64 +#define SMTC_AUTH_SALT_LEN 64 +#define SMTC_AUTH_KEY_LEN 64 + +#define SMTC_AUTH_ID "SMTC" +#define SMTC_AUTH_TEXT1 "login" +#define SMTC_AUTH_TEXT2 "_admin_" +#define SMTC_AUTH_TIMEOUT 60 + +static int SMTC_conditional_error_check = 1; static CRYPTO_RWLOCK *self_test_lock = NULL; static CRYPTO_RWLOCK *smtc_state_lock = NULL; static int smtc_state = SMTC_STATE_INIT; -static unsigned char fixed_key[32] = { SMTC_KEY_ELEMENTS }; +static unsigned char pubkey[] = SMTC_KEY_STRING; +static unsigned char smtc_passwd[] = {SMTC_DEFAULT_PASSWORD_ELEMENTS}; + +#ifndef OPENSSL_NO_ATF_SLIBCE +IMPLEMENT_LEGACY_EVP_MD_METH(sm3_sw, SM3) +static EVP_MD *sm3_md = NULL; +static const EVP_MD *sw_sm3_md(void) +{ + if (sm3_md == NULL) { + EVP_MD *md; + + if ((md = EVP_MD_meth_new(NID_sm3, NID_SM2_with_SM3)) == NULL + || !EVP_MD_meth_set_result_size(md, SM3_DIGEST_LENGTH) + || !EVP_MD_meth_set_input_blocksize(md, SM3_CBLOCK) + || !EVP_MD_meth_set_app_datasize(md, + sizeof(EVP_MD *) + sizeof(SM3_CTX)) + || !EVP_MD_meth_set_flags(md, 0) + || !EVP_MD_meth_set_init(md, sm3_sw_init) + || !EVP_MD_meth_set_update(md, sm3_sw_update) + || !EVP_MD_meth_set_final(md, sm3_sw_final)) { + EVP_MD_meth_free(md); + md = NULL; + } + sm3_md = md; + } + return sm3_md; +} + +static int sw_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) +{ + static int digest_nids[2] = { NID_sm3, 0}; + int ok = 1; + if (!digest) { + *nids = digest_nids; + return OSSL_NELEM(digest_nids); + } + + switch (nid) { + case NID_sm3: + *digest = sw_sm3_md(); + break; + default: + ok = 0; + *digest = NULL; + break; + } + + return ok; +} + +static CRYPTO_ONCE engine_atf_slibce = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(init_engine_atf_slibce) +{ + int ok = 0; + ENGINE *engine = NULL; + +# ifdef OPENSSL_NO_DYNAMIC_ENGINE + extern ENGINE *engine_atf_slibce_load(const char* engine_name); + engine = engine_atf_slibce_load("atf_slibce"); +# else + engine = ENGINE_by_id("atf_slibce"); +# endif + if (engine == NULL) + return 0; + + if(!ENGINE_ctrl_cmd_string(engine, "engine_load", NULL, 0)) { + OSSL_TRACE(SMTC, "Failed to execute cmd: engine_load\n"); + goto end; + } + + if(!ENGINE_ctrl_cmd_string(engine, "engine_alloc_prsrc", NULL, 0)) { + OSSL_TRACE(SMTC, "Failed to execute cmd: engine_alloc_prsrc\n"); + goto end; + } + + if(!ENGINE_ctrl_cmd_string(engine, "engine_enable_sm2", NULL, 0)) { + OSSL_TRACE(SMTC, "Failed to execute cmd: engine_enable_sm2\n"); + goto end; + } + + if(!ENGINE_ctrl_cmd_string(engine, "engine_enable_sm4", NULL, 0)) { + OSSL_TRACE(SMTC, "Failed to execute cmd: engine_enable_sm4\n"); + goto end; + } + + if(!ENGINE_ctrl_cmd_string(engine, "engine_enable_asym_kek", NULL, 0)) { + OSSL_TRACE(SMTC, "Failed to execute cmd: engine_enable_asym_kek\n"); + goto end; + } + + if(!ENGINE_ctrl_cmd_string(engine, "engine_enable_kek", NULL, 0)) { + OSSL_TRACE(SMTC, "Failed to execute cmd: engine_enable_kek\n"); + goto end; + } + + if(!ENGINE_ctrl_cmd_string(engine, "engine_enable_kgen_kek", NULL, 0)) { + OSSL_TRACE(SMTC, "Failed to execute cmd: engine_enable_kgen_kek\n"); + goto end; + } + + if (!ENGINE_set_digests(engine, sw_digests)) + goto end; + + if (!ENGINE_set_default_pkey_meths(engine)) + goto end; + + ok = 1; +end: +# ifdef OPENSSL_NO_DYNAMIC_ENGINE + if (ok == 0) +# endif + { + ENGINE_free(engine); + } + return ok; +} +#endif static CRYPTO_ONCE smtc_self_test_init = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(do_smtc_self_test_init) @@ -52,93 +185,241 @@ DEFINE_RUN_ONCE_STATIC(do_smtc_self_test_init) } /* - * Calculate the HMAC SM3 of data read using a BIO and read_cb, and verify - * the result matches the expected value. + * Verify the signatre(SM2withSM3) of data read using a BIO and read_cb, and + * verify the result matches the expected value. * Return 1 if verified, or 0 if it fails. */ -static int verify_integrity(OSSL_CORE_BIO *bio, OSSL_FUNC_BIO_read_ex_fn read_ex_cb, +static int verify_integrity(OSSL_CORE_BIO *bio, + OSSL_FUNC_BIO_read_ex_fn read_ex_cb, unsigned char *expected, size_t expected_len, - OSSL_LIB_CTX *libctx, OSSL_SELF_TEST *ev, - const char *event_type) + OSSL_LIB_CTX *libctx, OSSL_SELF_TEST *ev) { - int ret = 0, status; - unsigned char out[MAX_MD_SIZE]; + int ok = 0, status; + BIO *pkey_bio = NULL; unsigned char buf[INTEGRITY_BUF_SIZE]; - size_t bytes_read = 0, out_len = 0; - EVP_MAC *mac = NULL; - EVP_MAC_CTX *ctx = NULL; - OSSL_PARAM params[2], *p = params; + size_t bytes_read = 0; + EVP_MD_CTX *mctx = NULL; + EVP_PKEY *pkey = NULL; - OSSL_SELF_TEST_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC); + OSSL_SELF_TEST_onbegin(ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY, + OSSL_SELF_TEST_DESC_INTEGRITY_VERIFY); - mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL); - if (mac == NULL) - goto err; - ctx = EVP_MAC_CTX_new(mac); - if (ctx == NULL) - goto err; + pkey_bio = BIO_new_mem_buf(pubkey, sizeof(pubkey)); + if (pkey_bio == NULL) + goto end; - *p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, 0); - *p = OSSL_PARAM_construct_end(); + pkey = PEM_read_bio_PUBKEY_ex(pkey_bio, NULL, NULL, NULL, libctx, NULL); + if (pkey == NULL) + goto end; - if (!EVP_MAC_init(ctx, fixed_key, sizeof(fixed_key), params)) - goto err; + mctx = EVP_MD_CTX_new(); + if (mctx == NULL) + goto end; + + if (EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey) != 1) + goto end; while (1) { status = read_ex_cb(bio, buf, sizeof(buf), &bytes_read); if (status != 1) break; - if (!EVP_MAC_update(ctx, buf, bytes_read)) - goto err; - } - if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out))) - goto err; - - OSSL_SELF_TEST_oncorrupt_byte(ev, out); - if (expected_len != out_len - || memcmp(expected, out, out_len) != 0) - goto err; - ret = 1; -err: - OSSL_SELF_TEST_onend(ev, ret); - EVP_MAC_CTX_free(ctx); - EVP_MAC_free(mac); - return ret; + if (EVP_DigestVerifyUpdate(mctx, buf, bytes_read) != 1) + goto end; + } + + OSSL_SELF_TEST_oncorrupt_byte(ev, expected); + + if (EVP_DigestVerifyFinal(mctx, expected, expected_len) != 1) + goto end; + + ok = 1; +end: + BIO_free(pkey_bio); + EVP_PKEY_free(pkey); + EVP_MD_CTX_free(mctx); + OSSL_SELF_TEST_onend(ev, ok); + return ok; } #define PASSWD_BUF_SIZE 1024 -static int verify_password(OSSL_LIB_CTX *libctx, unsigned char *password, - size_t pass_len, unsigned char *salt, - size_t salt_len) +static int do_auth(time_t ts, const char *text2, unsigned char *mac, + size_t mac_len, const unsigned char *mac_key, + size_t mac_key_len) { - int ret = 0; - char passphrase[PASSWD_BUF_SIZE]; - EVP_MD_CTX *mctx = NULL; - unsigned char buf[EVP_MAX_MD_SIZE]; + int ok = 0; + time_t now = time(NULL); + char buf[128]; + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int md_len; + int buflen; + + if (ts > now || now - ts > SMTC_AUTH_TIMEOUT) + return 0; + + if (text2 == NULL || strcmp(text2, SMTC_AUTH_TEXT2) != 0) + return 0; + + buflen = snprintf(buf, sizeof(buf), "%ld%s%s", ts, SMTC_AUTH_ID, + SMTC_AUTH_TEXT1); + if (buflen < 0 || buflen >= (int)sizeof(buf)) + return 0; + + if (HMAC(EVP_sm3(), mac_key, mac_key_len, (const unsigned char *)buf, + buflen, md, &md_len) == NULL) + goto end; + + if (md_len != mac_len || memcmp(md, mac, md_len) != 0) { + OSSL_TRACE(SMTC, "Incorrect password\n"); + goto end; + } + + ok = 1; +end: + return ok; +} + +static int verify_password(OSSL_LIB_CTX *libctx, const char *conf_key, + const char *conf_salt, const char *kek_file, + const char *eng) +{ + int ok = 0; + time_t ts; + unsigned char buf[128]; + unsigned char *mac_key = NULL, *salt = NULL; + long mac_key_len, salt_len; + char passphrase[SMTC_PASSWD_LEN]; + unsigned char key[SMTC_AUTH_KEY_LEN]; + unsigned char mkey[SMTC_AUTH_KEY_LEN]; + int buflen, keklen; + size_t outlen; + unsigned char mac[EVP_MAX_MD_SIZE]; + unsigned int maclen; + ENGINE *engine = NULL; + BIO *bio = NULL, *kekbio = NULL; + EVP_PKEY *pkek = NULL; + EVP_PKEY_CTX *ctx = NULL; + unsigned char kekbuf[4096]; + + if (conf_key == NULL && conf_salt == NULL) { + if (EVP_read_pw_string(passphrase, sizeof(passphrase), + "Enter password: ", 0) != 0) + goto end; - if (password == NULL || pass_len != SM3_DIGEST_LENGTH || salt == NULL - || salt_len != SM3_DIGEST_LENGTH) + if (memcmp(passphrase, smtc_passwd, sizeof(smtc_passwd)) != 0) { + OSSL_TRACE(SMTC, "Incorrect password\n"); + goto end; + } + + ok = 1; goto end; + } + + if (conf_key == NULL || conf_salt == NULL) + goto end; + + mac_key = OPENSSL_hexstr2buf(conf_key, &mac_key_len); + if (mac_key == NULL) + goto end; + + salt = OPENSSL_hexstr2buf(conf_salt, &salt_len); + if (salt == NULL || salt_len != SMTC_AUTH_SALT_LEN) + goto end; + + ts = time(NULL); if (EVP_read_pw_string(passphrase, sizeof(passphrase), "Enter password: ", 0) != 0) goto end; - if ((mctx = EVP_MD_CTX_new()) == NULL - || !EVP_DigestInit_ex(mctx, EVP_sm3(), NULL) - || !EVP_DigestUpdate(mctx, salt, salt_len) - || !EVP_DigestUpdate(mctx, passphrase, strlen(passphrase)) - || !EVP_DigestFinal_ex(mctx, buf, NULL)) + if (PKCS5_PBKDF2_HMAC(passphrase, strlen(passphrase), salt, salt_len, + 10000, EVP_sm3(), sizeof(key), key) != 1) + goto end; + + buflen = snprintf((char *)buf, sizeof(buf), "%ld%s%s", ts, SMTC_AUTH_ID, + SMTC_AUTH_TEXT1); + if (buflen < 0 || buflen >= (int)sizeof(buf)) + goto end; + + if (HMAC(EVP_sm3(), key, sizeof(key), buf, buflen, mac, &maclen) == NULL) + goto end; + + if (eng) { + engine = ENGINE_by_id(eng); + if (engine == NULL) { + OSSL_TRACE1(SMTC, "Can't load engine %s\n", eng); + goto end; + } + } + + kekbio = BIO_new_file(kek_file, "rb"); + if (kekbio == NULL) { + OSSL_TRACE1(SMTC, "Can't open auth kek file %s\n", kek_file); + goto end; + } + + keklen = BIO_read(kekbio, kekbuf, sizeof(kekbuf) - 1); + BIO_free(kekbio); + + if (keklen <= 0) { + OSSL_TRACE1(SMTC, "Error reading auth kek %s\n", kek_file); + goto end; + } + + kekbuf[keklen] = '\0'; + + /* + * atf_slibce engine doesn't support ENGINE_load_private_key(), use + * PEM_read_bio_PrivateKey() instead + */ +#ifdef OPENSSL_NO_ATF_SLIBCE + if (engine) { + pkek = ENGINE_load_private_key(engine, (const char *)kekbuf, NULL, + NULL); + } else { +#endif + bio = BIO_new_mem_buf((const void *)kekbuf, keklen); + if (bio == NULL) + goto end; + + pkek = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); +#ifdef OPENSSL_NO_ATF_SLIBCE + } +#endif + + if (pkek == NULL) goto end; - if (memcmp(buf, password, pass_len)) + ctx = EVP_PKEY_CTX_new(pkek, engine); + if (ctx == NULL) + goto end; + + outlen = sizeof(mkey); + + if (EVP_PKEY_decrypt_init(ctx) != 1 + || EVP_PKEY_decrypt(ctx, mkey, &outlen, mac_key, mac_key_len) != 1 + || outlen != sizeof(mkey)) goto end; - ret = 1; + if (do_auth(ts, SMTC_AUTH_TEXT2, mac, maclen, mkey, outlen) != 1) + goto end; + + ok = 1; end: - EVP_MD_CTX_free(mctx); - return ret; + if (!ok) { + OSSL_TRACE(SMTC, "Authentication failed\n"); + OSSL_syslog(LOG_ERR, "[SMTC] Admin login failed!\n"); + ossl_sleep(3000); + } else { + OSSL_syslog(LOG_INFO, "[SMTC] Admin login success\n"); + } + EVP_PKEY_CTX_free(ctx); + OPENSSL_free(mac_key); + OPENSSL_free(salt); + ENGINE_free(engine); + EVP_PKEY_free(pkek); + BIO_free_all(bio); + return ok; } int smtc_prov_get_state(void) @@ -161,82 +442,108 @@ static void smtc_set_state(int state) smtc_state = state; CRYPTO_THREAD_unlock(smtc_state_lock); } + + if (state == SMTC_STATE_ERROR) { + OSSL_syslog(LOG_ERR, "[SMTC] SMTC module entering error state\n"); + } else if (state == SMTC_STATE_RUNNING) { + OSSL_syslog(LOG_INFO, "[SMTC] SMTC module ready\n"); + } } -static int get_bit(const unsigned char *buf, int m) +/* + * GM/T 0105-2021 Appendix D.3, Adaptive Proportion Test + */ +static ossl_unused int smtc_adaptive_proportion_test( + const unsigned char *entropy, size_t len, int W, int C) { - if (m < 0) + size_t i; + int cnt = 0; + unsigned char sample = 0; + + if (entropy == NULL) return 0; - return (buf[m / 8] << (m % 8) >> 7) & 1; + for (i = 0; i < len; i++) { + if (i % W == 0) { + sample = entropy[i]; + cnt = 1; + } else if (entropy[i] == sample) { + cnt++; + if (cnt >= C) + return 0; + } + } + + return 1; } -/* - * GM/T 0105-2021 Appendix D.3, Adaptive Proportion Test - */ static int ossl_smtc_rng_poweron_test(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) { - int res = 0, i; - int W = 1024, C = 670, cnt; - unsigned char buf[W / 8]; - size_t left = sizeof(buf); - size_t len, entropy_len; - int sample; + int ok = 0; unsigned char *entropy = NULL; - EVP_RAND *rand = NULL; - EVP_RAND_CTX *ctx = NULL; - PROV_DRBG *drbg; + size_t ret = 0; +#if defined(OPENSSL_RAND_SEED_RTCODE) || defined(OPENSSL_RAND_SEED_RTMEM) \ + || defined(OPENSSL_RAND_SEED_RTSOCK) + size_t len = 1024, W = 512, C = 13; +#endif OSSL_SELF_TEST_onbegin(st, "Poweron_RNG_Test", "RNG"); - rand = EVP_RAND_fetch(libctx, "HASH-DRBG", NULL); - if (rand == NULL) - goto end; - - ctx = EVP_RAND_CTX_new(rand, NULL); - if (ctx == NULL) +#if defined(OPENSSL_RAND_SEED_RTCODE) + ret = ossl_rand_get_entropy_from_source(RAND_ENTROPY_SOURCE_RTCODE, + &entropy, 0, len, len); + if (ret == len) { + if (!smtc_adaptive_proportion_test(entropy, len, W, C)) + goto end; + } else { goto end; + } - drbg = (PROV_DRBG *)ctx->algctx; - if (drbg == NULL) - goto end; + ossl_rand_cleanup_entropy(NULL, entropy, len); + entropy = NULL; +#endif - while (left > 0) { - entropy_len - = ossl_prov_get_entropy(drbg->provctx, &entropy, left * 8, - drbg->min_entropylen, drbg->max_entropylen); - if (entropy_len == 0) +#if defined(OPENSSL_RAND_SEED_RTMEM) + entropy = NULL; + ret = ossl_rand_get_entropy_from_source(RAND_ENTROPY_SOURCE_RTMEM, + &entropy, 0, len, len); + if (ret == len) { + if (!smtc_adaptive_proportion_test(entropy, len, W, C)) goto end; + } else { + goto end; + } - len = entropy_len > left ? left : entropy_len; - memcpy(buf + (sizeof(buf) - left), entropy, len); - left -= len; + ossl_rand_cleanup_entropy(NULL, entropy, len); + entropy = NULL; +#endif - ossl_prov_cleanup_entropy(drbg->provctx, entropy, entropy_len); - entropy = NULL; +#if defined(OPENSSL_RAND_SEED_RTSOCK) + ret = ossl_rand_get_entropy_from_source(RAND_ENTROPY_SOURCE_RTSOCK, + &entropy, 0, len, len); + if (ret == len) { + if (!smtc_adaptive_proportion_test(entropy, len, W, C)) + goto end; + } else { + goto end; } - sample = get_bit(buf, 0); - cnt = 1; + ossl_rand_cleanup_entropy(NULL, entropy, len); + entropy = NULL; +#endif - for (i = 1; i < W; i++) { - int cur = get_bit(buf, i); - if (cur == sample) { - cnt++; - if (cnt >= C) - goto end; - } else { - sample = cur; - cnt = 1; - } + ok = 1; +#if defined(OPENSSL_RAND_SEED_RTCODE) || defined(OPENSSL_RAND_SEED_RTMEM) \ + || defined(OPENSSL_RAND_SEED_RTSOCK) +end: +#endif + if (entropy) { + ossl_rand_cleanup_entropy(NULL, entropy, ret); + entropy = NULL; } - res = 1; -end: - OSSL_SELF_TEST_onend(st, res); - EVP_RAND_CTX_free(ctx); - EVP_RAND_free(rand); - return res; + OSSL_SELF_TEST_onend(st, ok); + return ok; } /* This API is triggered either on loading of the SMTC module or on demand */ @@ -244,16 +551,21 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test) { int ok = 0; int loclstate; - long checksum_len; - long pass_len, salt_len; + long siglen; OSSL_CORE_BIO *bio_module = NULL; - unsigned char *module_checksum = NULL; - unsigned char *password = NULL, *salt = NULL; + unsigned char *module_sig = NULL; OSSL_SELF_TEST *ev = NULL; if (!RUN_ONCE(&smtc_self_test_init, do_smtc_self_test_init)) return 0; +#ifndef OPENSSL_NO_ATF_SLIBCE + if (!RUN_ONCE(&engine_atf_slibce, init_engine_atf_slibce)) { + OSSL_TRACE(SMTC, "Failed to load atf_slibce engine\n"); + goto end; + } +#endif + if (!CRYPTO_THREAD_write_lock(self_test_lock)) return 0; if (!CRYPTO_THREAD_read_lock(smtc_state_lock)) { @@ -285,25 +597,24 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test) goto end; #ifndef OPENSSL_NO_SMTC_DEBUG - if (st->verify_mac == NULL || atoi(st->verify_mac) != 0) + if (st->verify_sig == NULL || atoi(st->verify_sig) != 0) #endif { - if (st->module_filename == NULL || st->module_checksum_data == NULL) { + if (st->module_filename == NULL || st->module_sig == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CONFIG_DATA); goto end; } bio_module = ossl_prov_bio_new_file(st->module_filename, "rb"); - module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data, - &checksum_len); - if (bio_module == NULL || module_checksum == NULL) { + module_sig = OPENSSL_hexstr2buf(st->module_sig, &siglen); + if (bio_module == NULL || module_sig == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA); goto end; } - if (!verify_integrity(bio_module, ossl_prov_bio_read_ex, - module_checksum, checksum_len, st->libctx, - ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY)) { + if (!verify_integrity(bio_module, ossl_prov_bio_read_ex, module_sig, + siglen, st->libctx, ev)) { + OSSL_TRACE(SMTC, "Module integrity verification failed\n"); ERR_raise(ERR_LIB_PROV, PROV_R_MODULE_INTEGRITY_FAILURE); goto end; } @@ -319,12 +630,20 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test) if ((st->randomness_poweron_test == NULL || atoi(st->randomness_poweron_test) != 0) - && !smtc_randomness_test_poweron(ev, st->libctx)) { + && (!smtc_rand_poweron_test(ev, 0) +#ifdef SDF_LIB + || !smtc_rand_poweron_test(ev, 1) +#endif + )) { ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_POST_FAILURE); goto end; } } else { // SMTC_STATE_SELFTEST_WHILE_RUNNING - if (!smtc_randomness_test_single(ev, st->libctx)) { + if (!smtc_rand_single_test(ev, 0) +#ifdef SDF_LIB + || !smtc_rand_single_test(ev, 1) +#endif + ) { ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_POST_FAILURE); goto end; } @@ -339,46 +658,56 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test) if (st->verify_pass == NULL || atoi(st->verify_pass) != 0) #endif if (loclstate == SMTC_STATE_SELFTEST_WHILE_IN_INIT) { - if (st->admin_pass == NULL || st->admin_salt == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CONFIG_DATA); - goto end; - } - - password = OPENSSL_hexstr2buf(st->admin_pass, &pass_len); - salt = OPENSSL_hexstr2buf(st->admin_salt, &salt_len); - if (password == NULL || salt == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA); - goto end; - } - - if (!verify_password(st->libctx, password, pass_len, salt, salt_len)) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA); + if (!verify_password(st->libctx, st->auth_key, st->auth_salt, st->kek, + st->eng)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INCORRECT_PASSWORD); goto end; } } ok = 1; end: - OPENSSL_free(password); - OPENSSL_free(salt); OSSL_SELF_TEST_free(ev); - OPENSSL_free(module_checksum); + OPENSSL_free(module_sig); if (st != NULL) ossl_prov_bio_free(bio_module); - if (ok) + if (ok) { + OSSL_syslog(LOG_INFO, "[SMTC] Self-test passed\n"); smtc_set_state(SMTC_STATE_RUNNING); - else + } else { + OSSL_syslog(LOG_ERR, "[SMTC] Self-test failed\n"); smtc_set_state(SMTC_STATE_ERROR); + } CRYPTO_THREAD_unlock(self_test_lock); return ok; } -int smtc_prov_is_running(void) +void SELF_TEST_disable_conditional_error_state(void) +{ + SMTC_conditional_error_check = 0; +} + +void ossl_set_error_state(const char *type) +{ + int cond_test = (type != NULL && strcmp(type, OSSL_SELF_TEST_TYPE_PCT) == 0); + + if (!cond_test || (SMTC_conditional_error_check == 1)) { + smtc_set_state(SMTC_STATE_ERROR); + ERR_raise(ERR_LIB_PROV, PROV_R_SMTC_MODULE_ENTERING_ERROR_STATE); + } else { + ERR_raise(ERR_LIB_PROV, PROV_R_SMTC_MODULE_CONDITIONAL_ERROR); + } +} + +int ossl_prov_is_running(void) { int res; + if (!RUN_ONCE(&smtc_self_test_init, do_smtc_self_test_init)) + return 0; + if (!CRYPTO_THREAD_read_lock(smtc_state_lock)) return 0; res = smtc_state == SMTC_STATE_RUNNING diff --git a/providers/smtc/self_test.h b/providers/smtc/self_test.h index 3001fa92b..ffbec9618 100644 --- a/providers/smtc/self_test.h +++ b/providers/smtc/self_test.h @@ -19,15 +19,17 @@ typedef struct self_test_post_params_st { const char *module_filename; /* Module file to perform MAC on */ - const char *module_checksum_data; /* Expected module MAC integrity */ - const char *show_selftest; /* Output selftest results */ - const char *admin_pass; /* Admin password */ - const char *admin_salt; /* Salt of password */ - const char *rng_poweron_test; /* 熵源上电健康测试 */ - const char *rng_continuous_test; /* 熵源连续健康测试 */ - const char *randomness_poweron_test; /* 随机数上电自检 */ + const char *module_sig; /* Signature of module */ + const char *auth_key; /* key of HMAC, PBKDF(password, salt) */ + const char *auth_salt; /* Salt of PBKDF */ + const char *kek; /* key for encrypting HMAC key */ + const char *eng; /* Engine ID */ + const char *syslog; /* syslog switch */ + const char *rng_poweron_test; /* Entropy power-on health test */ + const char *rng_continuous_test; /* Entropy continuous health test */ + const char *randomness_poweron_test; /* Random power-on self-test */ #ifndef OPENSSL_NO_SMTC_DEBUG - const char *verify_mac; + const char *verify_sig; const char *verify_pass; #endif diff --git a/providers/smtc/self_test_data.inc b/providers/smtc/self_test_data.inc index be618233b..741466bf3 100644 --- a/providers/smtc/self_test_data.inc +++ b/providers/smtc/self_test_data.inc @@ -66,7 +66,7 @@ typedef struct st_kat_kdf_st { size_t expected_len; } ST_KAT_KDF; -typedef struct st_kat_drbg_st { +typedef struct st_kat_smtc_drbg_st { const char *desc; const char *algorithm; const char *param_name; @@ -85,9 +85,17 @@ typedef struct st_kat_drbg_st { size_t entropyaddin1len; const unsigned char *entropyaddin2; size_t entropyaddin2len; + const unsigned char *V; + size_t Vlen; + const unsigned char *C; + size_t Clen; + const unsigned char *V1; + size_t V1len; + const unsigned char *C1; + size_t C1len; const unsigned char *expected; size_t expectedlen; -} ST_KAT_DRBG; +} ST_KAT_SMTC_DRBG; typedef struct st_kat_kas_st { const char *desc; @@ -105,7 +113,10 @@ typedef struct st_kat_sign_st { const char *desc; const char *algorithm; const char *mdalgorithm; + int sign; const ST_KAT_PARAM *key; + const unsigned char *dgst; + size_t dgst_len; const unsigned char *sig_expected; /* Set to NULL if this value changes */ size_t sig_expected_len; } ST_KAT_SIGN; @@ -155,6 +166,20 @@ static const ST_KAT_DIGEST st_kat_digest_tests[] = /*- CIPHER TEST DATA */ #ifndef OPENSSL_NO_SM4 +/* SM4-ECB test data */ +static const unsigned char sm4_ecb_key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, +}; +static const unsigned char sm4_ecb_pt[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, +}; +static const unsigned char sm4_ecb_ct[] = { + 0x68, 0x1E, 0xDF, 0x34, 0xD2, 0x06, 0x96, 0x5E, + 0x86, 0xB3, 0xE9, 0x4F, 0x53, 0x6E, 0x42, 0x46, +}; + /* SM4-CBC test data */ static const unsigned char sm4_cbc_key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, @@ -212,6 +237,16 @@ static const unsigned char sm4_gcm_tag[] = { static const ST_KAT_CIPHER st_kat_cipher_tests[] = { #ifndef OPENSSL_NO_SM4 + { + { + "SM4_ECB", + "SM4-ECB", + ITM(sm4_ecb_pt), + ITM(sm4_ecb_ct) + }, + CIPHER_MODE_ENCRYPT | CIPHER_MODE_DECRYPT, + ITM(sm4_ecb_key), + }, { { "SM4_CBC", @@ -223,6 +258,7 @@ static const ST_KAT_CIPHER st_kat_cipher_tests[] = ITM(sm4_cbc_key), ITM(sm4_cbc_iv), }, +/* { { "SM4_GCM", @@ -236,6 +272,7 @@ static const ST_KAT_CIPHER st_kat_cipher_tests[] = ITM(sm4_gcm_aad), ITM(sm4_gcm_tag), }, +*/ #endif }; @@ -364,21 +401,60 @@ static const unsigned char drbg_hash_sm3_pr_addin1[] = { 0xb2, 0x94, 0x73, 0xe2, 0xfd, 0x39, 0x51, 0x2e, 0xad, 0x45, 0x69, 0xee, 0xe3, 0xe3, 0x80, 0x33, 0x14, 0xab, 0xa7, 0xa3 }; +static const unsigned char drbg_hash_sm3_V_expected[] = { + 0xd3, 0x51, 0x2a, 0xe4, 0x49, 0x45, 0x5b, 0xfc, 0x59, 0x63, 0x5c, 0xad, + 0xd2, 0xd9, 0xe0, 0xa3, 0x17, 0x05, 0xbb, 0x0e, 0x11, 0xc1, 0xc8, 0xce, + 0xfe, 0x6f, 0xd8, 0x87, 0x90, 0x0b, 0xfb, 0x95, 0xf0, 0x7c, 0xb2, 0x4c, + 0x85, 0x93, 0x99, 0x66, 0x89, 0x4f, 0xd6, 0x44, 0x6f, 0xb4, 0xfe, 0xb1, + 0xb1, 0x5b, 0x57, 0xd5, 0x88, 0x70, 0x3c, +}; +static const unsigned char drbg_hash_sm3_C_expected[] = { + 0xf6, 0x8a, 0x6f, 0x03, 0x6f, 0x26, 0xbb, 0x90, 0xc4, 0x3d, 0x08, 0x0e, + 0x99, 0x9b, 0x69, 0xba, 0x59, 0xc1, 0x1e, 0xa7, 0xd8, 0xbb, 0xb4, 0xe8, + 0x59, 0xbc, 0x77, 0x69, 0x27, 0x73, 0xbd, 0x66, 0xf4, 0xc2, 0xac, 0xd4, + 0xc7, 0x80, 0xb6, 0xf7, 0xcf, 0xe3, 0x51, 0xff, 0x0e, 0xec, 0x77, 0xed, + 0x45, 0xb3, 0x3b, 0xb1, 0xd6, 0x64, 0xce, +}; +static const unsigned char drbg_hash_sm3_V1_expected[] = { + 0x8a, 0xb9, 0x3c, 0x9d, 0x9f, 0xfc, 0xc0, 0x64, 0x54, 0x58, 0x48, 0x4c, + 0xa0, 0x0c, 0x01, 0x5f, 0x97, 0x24, 0xc7, 0x07, 0xed, 0x2c, 0x67, 0x5d, + 0xc5, 0xce, 0x7c, 0xf7, 0xba, 0x40, 0x96, 0x2a, 0x77, 0x5a, 0x9c, 0x79, + 0xa0, 0x37, 0xbb, 0xec, 0xb4, 0x48, 0xc0, 0xf2, 0x82, 0x03, 0x33, 0x7c, + 0xa9, 0x95, 0xb3, 0x9f, 0x9f, 0x6f, 0x66, +}; +static const unsigned char drbg_hash_sm3_C1_expected[] = { + 0xe7, 0xca, 0x05, 0x6c, 0x83, 0xcb, 0x42, 0x0e, 0x19, 0xf2, 0x9b, 0xdb, + 0x14, 0x11, 0xf3, 0x8a, 0x07, 0x13, 0xf4, 0x58, 0x43, 0x6d, 0xd6, 0x15, + 0x6e, 0xea, 0x6a, 0x77, 0x45, 0x6f, 0x24, 0x1b, 0xcf, 0x04, 0x15, 0xa1, + 0x8e, 0x63, 0x48, 0x67, 0xae, 0x72, 0x4d, 0xa0, 0xbf, 0x26, 0xae, 0x7f, + 0x5e, 0xc0, 0x97, 0x53, 0x4b, 0x33, 0x63, +}; static const unsigned char drbg_hash_sm3_pr_expected[] = { - 0xc0, 0xd1, 0xef, 0x6f, 0x52, 0xf4, 0x2a, 0xd7, 0xa1, 0xaa, 0x91, 0xbc, - 0x11, 0x7b, 0xdc, 0xa0, 0x74, 0xc0, 0xda, 0x26, 0xa9, 0xba, 0xb1, 0x6a, - 0x0e, 0x43, 0xa0, 0x1b, 0x7d, 0xa5, 0x85, 0xa9, 0xb5, 0x1b, 0xa7, 0xa3, - 0x81, 0x03, 0x70, 0x41, 0x38, 0xf9, 0x40, 0xb4, 0x20, 0x11, 0x99, 0x06, - 0x25, 0x14, 0x88, 0x0a, 0xf7, 0xd6, 0x03, 0x5d, 0x08, 0x13, 0xba, 0x7e, - 0x78, 0xb1, 0x76, 0x75, 0x49, 0x29, 0x7a, 0xf9, 0x54, 0x13, 0xcc, 0x6d, - 0x38, 0x63, 0x1a, 0xd5, 0x9f, 0xc4, 0x1a, 0xdb, 0x6d, 0x10, 0x68, 0x8d, - 0xdf, 0x64, 0xdc, 0x7e, 0xe2, 0x4a, 0x16, 0xde, 0x9a, 0x82, 0x11, 0x00, - 0xd5, 0xc9, 0x77, 0xf8, 0x81, 0x64, 0x66, 0xdb, 0x2a, 0x40, 0x27, 0xc0, - 0x61, 0xb2, 0x05, 0xc4, 0xa7, 0x66, 0xa3, 0x64, 0x61, 0x29, 0xb2, 0x3f, - 0x11, 0x8c, 0x50, 0xbf, 0x8b, 0x64, 0xc0, 0x72, -}; - -static const ST_KAT_DRBG st_kat_drbg_tests[] = + 0xbb, 0xb8, 0x89, 0x31, 0x02, 0x7a, 0xf6, 0x59, 0x27, 0xd6, 0x67, 0x98, + 0xe0, 0xd3, 0xc0, 0x49, 0x38, 0x71, 0x2e, 0x4d, 0x85, 0x62, 0x88, 0x2c, + 0xb4, 0xe3, 0x4d, 0x6f, 0x08, 0xa1, 0xac, 0xcc, 0xff, 0x2b, 0x53, 0xca, + 0x38, 0x52, 0x0b, 0xb9, 0xab, 0x58, 0x87, 0x7c, 0x1c, 0x57, 0xf2, 0x36, + 0xfe, 0x6c, 0x81, 0x91, 0x9e, 0x62, 0x88, 0xb1, 0x8c, 0x76, 0x94, 0xc5, + 0x23, 0x36, 0x48, 0xa8, 0x57, 0xcc, 0x2d, 0x7d, 0x02, 0x9b, 0xc3, 0x9d, + 0xd4, 0x6b, 0x60, 0x63, 0x15, 0xfc, 0x1b, 0xa0, 0x04, 0x17, 0x56, 0x31, + 0x78, 0x66, 0x10, 0xe7, 0x22, 0xe7, 0x53, 0x7d, 0x4f, 0xcd, 0x90, 0x02, + 0xd4, 0xfa, 0x1b, 0xda, 0xca, 0x66, 0xd2, 0x25, 0xa2, 0x47, 0x97, 0x87, + 0x26, 0xbc, 0xeb, 0x6c, 0x18, 0x58, 0x62, 0x07, 0x61, 0x45, 0xf0, 0x76, + 0xd5, 0x1a, 0x21, 0xba, 0xfc, 0x42, 0xf2, 0xc6, 0x98, 0x63, 0x49, 0x45, + 0xde, 0xdb, 0xfa, 0x14, 0x34, 0xc7, 0x30, 0xbe, 0x07, 0xfd, 0xee, 0x55, + 0x30, 0xce, 0xab, 0x54, 0x61, 0xee, 0xcd, 0xd9, 0xdd, 0x34, 0x26, 0x47, + 0xed, 0xf4, 0xbb, 0xa8, 0x32, 0xc6, 0xf6, 0xbc, 0x96, 0xc3, 0x56, 0x32, + 0xf1, 0x4d, 0x3b, 0x8f, 0x10, 0x01, 0x02, 0x69, 0x25, 0xff, 0x4a, 0x71, + 0x6e, 0x8d, 0x78, 0xd7, 0x1e, 0xb1, 0xb7, 0x17, 0x3f, 0x30, 0xd4, 0xa0, + 0x85, 0xe8, 0x87, 0xba, 0x63, 0x63, 0x9f, 0x32, 0x52, 0x27, 0x77, 0xcb, + 0x91, 0x01, 0x0d, 0xbd, 0x29, 0x06, 0xa4, 0x7d, 0x51, 0x58, 0xe3, 0xc1, + 0x29, 0x14, 0xeb, 0x51, 0x30, 0x45, 0xb0, 0x19, 0x2b, 0x4b, 0xe3, 0x9d, + 0xea, 0x40, 0x13, 0xb0, 0xcc, 0x9f, 0x2b, 0xda, 0xe3, 0xd7, 0x49, 0xdd, + 0x90, 0x46, 0xcc, 0x32, 0x28, 0xcc, 0xd5, 0x2e, 0x3f, 0x10, 0x79, 0x05, + 0xa9, 0x28, 0xa0, 0x79, +}; + +static const ST_KAT_SMTC_DRBG st_kat_drbg_tests[] = { { OSSL_SELF_TEST_DESC_DRBG_HASH, @@ -390,6 +466,10 @@ static const ST_KAT_DRBG st_kat_drbg_tests[] = ITM(drbg_hash_sm3_pr_entropyinpr1), ITM(drbg_hash_sm3_pr_addin0), ITM(drbg_hash_sm3_pr_addin1), + ITM(drbg_hash_sm3_V_expected), + ITM(drbg_hash_sm3_C_expected), + ITM(drbg_hash_sm3_V1_expected), + ITM(drbg_hash_sm3_C1_expected), ITM(drbg_hash_sm3_pr_expected) }, }; @@ -703,6 +783,21 @@ static const ST_KAT_PARAM sm2_key[] = { ST_KAT_PARAM_OCTET(OSSL_PKEY_PARAM_PUB_KEY, sm2_pub), ST_KAT_PARAM_END() }; + +static const unsigned char dgst[] = { + 0xD7, 0xAD, 0x39, 0x7F, 0x6F, 0xFA, 0x5D, 0x4F, 0x7F, 0x11, 0xE7, 0x21, + 0x7F, 0x24, 0x16, 0x07, 0xDC, 0x30, 0x61, 0x8C, 0x23, 0x6D, 0x2C, 0x09, + 0xC1, 0xB9, 0xEA, 0x8F, 0xDA, 0xDE, 0xE2, 0xE8, +}; + +static const unsigned char sig_expected[] = { + 0x30, 0x46, 0x02, 0x21, 0x00, 0xAB, 0x1D, 0xB6, 0x4D, 0xE7, 0xC4, 0x0E, + 0xDB, 0xDE, 0x66, 0x51, 0xC9, 0xB8, 0xEB, 0xDB, 0x80, 0x46, 0x73, 0xDB, + 0x83, 0x6E, 0x5D, 0x5C, 0x7F, 0xE1, 0x5D, 0xCF, 0x9E, 0xD2, 0x72, 0x50, + 0x37, 0x02, 0x21, 0x00, 0xEB, 0xA7, 0x14, 0x45, 0x1F, 0xF6, 0x9B, 0x0B, + 0xB9, 0x30, 0xB3, 0x79, 0xE1, 0x92, 0xE7, 0xCD, 0x5F, 0xA6, 0xE3, 0xC4, + 0x1C, 0x7F, 0xBD, 0x83, 0x03, 0xB7, 0x99, 0xAB, 0x54, 0xA5, 0x46, 0x21, +}; #endif static const unsigned char sm2_asym_plaintext_encrypt[] = { @@ -729,15 +824,26 @@ static const unsigned char sm2_asym_expected_encrypt[] = { static const ST_KAT_SIGN st_kat_sign_tests[] = { #ifndef OPENSSL_NO_SM2 { - OSSL_SELF_TEST_DESC_SIGN_SM2, + OSSL_SELF_TEST_DESC_SIGN_SM2_SIGN, "SM2", "SM3", + 1, sm2_key, + ITM(dgst), /* * The SM2 signature changes each time due to it using a random k. * So there is no expected KAT for this case. */ }, + { + OSSL_SELF_TEST_DESC_SIGN_SM2_VERIFY, + "SM2", + "SM3", + 0, + sm2_pub_key, + ITM(dgst), + ITM(sig_expected), + }, #endif }; @@ -759,7 +865,7 @@ static const ST_KAT_ASYM_CIPHER st_kat_asym_cipher_tests[] = { OSSL_SELF_TEST_DESC_ASYM_SM2_DEC, "SM2", 0, - sm2_priv_key, + sm2_key, sm2_enc_params, ITM(sm2_asym_expected_encrypt), ITM(sm2_asym_plaintext_encrypt), diff --git a/providers/smtc/self_test_kats.c b/providers/smtc/self_test_kats.c index 4c4c95177..aa9094f0c 100644 --- a/providers/smtc/self_test_kats.c +++ b/providers/smtc/self_test_kats.c @@ -12,10 +12,22 @@ #include #include #include +#include +#include +#include +#include +#include "crypto/evp.h" #include "internal/cryptlib.h" #include "internal/nelem.h" #include "self_test.h" #include "self_test_data.inc" +#include "../implementations/rands/drbg_local.h" +#include "../../crypto/evp/evp_local.h" +#include "../../crypto/sdf/sdf_local.h" +#ifdef SDF_LIB +# include "sdfe_api.h" +#endif + static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) @@ -247,13 +259,15 @@ static int self_test_kdf(const ST_KAT_KDF *t, OSSL_SELF_TEST *st, return ret; } -static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st, +static int self_test_drbg(const ST_KAT_SMTC_DRBG *t, OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) { int ret = 0; unsigned char out[256]; EVP_RAND *rand; EVP_RAND_CTX *test = NULL, *drbg = NULL; + PROV_DRBG *prov_drbg = NULL; + PROV_DRBG_HASH *hash_drbg = NULL; unsigned int strength = 256; int prediction_resistance = 1; /* Causes a reseed */ OSSL_PARAM drbg_params[3] = { @@ -289,9 +303,6 @@ static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st, drbg_params[0] = OSSL_PARAM_construct_utf8_string(t->param_name, t->param_value, 0); - /* This is only used by HMAC-DRBG but it is ignored by the others */ - drbg_params[1] = - OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_MAC, "HMAC", 0); if (!EVP_RAND_CTX_set_params(drbg, drbg_params)) goto err; @@ -308,6 +319,18 @@ static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st, NULL)) goto err; + prov_drbg = (PROV_DRBG *)drbg->algctx; + if (prov_drbg == NULL) + goto err; + + hash_drbg = (PROV_DRBG_HASH *)prov_drbg->data; + if (hash_drbg == NULL) + goto err; + + if (memcmp(hash_drbg->V, t->V, t->Vlen) != 0 + || memcmp(hash_drbg->C, t->C, t->Clen) != 0) + goto err; + drbg_params[0] = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY, (void *)t->entropyinpr1, @@ -315,9 +338,13 @@ static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st, if (!EVP_RAND_CTX_set_params(test, drbg_params)) goto err; - if (!EVP_RAND_generate(drbg, out, t->expectedlen, strength, - prediction_resistance, - t->entropyaddin1, t->entropyaddin1len)) + if (EVP_RAND_reseed(drbg, prediction_resistance, + t->entropyinpr1, t->entropyinpr1len, + t->entropyaddin1, t->entropyaddin1len) != 1) + goto err; + + if (memcmp(hash_drbg->V, t->V1, t->V1len) != 0 + || memcmp(hash_drbg->C, t->C1, t->C1len) != 0) goto err; drbg_params[0] = @@ -358,8 +385,128 @@ static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st, return ret; } -static int self_test_sign(const ST_KAT_SIGN *t, - OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) +#ifdef SDF_LIB +static int bitmap_is_inuse(uint64_t *pu64, int32_t index) +{ + + int32_t pos, offset; + uint64_t mask; + + mask = 0x1ull; + + pos = index >> 6; + offset = (63 - (index & 0x3f)); + mask <<= offset; + + return (pu64[pos] & mask) ? 1 : 0; +} + +static int self_test_sign_with_sdf(const ST_KAT_SIGN *t, OSSL_SELF_TEST *st, + OSSL_LIB_CTX *libctx) +{ + int ok = 0; + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_login_arg_t login_arg; + OSSL_ECCrefPrivateKey privkey; + OSSL_ECCrefPublicKey pubkey; + sdfe_bitmap_t bitmap; + sdfe_asym_key_ecc_t asym; + const ST_KAT_PARAM *param; + OSSL_ECCSignature sig; + uint32_t cnt, i; + int index = -1; + const char *typ = OSSL_SELF_TEST_TYPE_KAT_SIGNATURE; + + if (t->sig_expected == NULL) + typ = OSSL_SELF_TEST_TYPE_PCT_SIGNATURE; + + OSSL_SELF_TEST_onbegin(st, typ, t->desc); + + memset(&privkey, 0, sizeof(privkey)); + memset(&pubkey, 0, sizeof(pubkey)); + memset(&asym, 0, sizeof(asym)); + memset(&login_arg, 0, sizeof(login_arg)); + + strcpy((char *)login_arg.name, "admin"); + login_arg.passwd = (uint8_t *)"123123"; + login_arg.passwd_len = 6; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + bitmap.start = 0; + bitmap.cnt = SDFE_BITMAP_U64_MAX_CNT; + if (SDFE_BitmapAsymKey(hSessionHandle, SDFE_ASYM_KEY_AREA_ENC, + SDFE_ASYM_KEY_TYPE_SM2, &bitmap) != OSSL_SDR_OK) + goto end; + + cnt = bitmap.cnt << 6; + for(i = 0; i < cnt; i++){ + if(!bitmap_is_inuse(bitmap.bitmap, i)) { + index = i; + break; + } + } + + if (index < 0) + goto end; + + asym.area = SDFE_ASYM_KEY_AREA_SIGN; + asym.index = index; + asym.type = SDFE_ASYM_KEY_TYPE_SM2; + asym.privkey_bits = 256; + asym.privkey_len = asym.privkey_bits >> 3; + asym.pubkey_bits = 256; + asym.pubkey_len = (asym.pubkey_bits >> 3) << 1; + + for (param = t->key; param->data; param++) { + if (strcmp(param->name, OSSL_PKEY_PARAM_PUB_KEY) == 0) { + pubkey.bits = 256; + memcpy(pubkey.x + sizeof(pubkey.x) - 32, + (unsigned char *)param->data + 1, 32); + memcpy(pubkey.y + sizeof(pubkey.y) - 32, + (unsigned char *)param->data + 1 + 32, 32); + } else if (strcmp(param->name, OSSL_PKEY_PARAM_PRIV_KEY) == 0) { + privkey.bits = 256; + memcpy(privkey.K + sizeof(privkey.K) - param->data_len, param->data, + param->data_len); + } + } + + memcpy(asym.pubkey, &pubkey, sizeof(pubkey)); + memcpy(asym.privkey, &privkey, sizeof(privkey)); + + if (SDFE_ImportECCKey(hSessionHandle, &asym, NULL) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_GetPrivateKeyAccessRight(hSessionHandle, index, NULL, 0) + != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_InternalSign_ECC(hSessionHandle, index, + (unsigned char *)t->dgst, + t->dgst_len, &sig) != OSSL_SDR_OK) + goto end; + + ok = 1; +end: + (void)SDFE_DelECCKey(hSessionHandle, asym.area, index); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); + OSSL_SELF_TEST_onend(st, ok); + return ok; +} +#endif + +static int self_test_sign(const ST_KAT_SIGN *t, OSSL_SELF_TEST *st, + OSSL_LIB_CTX *libctx) { int ret = 0; OSSL_PARAM *params = NULL, *params_sig = NULL; @@ -369,13 +516,13 @@ static int self_test_sign(const ST_KAT_SIGN *t, unsigned char sig[256]; BN_CTX *bnctx = NULL; size_t siglen = sizeof(sig); - static const unsigned char dgst[] = { - 0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, - 0x48, 0xa1, 0xd6, 0x5d, 0xfc, 0x2d, 0x4b, 0x1f, 0xa3, 0xd6, 0x77, 0x28, - 0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 - }; const char *typ = OSSL_SELF_TEST_TYPE_KAT_SIGNATURE; +#ifdef SDF_LIB + if (t->sign) + return self_test_sign_with_sdf(t, st, libctx); +#endif + if (t->sig_expected == NULL) typ = OSSL_SELF_TEST_TYPE_PCT_SIGNATURE; @@ -391,20 +538,20 @@ static int self_test_sign(const ST_KAT_SIGN *t, if (!add_params(bld, t->key, bnctx)) goto err; + params = OSSL_PARAM_BLD_to_param(bld); - /* Create a EVP_PKEY_CTX to load the DSA key into */ - kctx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, ""); + kctx = EVP_PKEY_CTX_new_from_name_provided(libctx, t->algorithm, NULL); + if (kctx == NULL || params == NULL) goto err; + if (EVP_PKEY_fromdata_init(kctx) <= 0 || EVP_PKEY_fromdata(kctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) goto err; - /* Create a EVP_PKEY_CTX to use for the signing operation */ - sctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL); - if (sctx == NULL - || EVP_PKEY_sign_init(sctx) <= 0) + sctx = EVP_PKEY_CTX_new_from_pkey_provided(libctx, pkey, NULL); + if (sctx == NULL) goto err; /* set signature parameters */ @@ -412,47 +559,172 @@ static int self_test_sign(const ST_KAT_SIGN *t, t->mdalgorithm, strlen(t->mdalgorithm) + 1)) goto err; + params_sig = OSSL_PARAM_BLD_to_param(bld); - if (EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0) + if (params_sig == NULL) goto err; - if (EVP_PKEY_sign(sctx, sig, &siglen, dgst, sizeof(dgst)) <= 0 - || EVP_PKEY_verify_init(sctx) <= 0 + if (t->sign) { + if (EVP_PKEY_sign_init(sctx) <= 0) + goto err; + + if (EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0) + goto err; + + if (EVP_PKEY_sign(sctx, sig, &siglen, t->dgst, t->dgst_len) <= 0) + goto err; + + OSSL_SELF_TEST_oncorrupt_byte(st, sig); + + if (t->sig_expected != NULL + && (siglen != t->sig_expected_len + || memcmp(sig, t->sig_expected, t->sig_expected_len) != 0)) + goto err; + } + + if (EVP_PKEY_verify_init(sctx) <= 0 || EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0) goto err; - /* - * Used by RSA, for other key types where the signature changes, we - * can only use the verify. - */ - if (t->sig_expected != NULL - && (siglen != t->sig_expected_len - || memcmp(sig, t->sig_expected, t->sig_expected_len) != 0)) - goto err; + if (!t->sign) { + memcpy(sig, t->sig_expected, t->sig_expected_len); + siglen = t->sig_expected_len; + } OSSL_SELF_TEST_oncorrupt_byte(st, sig); - if (EVP_PKEY_verify(sctx, sig, siglen, dgst, sizeof(dgst)) <= 0) + if (EVP_PKEY_verify(sctx, sig, siglen, t->dgst, t->dgst_len) <= 0) goto err; + ret = 1; err: BN_CTX_free(bnctx); EVP_PKEY_free(pkey); - EVP_PKEY_CTX_free(kctx); EVP_PKEY_CTX_free(sctx); - OSSL_PARAM_free(params); OSSL_PARAM_free(params_sig); OSSL_PARAM_BLD_free(bld); OSSL_SELF_TEST_onend(st, ret); return ret; } -/* - * Test an encrypt or decrypt KAT.. - * - * FIPS 140-2 IG D.9 states that separate KAT tests are needed for encrypt - * and decrypt.. - */ -static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st, +#ifdef SDF_LIB +static int self_test_asym_decrypt_with_sdf(const ST_KAT_ASYM_CIPHER *t, + OSSL_SELF_TEST *st, + OSSL_LIB_CTX *libctx) +{ + int ok = 0; + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_login_arg_t login_arg; + OSSL_ECCrefPrivateKey privkey; + OSSL_ECCrefPublicKey pubkey; + sdfe_bitmap_t bitmap; + sdfe_asym_key_ecc_t asym; + const ST_KAT_PARAM *param; + OSSL_ECCCipher *pECCCipher = NULL; + unsigned char out[256]; + unsigned int outlen = sizeof(out); + uint32_t cnt, i; + int index = -1; + const char *typ = OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER; + + if (t->expected == NULL) + typ = OSSL_SELF_TEST_TYPE_PCT_ASYM_CIPHER; + + OSSL_SELF_TEST_onbegin(st, typ, t->desc); + + memset(&privkey, 0, sizeof(privkey)); + memset(&pubkey, 0, sizeof(pubkey)); + memset(&asym, 0, sizeof(asym)); + memset(&login_arg, 0, sizeof(login_arg)); + + strcpy((char *)login_arg.name, "admin"); + login_arg.passwd = (uint8_t *)"123123"; + login_arg.passwd_len = 6; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + bitmap.start = 0; + bitmap.cnt = SDFE_BITMAP_U64_MAX_CNT; + if (SDFE_BitmapAsymKey(hSessionHandle, SDFE_ASYM_KEY_AREA_ENC, + SDFE_ASYM_KEY_TYPE_SM2, &bitmap) != OSSL_SDR_OK) + goto end; + + cnt = bitmap.cnt << 6; + for(i = 0; i < cnt; i++){ + if(!bitmap_is_inuse(bitmap.bitmap, i)) { + index = i; + break; + } + } + + if (index < 0) + goto end; + + asym.area = SDFE_ASYM_KEY_AREA_ENC; + asym.index = index; + asym.type = SDFE_ASYM_KEY_TYPE_SM2; + asym.privkey_bits = 256; + asym.privkey_len = asym.privkey_bits >> 3; + asym.pubkey_bits = 256; + asym.pubkey_len = (asym.pubkey_bits >> 3) << 1; + + for (param = t->key; param->data; param++) { + if (strcmp(param->name, OSSL_PKEY_PARAM_PUB_KEY) == 0) { + pubkey.bits = 256; + memcpy(pubkey.x + sizeof(pubkey.x) - 32, + (unsigned char *)param->data + 1, 32); + memcpy(pubkey.y + sizeof(pubkey.y) - 32, + (unsigned char *)param->data + 1 + 32, 32); + } else if (strcmp(param->name, OSSL_PKEY_PARAM_PRIV_KEY) == 0) { + privkey.bits = 256; + memcpy(privkey.K + sizeof(privkey.K) - param->data_len, param->data, + param->data_len); + } + } + + memcpy(asym.pubkey, &pubkey, sizeof(pubkey)); + memcpy(asym.privkey, &privkey, sizeof(privkey)); + + if (SDFE_ImportECCKey(hSessionHandle, &asym, NULL) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_GetPrivateKeyAccessRight(hSessionHandle, index, NULL, 0) + != OSSL_SDR_OK) + goto end; + + pECCCipher = TSAPI_SM2Ciphertext_to_ECCCipher(t->in, t->in_len); + + if (TSAPI_SDF_InternalDecrypt_ECC(hSessionHandle, index, pECCCipher, + out, &outlen) != OSSL_SDR_OK) + goto end; + + OSSL_SELF_TEST_oncorrupt_byte(st, out); + + if (t->expected != NULL + && (outlen != t->expected_len + || memcmp(out, t->expected, t->expected_len) != 0)) + goto end; + + ok = 1; +end: + OPENSSL_free(pECCCipher); + (void)SDFE_DelECCKey(hSessionHandle, asym.area, index); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); + OSSL_SELF_TEST_onend(st, ok); + return ok; +} +#endif + +static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, + OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) { int ret = 0; @@ -463,8 +735,17 @@ static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st BN_CTX *bnctx = NULL; unsigned char out[256]; size_t outlen = sizeof(out); + const char *typ = OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER; + +#ifdef SDF_LIB + if (!t->encrypt) + return self_test_asym_decrypt_with_sdf(t, st, libctx); +#endif - OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER, t->desc); + if (t->expected == NULL) + typ = OSSL_SELF_TEST_TYPE_PCT_ASYM_CIPHER; + + OSSL_SELF_TEST_onbegin(st, typ, t->desc); bnctx = BN_CTX_new_ex(libctx); if (bnctx == NULL) @@ -476,7 +757,7 @@ static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st || !add_params(keybld, t->key, bnctx)) goto err; keyparams = OSSL_PARAM_BLD_to_param(keybld); - keyctx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, NULL); + keyctx = EVP_PKEY_CTX_new_from_name_provided(libctx, t->algorithm, NULL); if (keyctx == NULL || keyparams == NULL) goto err; if (EVP_PKEY_fromdata_init(keyctx) <= 0 @@ -484,7 +765,7 @@ static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st goto err; /* Create a EVP_PKEY_CTX to use for the encrypt or decrypt operation */ - encctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL); + encctx = EVP_PKEY_CTX_new_from_pkey_provided(libctx, key, NULL); if (encctx == NULL || (t->encrypt && EVP_PKEY_encrypt_init(encctx) <= 0) || (!t->encrypt && EVP_PKEY_decrypt_init(encctx) <= 0)) @@ -614,17 +895,12 @@ int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) { int ret = 1; - if (!self_test_digests(st, libctx)) - ret = 0; - if (!self_test_ciphers(st, libctx)) - ret = 0; - if (!self_test_signatures(st, libctx)) - ret = 0; - if (!self_test_kdfs(st, libctx)) - ret = 0; - if (!self_test_drbgs(st, libctx)) - ret = 0; - if (!self_test_asym_ciphers(st, libctx)) + if (!self_test_digests(st, libctx) + || !self_test_ciphers(st, libctx) + || !self_test_asym_ciphers(st, libctx) + || !self_test_signatures(st, libctx) + || !self_test_kdfs(st, libctx) + || !self_test_drbgs(st, libctx)) ret = 0; return ret; diff --git a/providers/smtc/self_test_rand.c b/providers/smtc/self_test_rand.c index 01878bcb0..c514b91a2 100644 --- a/providers/smtc/self_test_rand.c +++ b/providers/smtc/self_test_rand.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "internal/nelem.h" #include "self_test_rand.h" @@ -438,7 +439,7 @@ static double psi2(const unsigned char *buf, size_t m, size_t n) pow_len = (size_t)pow(2, m + 1) - 1; - if ((P = OPENSSL_zalloc(pow_len * sizeof(size_t))) == NULL) + if ((P = OPENSSL_zalloc(pow_len * sizeof(unsigned int))) == NULL) return 0.0; for (i = 1; i < pow_len - 1; i++) @@ -1903,19 +1904,36 @@ int rand_self_test_discrete_fourier_transform(const unsigned char *buf, return p_value >= alpha; } -int smtc_randomness_test_delivery(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) +int smtc_rand_delivery_test(OSSL_SELF_TEST *st, int sdf) { int nbit = 1000000; unsigned char buf[nbit / 8]; int fail[15] = {0}; size_t i = 0, j, k; int retry = 1, res = 0; + void *hDeviceHandle = NULL, *hSessionHandle = NULL; - OSSL_SELF_TEST_onbegin(st, "Delivery_Test", "Randomness"); + if (sdf) + OSSL_SELF_TEST_onbegin(st, "Delivery_Test", "Randomness for device"); + else + OSSL_SELF_TEST_onbegin(st, "Delivery_Test", "Randomness"); + + if (sdf) { + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != 0) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != 0) + goto end; + } while (i++ < 50) { - if (RAND_bytes(buf, nbit / 8) != 1) - return 0; + if (sdf) { + if (TSAPI_SDF_GenerateRandom(hSessionHandle, nbit / 8, buf) != 0) + goto end; + } else { + if (RAND_bytes(buf, nbit / 8) != 1) + goto end; + } j = 0; fail[j++] += rand_self_test_frequency(buf, nbit, NULL) ^ 1; @@ -1948,23 +1966,42 @@ int smtc_randomness_test_delivery(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) res = 1; end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); OSSL_SELF_TEST_onend(st, res); return 1; } -int smtc_randomness_test_poweron(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) +int smtc_rand_poweron_test(OSSL_SELF_TEST *st, int sdf) { int nbit = 1000000; unsigned char buf[nbit / 8]; int fail[15] = {0}; size_t i = 0, j, k; int retry = 1, res = 0; + void *hDeviceHandle = NULL, *hSessionHandle = NULL; - OSSL_SELF_TEST_onbegin(st, "Poweron_Test", "Randomness"); + if (sdf) + OSSL_SELF_TEST_onbegin(st, "Poweron_Test", "Randomness for device"); + else + OSSL_SELF_TEST_onbegin(st, "Poweron_Test", "Randomness"); - while(i++ < 20) { - if (RAND_bytes(buf, nbit / 8) != 1) + if (sdf) { + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != 0) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != 0) goto end; + } + + while(i++ < 20) { + if (sdf) { + if (TSAPI_SDF_GenerateRandom(hSessionHandle, nbit / 8, buf) != 0) + goto end; + } else { + if (RAND_bytes(buf, nbit / 8) != 1) + goto end; + } j = 0; fail[j++] += rand_self_test_frequency(buf, nbit, NULL) ^ 1; @@ -1997,25 +2034,37 @@ int smtc_randomness_test_poweron(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) res = 1; end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); OSSL_SELF_TEST_onend(st, res); return 1; } -int smtc_randomness_test_cyclical(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) +int smtc_rand_cyclical_test(OSSL_SELF_TEST *st, int sdf) { int nbit = 20000; unsigned char buf[nbit / 8]; int fail[12] = {0}; size_t i = 0, j, k; int retry = 1, res = 0; + void *hDeviceHandle = NULL, *hSessionHandle = NULL; - OSSL_SELF_TEST_onbegin(st, "Cyclical_Test", "Randomness"); + if (sdf) + OSSL_SELF_TEST_onbegin(st, "Cyclical_Test", "Randomness for device"); + else + OSSL_SELF_TEST_onbegin(st, "Cyclical_Test", "Randomness"); while(i++ < 20) { - if (RAND_bytes(buf, nbit / 8) != 1) - goto end; + if (sdf) { + if (TSAPI_SDF_GenerateRandom(hSessionHandle, nbit / 8, buf) != 0) + goto end; + } else { + if (RAND_bytes(buf, nbit / 8) != 1) + goto end; + } j = 0; + fail[j++] += rand_self_test_frequency(buf, nbit, NULL) ^ 1; fail[j++] += rand_self_test_block_frequency(buf, nbit, 1000, NULL) ^ 1; fail[j++] += rand_self_test_poker(buf, nbit, 8, NULL) ^ 1; @@ -2043,22 +2092,41 @@ int smtc_randomness_test_cyclical(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) res = 1; end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); OSSL_SELF_TEST_onend(st, res); return 1; } -int smtc_randomness_test_single(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) +int smtc_rand_single_test(OSSL_SELF_TEST *st, int sdf) { int nbit = 256; unsigned char buf[nbit / 8]; int retry = 1, res = 0; + void *hDeviceHandle = NULL, *hSessionHandle = NULL; - OSSL_SELF_TEST_onbegin(st, "Single_Test", "Randomness"); + if (sdf) + OSSL_SELF_TEST_onbegin(st, "Single_Test", "Randomness for device"); + else + OSSL_SELF_TEST_onbegin(st, "Single_Test", "Randomness"); - do { - if (RAND_bytes(buf, nbit / 8) != 1) + if (sdf) { + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != 0) goto end; + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != 0) + goto end; + } + + do { + if (sdf) { + if (TSAPI_SDF_GenerateRandom(hSessionHandle, nbit / 8, buf) != 0) + goto end; + } else { + if (RAND_bytes(buf, nbit / 8) != 1) + goto end; + } + if (rand_self_test_poker(buf, nbit, 2, NULL) == 1) break; else @@ -2067,6 +2135,8 @@ int smtc_randomness_test_single(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) res = 1; end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); OSSL_SELF_TEST_onend(st, res); return 1; } diff --git a/providers/smtc/self_test_rand.h b/providers/smtc/self_test_rand.h index 3dd69ff20..c33745a97 100644 --- a/providers/smtc/self_test_rand.h +++ b/providers/smtc/self_test_rand.h @@ -45,7 +45,7 @@ int rand_self_test_maurer_universal_statistical(const unsigned char *buf, int rand_self_test_discrete_fourier_transform(const unsigned char *buf, size_t nbit, double *P); -int smtc_randomness_test_delivery(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx); -int smtc_randomness_test_poweron(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx); -int smtc_randomness_test_cyclical(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx); -int smtc_randomness_test_single(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx); +int smtc_rand_delivery_test(OSSL_SELF_TEST *st, int sdf); +int smtc_rand_poweron_test(OSSL_SELF_TEST *st, int sdf); +int smtc_rand_cyclical_test(OSSL_SELF_TEST *st, int sdf); +int smtc_rand_single_test(OSSL_SELF_TEST *st, int sdf); diff --git a/providers/smtc/smtckey.h.in b/providers/smtc/smtckey.h.in index a6e30ed7a..68dec4216 100644 --- a/providers/smtc/smtckey.h.in +++ b/providers/smtc/smtckey.h.in @@ -1,7 +1,7 @@ /* * {- join("\n * ", @autowarntext) -} * - * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. + * Copyright 2023-2024 The Tongsuo 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 @@ -9,10 +9,7 @@ * https://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt */ -/* - * The SMTC validation HMAC key, usable as an array initializer. - */ -#define SMTC_KEY_ELEMENTS \ - {- join(', ', map { "0x$_" } unpack("(A2)*", $config{SMTCKEY})) -} +#define SMTC_KEY_STRING "{- $config{SMTCPUBKEY} -}" -#define SMTC_KEY_STRING "{- $config{SMTCKEY} -}" +#define SMTC_DEFAULT_PASSWORD_ELEMENTS \ + {- join(', ', map { sprintf '0x%02x', ord($_) } split //, $config{SMTCPASSWD}) -} diff --git a/providers/smtc/smtcprov.c b/providers/smtc/smtcprov.c index db5a92398..8a5993872 100644 --- a/providers/smtc/smtcprov.c +++ b/providers/smtc/smtcprov.c @@ -8,11 +8,15 @@ */ #include +#include #include #include #include +#include +#include #include #include +#include #include "internal/cryptlib.h" #include "prov/implementations.h" #include "prov/bio.h" @@ -24,6 +28,14 @@ #include "self_test.h" #include "internal/core.h" #include "internal/smtc_names.h" +#include "internal/thread_once.h" + + +/* From GM/T 0105-2021 (Sec 6) */ +#define L1_RESEED_INTERVAL (1 << 20) +#define L1_RESEED_TIME_INTERVAL (10 * 60) /* 10 minutes */ +#define L2_RESEED_INTERVAL (1 << 10) +#define L2_RESEED_TIME_INTERVAL (60) /* 1 minute */ /* * Forward declarations to ensure that interface functions are correctly @@ -41,12 +53,6 @@ OSSL_provider_init_fn ossl_smtc_provider_init; # define OSSL_provider_init_int ossl_smtc_provider_init #endif -/* - * Should these function pointers be stored in the provider side provctx? Could - * they ever be different from one init to the next? We assume not for now. - */ -static BIO *bio_err = NULL; - /* Functions provided by the core */ static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL; static OSSL_FUNC_core_get_params_fn *c_get_params; @@ -91,32 +97,40 @@ static const OSSL_PARAM smtc_param_types[] = { static int smtc_get_params_from_core(SMTC_GLOBAL *fgbl) { - OSSL_PARAM core_params[11], *p = core_params; + OSSL_PARAM core_params[14], *p = core_params; *p++ = OSSL_PARAM_construct_utf8_ptr( OSSL_PROV_SMTC_PARAM_MODULE_PATH, (char **)&fgbl->selftest_params.module_filename, sizeof(fgbl->selftest_params.module_filename)); *p++ = OSSL_PARAM_construct_utf8_ptr( - OSSL_PROV_SMTC_PARAM_MODULE_MAC, - (char **)&fgbl->selftest_params.module_checksum_data, - sizeof(fgbl->selftest_params.module_checksum_data)); + OSSL_PROV_SMTC_PARAM_MODULE_SIG, + (char **)&fgbl->selftest_params.module_sig, + sizeof(fgbl->selftest_params.module_sig)); + *p++ = OSSL_PARAM_construct_utf8_ptr( + OSSL_PROV_SMTC_PARAM_AUTH_KEY, + (char **)&fgbl->selftest_params.auth_key, + sizeof(fgbl->selftest_params.auth_key)); *p++ = OSSL_PARAM_construct_utf8_ptr( - OSSL_PROV_SMTC_PARAM_SHOW_SELFTEST, - (char **)&fgbl->selftest_params.show_selftest, - sizeof(fgbl->selftest_params.show_selftest)); + OSSL_PROV_SMTC_PARAM_AUTH_SALT, + (char **)&fgbl->selftest_params.auth_salt, + sizeof(fgbl->selftest_params.auth_salt)); *p++ = OSSL_PARAM_construct_utf8_ptr( - OSSL_PROV_SMTC_PARAM_ADMIN_PASS, - (char **)&fgbl->selftest_params.admin_pass, - sizeof(fgbl->selftest_params.admin_pass)); + OSSL_PROV_SMTC_PARAM_AUTH_KEK, + (char **)&fgbl->selftest_params.kek, + sizeof(fgbl->selftest_params.kek)); *p++ = OSSL_PARAM_construct_utf8_ptr( - OSSL_PROV_SMTC_PARAM_ADMIN_SALT, - (char **)&fgbl->selftest_params.admin_salt, - sizeof(fgbl->selftest_params.admin_salt)); + OSSL_PROV_SMTC_PARAM_ENGINE, + (char **)&fgbl->selftest_params.eng, + sizeof(fgbl->selftest_params.eng)); *p++ = OSSL_PARAM_construct_utf8_ptr( OSSL_PROV_SMTC_PARAM_RNG_POWERON_TEST, (char **)&fgbl->selftest_params.rng_poweron_test, sizeof(fgbl->selftest_params.rng_poweron_test)); + *p++ = OSSL_PARAM_construct_utf8_ptr( + OSSL_PROV_SMTC_PARAM_SYSLOG, + (char **)&fgbl->selftest_params.syslog, + sizeof(fgbl->selftest_params.syslog)); *p++ = OSSL_PARAM_construct_utf8_ptr( OSSL_PROV_SMTC_PARAM_RNG_CONTINUOUS_TEST, (char **)&fgbl->selftest_params.rng_continuous_test, @@ -127,9 +141,9 @@ static int smtc_get_params_from_core(SMTC_GLOBAL *fgbl) sizeof(fgbl->selftest_params.randomness_poweron_test)); #ifndef OPENSSL_NO_SMTC_DEBUG *p++ = OSSL_PARAM_construct_utf8_ptr( - OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_MAC, - (char **)&fgbl->selftest_params.verify_mac, - sizeof(fgbl->selftest_params.verify_mac)); + OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_SIG, + (char **)&fgbl->selftest_params.verify_sig, + sizeof(fgbl->selftest_params.verify_sig)); *p++ = OSSL_PARAM_construct_utf8_ptr( OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_PASS, (char **)&fgbl->selftest_params.verify_pass, @@ -164,7 +178,7 @@ static int smtc_get_params(void *provctx, OSSL_PARAM params[]) if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, TONGSUO_FULL_VERSION_STR)) return 0; p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_STATUS); - if (p != NULL && !OSSL_PARAM_set_int(p, smtc_prov_is_running())) + if (p != NULL && !OSSL_PARAM_set_int(p, ossl_prov_is_running())) return 0; return 1; } @@ -177,12 +191,6 @@ static int self_test_events(const OSSL_PARAM params[], void *arg) const char *phase = NULL, *type = NULL, *desc = NULL; int ret = 0; - if (bio_err == NULL) { - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT); - if (bio_err == NULL) - return 0; - } - p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE); if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) goto err; @@ -198,11 +206,10 @@ static int self_test_events(const OSSL_PARAM params[], void *arg) goto err; type = (const char *)p->data; - if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0) - BIO_printf(bio_err, "%s : (%s) : %s\n", desc, type, phase); - else if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0 - || strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0) - BIO_printf(bio_err, "%s : (%s) : %s\n", desc, type, phase); + if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0 + || strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0 + || strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0) + OSSL_TRACE3(SMTC, "%s : (%s) : %s\n", desc, type, phase); /* * The self test code will internally corrupt the KAT test result if an * error is returned during the corrupt phase. @@ -216,7 +223,7 @@ static int self_test_events(const OSSL_PARAM params[], void *arg) if (self_test_corrupt_type != NULL && strcmp(self_test_corrupt_type, type) != 0) goto end; - BIO_printf(bio_err, "%s : (%s) : %s\n", desc, type, phase); + OSSL_TRACE3(SMTC, "%s : (%s) : %s\n", desc, type, phase); goto err; } end: @@ -227,10 +234,8 @@ static int self_test_events(const OSSL_PARAM params[], void *arg) static void set_self_test_cb(SMTC_GLOBAL *fgbl) { - if (fgbl->selftest_params.show_selftest != NULL - && atoi(fgbl->selftest_params.show_selftest) != 0) - OSSL_SELF_TEST_set_callback(fgbl->selftest_params.libctx, - self_test_events, NULL); + OSSL_SELF_TEST_set_callback(fgbl->selftest_params.libctx, self_test_events, + NULL); if (c_stcbfn != NULL) { c_stcbfn((OPENSSL_CORE_CTX *)fgbl->selftest_params.libctx, @@ -244,14 +249,70 @@ static void set_self_test_cb(SMTC_GLOBAL *fgbl) static int smtc_self_test(void *provctx) { - SMTC_GLOBAL *fgbl = ossl_lib_ctx_get_data(ossl_prov_ctx_get0_libctx(provctx), - OSSL_LIB_CTX_SMTC_PROV_INDEX, - &smtc_prov_ossl_ctx_method); + SMTC_GLOBAL *fgbl = + ossl_lib_ctx_get_data(ossl_prov_ctx_get0_libctx(provctx), + OSSL_LIB_CTX_SMTC_PROV_INDEX, + &smtc_prov_ossl_ctx_method); set_self_test_cb(fgbl); return SELF_TEST_post(&fgbl->selftest_params, 1) ? 1 : 0; } +static int smtc_status(void *provctx) +{ + return ossl_prov_is_running(); +} + +static int smtc_reset(void *provctx) +{ + int ok = 0, i; + const char *conf_file = OPENSSL_info(OPENSSL_INFO_SMTC_MODULE_CONF); + CONF *conf = NULL; + STACK_OF(CONF_VALUE) *sect = NULL; + CONF_VALUE *cv = NULL; + const char *sec_name = "smtc_sect"; + BIO *out = NULL; + long eline; + + conf = NCONF_new(NCONF_default()); + if (conf == NULL) + goto end; + + if (NCONF_load(conf, conf_file, &eline) <= 0) + goto end; + + out = BIO_new_file(conf_file, "w"); + if (out == NULL) + goto end; + + if (BIO_printf(out, "[%s]\n", sec_name) <= 0 + || BIO_printf(out, "activate = 1\n") <= 0) + goto end; + + sect = NCONF_get_section(conf, sec_name); + + for (i = 0; i < sk_CONF_VALUE_num(sect); i++) { + cv = sk_CONF_VALUE_value(sect, i); + + if (strcmp(cv->name, OSSL_PROV_SMTC_PARAM_MODULE_PATH) == 0 + || strcmp(cv->name, OSSL_PROV_SMTC_PARAM_MODULE_SIG) == 0 + || strcmp(cv->name, OSSL_PROV_SMTC_PARAM_AUTH_KEK) == 0 + || strcmp(cv->name, OSSL_PROV_SMTC_PARAM_ENGINE) == 0 + || strcmp(cv->name, OSSL_PROV_SMTC_PARAM_SYSLOG) == 0 + || strcmp(cv->name, OSSL_PROV_SMTC_PARAM_RANDOMNESS_POWERON_TEST) == 0) + if (BIO_printf(out, "%s = %s\n", cv->name, cv->value) <= 0) + goto end; + } + + ok = 1; + OSSL_syslog(LOG_NOTICE, "[SMTC] Reset module\n"); +end: + NCONF_free(conf); + BIO_free(out); + + return ok; +} + /* * For the algorithm names, we use the following formula for our primary * names: @@ -286,8 +347,13 @@ static const OSSL_ALGORITHM smtc_digests[] = { static const OSSL_ALGORITHM_CAPABLE smtc_ciphers[] = { #ifndef OPENSSL_NO_SM4 + ALG(PROV_NAMES_SM4_ECB, ossl_sm4128ecb_functions), ALG(PROV_NAMES_SM4_CBC, ossl_sm4128cbc_functions), + ALG(PROV_NAMES_SM4_CFB, ossl_sm4128cfb128_functions), + ALG(PROV_NAMES_SM4_OFB, ossl_sm4128ofb128_functions), + ALG(PROV_NAMES_SM4_CTR, ossl_sm4128ctr_functions), ALG(PROV_NAMES_SM4_GCM, ossl_sm4128gcm_functions), + ALG(PROV_NAMES_SM4_CCM, ossl_sm4128ccm_functions), #endif /* OPENSSL_NO_SM4 */ {{NULL, NULL, NULL}, NULL}}; @@ -300,6 +366,7 @@ static const OSSL_ALGORITHM smtc_macs[] = { static const OSSL_ALGORITHM smtc_kdfs[] = { { PROV_NAMES_TLS1_PRF, "provider=smtc", ossl_kdf_tls1_prf_functions }, + { PROV_NAMES_PBKDF2, "provider=smtc", ossl_kdf_pbkdf2_functions }, /* used by SM2 encryption and decryption */ { PROV_NAMES_X963KDF, "provider=smtc", ossl_kdf_x963_kdf_functions }, { NULL, NULL, NULL } @@ -307,6 +374,7 @@ static const OSSL_ALGORITHM smtc_kdfs[] = { static const OSSL_ALGORITHM smtc_rands[] = { { PROV_NAMES_HASH_DRBG, "provider=smtc", ossl_drbg_hash_functions }, + { PROV_NAMES_SEED_SRC, "provider=smtc", ossl_seed_src_functions }, { PROV_NAMES_TEST_RAND, "provider=smtc", ossl_test_rng_functions }, { NULL, NULL, NULL } }; @@ -349,11 +417,18 @@ static const OSSL_ALGORITHM smtc_keymgmt[] = { PROV_DESCS_SM2 }, #endif /* TLCP create HMAC, such as ECC-SM2-SM4-CBC-SM3 */ - { PROV_NAMES_HMAC, "provider=default", ossl_mac_legacy_keymgmt_functions, + { PROV_NAMES_HMAC, "provider=smtc", ossl_mac_legacy_keymgmt_functions, PROV_DESCS_HMAC_SIGN }, { NULL, NULL, NULL } }; +static const OSSL_ALGORITHM smtc_encoder[] = { +#define ENCODER_PROVIDER "smtc" +#include "../encoders.inc" + { NULL, NULL, NULL } +#undef ENCODER_PROVIDER +}; + static const OSSL_ALGORITHM smtc_decoder[] = { #define DECODER_PROVIDER "smtc" #include "../decoders.inc" @@ -361,6 +436,15 @@ static const OSSL_ALGORITHM smtc_decoder[] = { #undef DECODER_PROVIDER }; +static const OSSL_ALGORITHM smtc_store[] = { +#define STORE(name, _dummy, func_table) \ + { name, "provider=smtc", (func_table) }, + +#include "../stores.inc" + { NULL, NULL, NULL } +#undef STORE +}; + static const OSSL_ALGORITHM *smtc_query(void *provctx, int operation_id, int *no_cache) { @@ -390,35 +474,113 @@ static const OSSL_ALGORITHM *smtc_query(void *provctx, int operation_id, return smtc_asym_cipher; case OSSL_OP_KEM: return smtc_asym_kem; + case OSSL_OP_ENCODER: + return smtc_encoder; case OSSL_OP_DECODER: return smtc_decoder; + case OSSL_OP_STORE: + return smtc_store; } return NULL; } +static void smtc_teardown(void *provctx) +{ + BIO_meth_free(ossl_prov_ctx_get0_core_bio_method(provctx)); + OSSL_LIB_CTX_free(PROV_LIBCTX_OF(provctx)); + ossl_prov_ctx_free(provctx); +} + static void smtc_intern_teardown(void *provctx) { - BIO_free(bio_err); + BIO_meth_free(ossl_prov_ctx_get0_core_bio_method(provctx)); /* * We know that the library context is the same as for the outer provider, * so no need to destroy it here. */ - BIO_meth_free(ossl_prov_ctx_get0_core_bio_method(provctx)); ossl_prov_ctx_free(provctx); } /* Functions we provide to the core */ static const OSSL_DISPATCH smtc_dispatch_table[] = { - { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))smtc_intern_teardown }, + { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))smtc_teardown }, { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))smtc_gettable_params }, { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))smtc_get_params }, { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))smtc_query }, { OSSL_FUNC_PROVIDER_GET_CAPABILITIES, (void (*)(void))ossl_prov_get_capabilities }, { OSSL_FUNC_PROVIDER_SELF_TEST, (void (*)(void))smtc_self_test }, + { OSSL_FUNC_PROVIDER_STATUS, (void (*)(void))smtc_status }, + { OSSL_FUNC_PROVIDER_RESET, (void (*)(void))smtc_reset }, { 0, NULL } }; +/* Functions we provide to ourself */ +static const OSSL_DISPATCH intern_dispatch_table[] = { + { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))smtc_intern_teardown }, + { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))smtc_query }, + { 0, NULL } +}; + +/* + * The internal init function used when the SMTC module uses EVP to call + * another algorithm also in the SMTC module. This is a recursive call that has + * been made from within the SMTC module itself. To make this work, we populate + * the provider context of this inner instance with the same library context + * that was used in the EVP call that initiated this recursive call. + */ +OSSL_provider_init_fn ossl_smtc_intern_provider_init; +int ossl_smtc_intern_provider_init(const OSSL_CORE_HANDLE *handle, + const OSSL_DISPATCH *in, + const OSSL_DISPATCH **out, + void **provctx) +{ + OSSL_FUNC_core_get_libctx_fn *c_internal_get_libctx = NULL; + BIO_METHOD *corebiometh = NULL; + OSSL_LIB_CTX *libctx = NULL; + + for (; in->function_id != 0; in++) { + switch (in->function_id) { + case OSSL_FUNC_CORE_GET_LIBCTX: + c_internal_get_libctx = OSSL_FUNC_core_get_libctx(in); + break; + default: + break; + } + } + + if (c_internal_get_libctx == NULL) + return 0; + + if ((*provctx = ossl_prov_ctx_new()) == NULL) + return 0; + + if ((corebiometh = ossl_bio_prov_init_bio_method()) == NULL) + goto err; + + /* + * Using the parent library context only works because we are a built-in + * internal provider. This is not something that most providers would be + * able to do. + */ + libctx = (OSSL_LIB_CTX *)c_internal_get_libctx(handle); + + ossl_prov_ctx_set0_libctx(*provctx, libctx); + ossl_prov_ctx_set0_handle(*provctx, handle); + ossl_prov_ctx_set0_core_bio_method(*provctx, corebiometh); + + *out = intern_dispatch_table; + return 1; + +err: + BIO_meth_free(corebiometh); + smtc_intern_teardown(*provctx); + *provctx = NULL; + OSSL_LIB_CTX_free(libctx); + return 0; +} + +OSSL_provider_init_fn OSSL_provider_init_int; int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, const OSSL_DISPATCH *in, const OSSL_DISPATCH **out, @@ -426,10 +588,31 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, { int ret; SMTC_GLOBAL *fgbl; - BIO_METHOD *corebiometh; + OSSL_PROVIDER *intern_prov = NULL; + BIO_METHOD *corebiometh = NULL; OSSL_LIB_CTX *libctx = NULL; OSSL_FUNC_core_get_libctx_fn *c_internal_get_libctx = NULL; SELF_TEST_POST_PARAMS selftest_params; + EVP_RAND_CTX *pub_drbg, *pri_drbg; + unsigned int reseed_interval = L2_RESEED_INTERVAL; + time_t reseed_time_interval = L2_RESEED_TIME_INTERVAL; + OSSL_PARAM params[3]; + struct utmpx *cur; + + setutxent(); + while ((cur = getutxent()) != NULL) { + /* + * Root users are prohibited from logging in to prevent malicious + * tampering. + */ + if (strcmp(cur->ut_user, "root") == 0) { + OSSL_TRACE(SMTC, "root user detected, init failed\n"); + endutxent(); + return 0; + } + } + + endutxent(); memset(&selftest_params, 0, sizeof(selftest_params)); @@ -461,17 +644,21 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, libctx = (OSSL_LIB_CTX *)c_internal_get_libctx(handle); + if (!OSSL_PROVIDER_add_builtin(libctx, "intern-smtc", + ossl_smtc_intern_provider_init) + || (intern_prov = OSSL_PROVIDER_load(libctx, "intern-smtc")) == NULL) + goto err; + /* Use SM3-DRBG */ ret = RAND_set_DRBG_type(libctx, "HASH-DRBG", NULL, NULL, "SM3"); if (ret != 1) - return 0; + goto err; - if ((*provctx = ossl_prov_ctx_new()) == NULL - || (corebiometh = ossl_bio_prov_init_bio_method()) == NULL) { - ossl_prov_ctx_free(*provctx); - *provctx = NULL; - return 0; - } + if ((*provctx = ossl_prov_ctx_new()) == NULL) + goto err; + + if ((corebiometh = ossl_bio_prov_init_bio_method()) == NULL) + goto err; if ((fgbl = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_SMTC_PROV_INDEX, &smtc_prov_ossl_ctx_method)) == NULL) @@ -494,15 +681,50 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, goto err; } + ossl_prov_cache_exported_algorithms(smtc_ciphers, exported_ciphers); + + if (fgbl->selftest_params.syslog && atoi(fgbl->selftest_params.syslog) != 0) + OSSL_enable_syslog(); + + OSSL_syslog(LOG_INFO, "[SMTC] SMTC module init\n"); + + if (!SELF_TEST_post(&fgbl->selftest_params, 0)) { + OSSL_TRACE(SMTC, "SELF_TEST_post failed\n"); + ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_POST_FAILURE); + goto err; + } + + pub_drbg = RAND_get0_public(libctx); + if (pub_drbg == NULL) + goto err; + + pri_drbg = RAND_get0_private(libctx); + if (pri_drbg == NULL) + goto err; + + params[0] = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS, + &reseed_interval); + params[1] = OSSL_PARAM_construct_time_t( + OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL, + &reseed_time_interval); + params[2] = OSSL_PARAM_construct_end(); + + if (!EVP_RAND_CTX_set_params(pub_drbg, params) + || !EVP_RAND_CTX_set_params(pri_drbg, params)) + goto err; + ossl_prov_ctx_set0_libctx(*provctx, libctx); ossl_prov_ctx_set0_handle(*provctx, handle); ossl_prov_ctx_set0_core_bio_method(*provctx, corebiometh); + OSSL_PROVIDER_unload(intern_prov); *out = smtc_dispatch_table; - ossl_prov_cache_exported_algorithms(smtc_ciphers, exported_ciphers); + return 1; err: - smtc_intern_teardown(*provctx); + OSSL_PROVIDER_unload(intern_prov); + BIO_meth_free(corebiometh); + smtc_teardown(*provctx); *provctx = NULL; OSSL_LIB_CTX_free(libctx); return 0; diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c index 2265ec287..f08e0f857 100644 --- a/ssl/ssl_rsa.c +++ b/ssl/ssl_rsa.c @@ -16,6 +16,9 @@ #include #include #include +#ifdef SMTC_MODULE +# include +#endif static int ssl_set_cert(CERT *c, X509 *x509); static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); @@ -1278,8 +1281,125 @@ static int ssl_set_cert_idx(CERT *c, X509 *x, int i) return 1; } +# ifdef SMTC_MODULE +static int sm2_enc_pairwise_test(const X509 *x, EVP_PKEY *k, + OSSL_CALLBACK *cb, void *cbarg) +{ + int ret = 0; + unsigned char in[16] = {0}; + unsigned char in2[16]; + size_t inlen2 = sizeof(in2); + unsigned char out[256]; + size_t outlen = sizeof(out); + EVP_PKEY *xk; + EVP_PKEY_CTX *ectx = NULL, *dctx = NULL; + OSSL_SELF_TEST *st = NULL; + + xk = X509_get0_pubkey(x); + if (xk == NULL) { + ERR_raise(ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY); + return 0; + } + + st = OSSL_SELF_TEST_new(cb, cbarg); + if (st == NULL) + return 0; + + OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT, + OSSL_SELF_TEST_DESC_SM2_ENC_PAIRWISE); + + ectx = EVP_PKEY_CTX_new_from_pkey(NULL, xk, NULL); + if (ectx == NULL) + goto err; + + if (EVP_PKEY_encrypt_init(ectx) <= 0 + || EVP_PKEY_encrypt(ectx, out, &outlen, in, sizeof(in)) <= 0) + goto err; + + dctx = EVP_PKEY_CTX_new_from_pkey(NULL, k, NULL); + if (dctx == NULL) + goto err; + + if (EVP_PKEY_decrypt_init(dctx) <= 0) + goto err; + + if (EVP_PKEY_decrypt(dctx, in2, &inlen2, out, outlen) <= 0) + goto err; + + OSSL_SELF_TEST_oncorrupt_byte(st, in2); + + if (inlen2 != sizeof(in) || memcmp(in, in2, sizeof(in)) != 0) + goto err; + + ret = 1; +err: + OSSL_SELF_TEST_onend(st, ret); + OSSL_SELF_TEST_free(st); + EVP_PKEY_CTX_free(ectx); + EVP_PKEY_CTX_free(dctx); + return ret; +} + +static int sm2_sign_pairwise_test(const X509 *x, EVP_PKEY *k, + OSSL_CALLBACK *cb, void *cbarg) +{ + int ret = 0; + unsigned char dgst[32] = {0}; + unsigned char sig[256]; + size_t siglen = sizeof(sig); + EVP_PKEY *xk; + EVP_PKEY_CTX *sctx = NULL, *vctx = NULL; + OSSL_SELF_TEST *st = NULL; + + xk = X509_get0_pubkey(x); + if (xk == NULL) { + ERR_raise(ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY); + return 0; + } + + st = OSSL_SELF_TEST_new(cb, cbarg); + if (st == NULL) + return 0; + + OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT, + OSSL_SELF_TEST_DESC_SM2_SIGN_PAIRWISE); + + sctx = EVP_PKEY_CTX_new_from_pkey(NULL, k, NULL); + if (sctx == NULL) + goto err; + + if (EVP_PKEY_sign_init(sctx) <= 0 + || EVP_PKEY_sign(sctx, sig, &siglen, dgst, sizeof(dgst)) <= 0) + goto err; + + vctx = EVP_PKEY_CTX_new_from_pkey(NULL, xk, NULL); + if (vctx == NULL) + goto err; + + if (EVP_PKEY_verify_init(vctx) <= 0) + goto err; + + OSSL_SELF_TEST_oncorrupt_byte(st, dgst); + + if (EVP_PKEY_verify(vctx, sig, siglen, dgst, sizeof(dgst)) <= 0) + goto err; + + ret = 1; +err: + OSSL_SELF_TEST_onend(st, ret); + OSSL_SELF_TEST_free(st); + EVP_PKEY_CTX_free(sctx); + EVP_PKEY_CTX_free(vctx); + return ret; +} +# endif + static int ssl_set_pkey_idx(CERT *c, EVP_PKEY *pkey, int i) { +#ifdef SMTC_MODULE + OSSL_CALLBACK *cb = NULL; + void *cbarg = NULL; +#endif if (c->pkeys[i].x509 != NULL) { EVP_PKEY *pktmp; pktmp = X509_get0_pubkey(c->pkeys[i].x509); @@ -1299,6 +1419,25 @@ static int ssl_set_pkey_idx(CERT *c, EVP_PKEY *pkey, int i) c->pkeys[i].x509 = NULL; return 0; } +#ifdef SMTC_MODULE + if (i == SSL_PKEY_SM2_SIGN || i == SSL_PKEY_SM2_ENC) { + OSSL_SELF_TEST_get_callback(NULL, &cb, &cbarg); + + if (i == SSL_PKEY_SM2_SIGN + && !sm2_sign_pairwise_test(c->pkeys[i].x509, pkey, cb, cbarg)) { + X509_free(c->pkeys[i].x509); + c->pkeys[i].x509 = NULL; + return 0; + } + + if (i == SSL_PKEY_SM2_ENC + && !sm2_enc_pairwise_test(c->pkeys[i].x509, pkey, cb, cbarg)) { + X509_free(c->pkeys[i].x509); + c->pkeys[i].x509 = NULL; + return 0; + } + } +#endif } EVP_PKEY_free(c->pkeys[i].privatekey); diff --git a/ssl/statem_ntls/ntls_statem_srvr.c b/ssl/statem_ntls/ntls_statem_srvr.c index ed274c45e..b91d2528d 100644 --- a/ssl/statem_ntls/ntls_statem_srvr.c +++ b/ssl/statem_ntls/ntls_statem_srvr.c @@ -1584,7 +1584,7 @@ int tls_construct_server_key_exchange_ntls(SSL *s, WPACKET *pkt) { unsigned char *encodedPoint = NULL; size_t encodedlen = 0; - int curve_id = 0; + uint16_t curve_id = 0; const SIGALG_LOOKUP *lu = s->s3.tmp.sigalg; unsigned long type; EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 67b45905d..93f60b28c 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -552,6 +552,13 @@ int tls1_setup_key_block(SSL *s) goto err; } +#if defined(SMTC_MODULE) && !defined(OPENSSL_NO_NTLS) + if (SSL_IS_NTLS(s) && (s->options & SSL_OP_NO_TICKET) + && (s->ctx->session_cache_mode == SSL_SESS_CACHE_OFF)) { + OPENSSL_cleanse(s->session->master_key, s->session->master_key_length); + } +#endif + OSSL_TRACE_BEGIN(TLS) { BIO_printf(trc_out, "key block\n"); BIO_dump_indent(trc_out, p, num, 4); diff --git a/test/build.info b/test/build.info index 6d53ee12f..a03023f4a 100644 --- a/test/build.info +++ b/test/build.info @@ -59,7 +59,7 @@ IF[{- !$disabled{tests} -}] context_internal_test aesgcmtest params_test evp_pkey_dparams_test \ keymgmt_internal_test hexstr_test provider_status_test defltfips_test \ bio_readbuffer_test user_property_test pkcs7_test upcallstest \ - provfetchtest prov_config_test rand_test babasslapitest + provfetchtest prov_config_test rand_test babasslapitest tsapi_test IF[{- !$disabled{'deprecated-3.0'} -}] PROGRAMS{noinst}=enginetest @@ -580,6 +580,10 @@ IF[{- !$disabled{tests} -}] INCLUDE[cmp_client_test]=.. ../include ../apps/include DEPEND[cmp_client_test]=../libcrypto.a libtestutil.a + SOURCE[tsapi_test]=tsapi_test.c + INCLUDE[tsapi_test]=.. ../include ../apps/include + DEPEND[tsapi_test]=../libcrypto.a libtestutil.a + # Internal test programs. These are essentially a collection of internal # test routines. Some of them need to reach internal symbols that aren't # available through the shared library (at least on Linux and Windows diff --git a/test/ssl-tests/31-ntls.cnf b/test/ntls-tests/31-ntls.cnf similarity index 100% rename from test/ssl-tests/31-ntls.cnf rename to test/ntls-tests/31-ntls.cnf diff --git a/test/ssl-tests/31-ntls.cnf.in b/test/ntls-tests/31-ntls.cnf.in similarity index 100% rename from test/ssl-tests/31-ntls.cnf.in rename to test/ntls-tests/31-ntls.cnf.in diff --git a/test/ssl-tests/32-ntls-force-ntls.cnf b/test/ntls-tests/32-ntls-force-ntls.cnf similarity index 100% rename from test/ssl-tests/32-ntls-force-ntls.cnf rename to test/ntls-tests/32-ntls-force-ntls.cnf diff --git a/test/ssl-tests/32-ntls-force-ntls.cnf.in b/test/ntls-tests/32-ntls-force-ntls.cnf.in similarity index 100% rename from test/ssl-tests/32-ntls-force-ntls.cnf.in rename to test/ntls-tests/32-ntls-force-ntls.cnf.in diff --git a/test/ssl-tests/39-ntls-sni-ticket.cnf b/test/ntls-tests/39-ntls-sni-ticket.cnf similarity index 100% rename from test/ssl-tests/39-ntls-sni-ticket.cnf rename to test/ntls-tests/39-ntls-sni-ticket.cnf diff --git a/test/ssl-tests/39-ntls-sni-ticket.cnf.in b/test/ntls-tests/39-ntls-sni-ticket.cnf.in similarity index 100% rename from test/ssl-tests/39-ntls-sni-ticket.cnf.in rename to test/ntls-tests/39-ntls-sni-ticket.cnf.in diff --git a/test/ssl-tests/40-ntls_client_auth.cnf b/test/ntls-tests/40-ntls_client_auth.cnf similarity index 100% rename from test/ssl-tests/40-ntls_client_auth.cnf rename to test/ntls-tests/40-ntls_client_auth.cnf diff --git a/test/ssl-tests/40-ntls_client_auth.cnf.in b/test/ntls-tests/40-ntls_client_auth.cnf.in similarity index 100% rename from test/ssl-tests/40-ntls_client_auth.cnf.in rename to test/ntls-tests/40-ntls_client_auth.cnf.in diff --git a/test/ssl-tests/41-ntls-alpn.cnf b/test/ntls-tests/41-ntls-alpn.cnf similarity index 100% rename from test/ssl-tests/41-ntls-alpn.cnf rename to test/ntls-tests/41-ntls-alpn.cnf diff --git a/test/ssl-tests/41-ntls-alpn.cnf.in b/test/ntls-tests/41-ntls-alpn.cnf.in similarity index 100% rename from test/ssl-tests/41-ntls-alpn.cnf.in rename to test/ntls-tests/41-ntls-alpn.cnf.in diff --git a/test/recipes/00-prep_smtc_cnf.t b/test/recipes/00-prep_smtc_cnf.t index d32104921..c431ae70d 100644 --- a/test/recipes/00-prep_smtc_cnf.t +++ b/test/recipes/00-prep_smtc_cnf.t @@ -29,8 +29,9 @@ my $smtcconf = bldtop_file('test', 'smtcmodule.cnf'); plan tests => 1; +$ENV{OPENSSL_CONF} = ""; + # Create the smtc conf file -ok(run(app(['openssl', 'mod', - '-module', $bin, '-provider_name', 'smtc', '-no_pass', - '-section_name', 'smtc_sect', '-out', $smtcconf])), - "smtc install"); +ok(run(app(['openssl', 'mod', '-install', '-no_verify', '-no_auth', + '-no_rand_poweron_test', '-module', $bin, '-out', $smtcconf])), + "smtc install"); diff --git a/test/recipes/10-test_mod_sm2.t b/test/recipes/10-test_mod_sm2.t index d070467cf..9d0d260e3 100644 --- a/test/recipes/10-test_mod_sm2.t +++ b/test/recipes/10-test_mod_sm2.t @@ -7,10 +7,16 @@ # https://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt use strict; -use OpenSSL::Test; # get 'plan' +use OpenSSL::Test qw/:DEFAULT srctop_file/; use OpenSSL::Test::Simple; use OpenSSL::Test::Utils; setup("test_mod_sm2"); +my $no_smtc = disabled('smtc') || disabled('smtc-debug'); + +if (!$no_smtc) { + $ENV{OPENSSL_CONF} = srctop_file("test", "smtc.cnf"); +} + simple_test("test_mod_sm2", "sm2_mod_test", "sm2"); diff --git a/test/recipes/20-test_cli_smtc.t b/test/recipes/20-test_cli_smtc.t index 6996c3084..38d2e8bec 100644 --- a/test/recipes/20-test_cli_smtc.t +++ b/test/recipes/20-test_cli_smtc.t @@ -26,8 +26,7 @@ plan skip_all => "Test only supported in a smtc build" if disabled("smtc") || disabled("smtc-debug"); plan tests => 9; -my $defaultconf = srctop_file("test", "default.cnf"); -my $smtcconf = srctop_file("test", "smtc-and-base.cnf"); +my $smtcconf = srctop_file("test", "smtc.cnf"); my $tbs_data = abs_path(bldtop_file('apps', 'openssl' . platform->binext())); my $bogus_data = $smtcconf; @@ -64,16 +63,13 @@ sub pubfrompriv { } -my $tsignverify_count = 8; +my $tsignverify_count = 2; sub tsignverify { my $prefix = shift; my $smtc_key = shift; my $smtc_pub_key = shift; - my $nonsmtc_key = shift; - my $nonsmtc_pub_key = shift; my $md = shift; my $smtc_sigfile = $prefix.'.smtc.sig'; - my $nonsmtc_sigfile = $prefix.'.nonsmtc.sig'; my $sigfile = ''; my $testtext = ''; @@ -95,65 +91,6 @@ sub tsignverify { '-signature', $sigfile, $tbs_data])), $testtext); - - $testtext = $prefix.': '. - 'Verify a valid signature against the wrong data with a SMTC key'. - ' (should fail)'; - ok(!run(app(['openssl', 'dgst', $md, - '-verify', $smtc_pub_key, - '-signature', $sigfile, - $bogus_data])), - $testtext); - - $ENV{OPENSSL_CONF} = $defaultconf; - - $sigfile = $nonsmtc_sigfile; - $testtext = $prefix.': '. - 'Sign something with a non-SMTC key'. - ' with the default provider'; - ok(run(app(['openssl', 'dgst', $md, - '-sign', $nonsmtc_key, - '-out', $sigfile, - $tbs_data])), - $testtext); - - $testtext = $prefix.': '. - 'Verify something with a non-SMTC key'. - ' with the default provider'; - ok(run(app(['openssl', 'dgst', $md, - '-verify', $nonsmtc_pub_key, - '-signature', $sigfile, - $tbs_data])), - $testtext); - - $ENV{OPENSSL_CONF} = $smtcconf; - - $testtext = $prefix.': '. - 'Sign something with a non-SMTC key'. - ' (should fail)'; - ok(!run(app(['openssl', 'dgst', $md, - '-sign', $nonsmtc_key, - '-out', $prefix.'.nonsmtc.fail.sig', - $tbs_data])), - $testtext); - - $testtext = $prefix.': '. - 'Verify something with a non-SMTC key'. - ' (should fail)'; - ok(!run(app(['openssl', 'dgst', $md, - '-verify', $nonsmtc_pub_key, - '-signature', $sigfile, - $tbs_data])), - $testtext); - - $testtext = $prefix.': '. - 'Verify a valid signature against the wrong data with a non-SMTC key'. - ' (should fail)'; - ok(!run(app(['openssl', 'dgst', $md, - '-verify', $nonsmtc_pub_key, - '-signature', $sigfile, - $bogus_data])), - $testtext); } SKIP : { @@ -164,24 +101,10 @@ SKIP : { my $testtext_prefix = 'SM2'; my $smtc_key = $testtext_prefix.'.smtc.priv.pem'; my $smtc_pub_key = $testtext_prefix.'.smtc.pub.pem'; - my $a_nonsmtc_curve = 'brainpoolP256r1'; - my $nonsmtc_key = $testtext_prefix.'.nonsmtc.priv.pem'; - my $nonsmtc_pub_key = $testtext_prefix.'.nonsmtc.pub.pem'; my $testtext = ''; my $curvename = ''; - plan tests => 5 + $tsignverify_count; - - $ENV{OPENSSL_CONF} = $defaultconf; - $curvename = $a_nonsmtc_curve; - $testtext = $testtext_prefix.': '. - 'Generate a key with a non-SMTC algorithm with the default provider'; - ok(run(app(['openssl', 'genpkey', '-algorithm', 'EC', - '-pkeyopt', 'ec_paramgen_curve:'.$curvename, - '-out', $nonsmtc_key])), - $testtext); - - pubfrompriv($testtext_prefix, $nonsmtc_key, $nonsmtc_pub_key, "non-SMTC"); + plan tests => 1 + 1 + $tsignverify_count; $ENV{OPENSSL_CONF} = $smtcconf; @@ -193,16 +116,6 @@ SKIP : { pubfrompriv($testtext_prefix, $smtc_key, $smtc_pub_key, "SMTC"); - $curvename = $a_nonsmtc_curve; - $testtext = $testtext_prefix.': '. - 'Generate a key with a non-SMTC algorithm'. - ' (should fail)'; - ok(!run(app(['openssl', 'genpkey', '-algorithm', 'EC', - '-pkeyopt', 'ec_paramgen_curve:'.$curvename, - '-out', $testtext_prefix.'.'.$curvename.'.priv.pem'])), - $testtext); - - tsignverify($testtext_prefix, $smtc_key, $smtc_pub_key, $nonsmtc_key, - $nonsmtc_pub_key, '-sm3'); + tsignverify($testtext_prefix, $smtc_key, $smtc_pub_key, '-sm3'); }; } diff --git a/test/recipes/20-test_mod.t b/test/recipes/20-test_mod.t index 92876338a..58148446e 100644 --- a/test/recipes/20-test_mod.t +++ b/test/recipes/20-test_mod.t @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. +# Copyright 2023-2024 The Tongsuo 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 @@ -9,16 +9,16 @@ use strict; use warnings; -use OpenSSL::Test; -use OpenSSL::Test::Utils; use OpenSSL::Test qw/:DEFAULT srctop_file/; +use OpenSSL::Test::Utils; use Cwd qw(abs_path); setup("test_mod"); plan skip_all => "Test only supported in a smtc build" if disabled("smtc"); -plan tests => 1; +plan tests => 2; -$ENV{OPENSSL_CONF} = abs_path(srctop_file("test", "smtc-and-base.cnf")); +$ENV{OPENSSL_CONF} = srctop_file("test", "smtc.cnf"); ok(run(app(['openssl', 'mod', '-test'])), "mod self test"); +ok(run(app(['openssl', 'mod', '-status'])), "mod show status"); diff --git a/test/recipes/70-test_ntlssni.t b/test/recipes/70-test_ntlssni.t index 743c43d18..f961712d0 100644 --- a/test/recipes/70-test_ntlssni.t +++ b/test/recipes/70-test_ntlssni.t @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. +# Copyright 2023-2024 The Tongsuo 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 @@ -29,6 +29,10 @@ plan skip_all => "$test_name needs SM2, SM3 and SM4 enabled" $ENV{OPENSSL_ia32cap} = '~0x200000200000000'; +my $no_smtc = disabled('smtc') || disabled('smtc-debug'); +if (!$no_smtc) { + $ENV{OPENSSL_CONF} = srctop_file("test", "smtc.cnf"); +} my $proxy = TLSProxy::Proxy->new( undef, diff --git a/test/recipes/80-test_ntls.t b/test/recipes/80-test_ntls.t new file mode 100644 index 000000000..fbb398ec3 --- /dev/null +++ b/test/recipes/80-test_ntls.t @@ -0,0 +1,129 @@ +#! /usr/bin/env perl +# Copyright 2015-2022 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 + + +use strict; +use warnings; + +use File::Basename; +use File::Compare qw/compare_text/; +use File::Spec::Functions qw/devnull catdir/; +use OpenSSL::Glob; +use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file bldtop_dir result_dir/; +use OpenSSL::Test::Utils qw/disabled alldisabled available_protocols/; + +BEGIN { +setup("test_ntls"); +} + +plan skip_all => "NTLS is not supported by this OpenSSL build" + if disabled("ntls"); + +use lib srctop_dir('Configurations'); +use lib bldtop_dir('.'); + +my $no_smtc = disabled('smtc') || disabled('smtc-debug'); +if (!$no_smtc) { + $ENV{OPENSSL_CONF} = srctop_file("test", "smtc.cnf"); +} + +$ENV{TEST_CERTS_DIR} = srctop_dir("test", "certs"); + +my @conf_srcs = glob(srctop_file("test", "ntls-tests", "*.cnf.in")); +my @conf_files = map { basename($_, ".in") } @conf_srcs; + +# We hard-code the number of tests to double-check that the globbing above +# finds all files as expected. +plan tests => 5; + + +# Add your test here if the test conf.in generates test cases and/or +# expectations dynamically based on the OpenSSL compile-time config. +my %conf_dependent_tests = ( + "31-ntls.cnf" => disabled("ntls"), + "32-ntls-force-ntls.cnf" => disabled("ntls"), + "39-ntls-sni-ticket.cnf" => disabled("ntls"), + "40-ntls_client_auth.cnf" => disabled("ntls"), + "41-ntls-alpn.cnf" => disabled("ntls"), +); + +# Add your test here if it should be skipped for some compile-time +# configurations. Default is $no_tls but some tests have different skip +# conditions. +my %skip = ( + "31-ntls.cnf" => disabled("ntls") || disabled("sm2") || disabled("sm3") + || disabled("sm4"), + "32-ntls-force-ntls.cnf" => disabled("ntls") || disabled("sm2") + || disabled("sm3") || disabled("sm4") + || !disabled("smtc"), + "39-ntls-sni-ticket.cnf" => disabled("ntls") || disabled("sm2") + || disabled("sm3") || disabled("sm4"), + "40-ntls_client_auth.cnf" => disabled("ntls") || disabled("sm2") + || disabled("sm3") || disabled("sm4"), + "41-ntls-alpn.cnf" => disabled("ntls") || disabled("sm2") || disabled("sm3") + || disabled("sm4"), +); + +foreach my $conf (@conf_files) { + subtest "Test configuration $conf" => sub { + plan tests => $no_smtc ? 6 : 3; + test_conf($conf, + $conf_dependent_tests{$conf} ? 0 : 1, $skip{$conf}, "none") + unless !$no_smtc; + test_conf($conf, 0, $skip{$conf}, "default") unless !$no_smtc; + test_conf($conf, 0, $skip{$conf}, "smtc") unless $no_smtc; + }; +} + +sub test_conf { + my ($conf, $check_source, $skip, $provider) = @_; + + my $conf_file = srctop_file("test", "ntls-tests", $conf); + my $input_file = $conf_file . ".in"; + my $output_file = $conf . "." . $provider; + my $run_test = 1; + + SKIP: { + # "Test" 1. Generate the source. + skip 'failure', 2 unless + ok(run(perltest(["generate_ssl_tests.pl", $input_file, $provider], + interpreter_args => [ "-I", srctop_dir("util", "perl")], + stdout => $output_file)), + "Getting output from generate_ssl_tests.pl."); + + SKIP: { + # Test 2. Compare against existing output in test/ntls-tests/ + skip "Skipping generated source test for $conf", 1 + if !$check_source; + + $run_test = is(cmp_text($output_file, $conf_file), 0, + "Comparing generated $output_file with $conf_file."); + } + + # Test 3. Run the test. + skip "No tests available; skipping tests", 1 if $skip; + skip "Stale sources; skipping tests", 1 if !$run_test; + + if ($provider eq "smtc") { + ok(run(test(["ssl_test", $output_file, $provider, + srctop_file("test", "smtc.cnf")])), + "running ssl_test $conf"); + } else { + ok(run(test(["ssl_test", $output_file, $provider])), + "running ssl_test $conf"); + } + } +} + +sub cmp_text { + return compare_text(@_, sub { + $_[0] =~ s/\R//g; + $_[1] =~ s/\R//g; + return $_[0] ne $_[1]; + }); +} diff --git a/test/recipes/80-test_sign_sm2.t b/test/recipes/80-test_sign_sm2.t index f746cb14e..0ef63fb93 100644 --- a/test/recipes/80-test_sign_sm2.t +++ b/test/recipes/80-test_sign_sm2.t @@ -11,7 +11,7 @@ use warnings; use POSIX; use File::Path 2.00 qw/rmtree/; -use OpenSSL::Test qw/:DEFAULT data_file merge_files/; +use OpenSSL::Test qw/:DEFAULT data_file merge_files srctop_file/; use OpenSSL::Test::Utils; use File::Spec::Functions qw/catfile catdir/; @@ -23,6 +23,11 @@ plan skip_all => "sm2 is not supported by this OpenSSL build" plan tests => 22; +my $no_smtc = disabled('smtc') || disabled('smtc-debug'); +if (!$no_smtc) { + $ENV{OPENSSL_CONF} = srctop_file("test", "smtc.cnf"); +} + my $CADIR = catdir(".", "ca"); my $SUBCADIR = catdir(".", "subca"); diff --git a/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t index edb42c3a3..0c417998c 100644 --- a/test/recipes/80-test_ssl_new.t +++ b/test/recipes/80-test_ssl_new.t @@ -25,7 +25,6 @@ use lib srctop_dir('Configurations'); use lib bldtop_dir('.'); my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0); -my $no_smtc = disabled('smtc') || disabled('smtc-debug'); $ENV{TEST_CERTS_DIR} = srctop_dir("test", "certs"); $ENV{TEST_RUNS_DIR} = catdir(result_dir(), "..", "test_dc_sign"); @@ -35,7 +34,7 @@ my @conf_files = map { basename($_, ".in") } @conf_srcs; # We hard-code the number of tests to double-check that the globbing above # finds all files as expected. -plan tests => 37; +plan tests => 32; # Some test results depend on the configuration of enabled protocols. We only # verify generated sources in the default configuration. @@ -81,12 +80,7 @@ my %conf_dependent_tests = ( "27-ticket-appdata.cnf" => !$is_default_tls, "28-seclevel.cnf" => disabled("tls1_2") || $no_ec, "30-extended-master-secret.cnf" => disabled("tls1_2"), - "31-ntls.cnf" => disabled("ntls"), - "32-ntls-force-ntls.cnf" => disabled("ntls"), "38-delegated-credential.cnf" => disabled("delegated-credential"), - "39-ntls-sni-ticket.cnf" => disabled("ntls"), - "40-ntls_client_auth.cnf" => disabled("ntls"), - "41-ntls-alpn.cnf" => disabled("ntls"), ); # Add your test here if it should be skipped for some compile-time @@ -123,26 +117,12 @@ my %skip = ( "29-dtls-sctp-label-bug.cnf" => disabled("sctp") || disabled("sock"), "30-tls13-sm.cnf" => disabled("sm2") || disabled("sm3") || disabled("sm4") || disabled("tls1_3") || !$no_fips, - "31-ntls.cnf" => disabled("ntls") || disabled("sm2") || disabled("sm3") - || disabled("sm4") || !$no_fips, - "32-ntls-force-ntls.cnf" => disabled("ntls") || disabled("sm2") - || disabled("sm3") || disabled("sm4") - || !$no_fips || !disabled("smtc"), "38-delegated-credential.cnf" => disabled("delegated-credential"), - "39-ntls-sni-ticket.cnf" => disabled("ntls") || disabled("sm2") - || disabled("sm3") || disabled("sm4") - || !$no_fips, - "40-ntls_client_auth.cnf" => disabled("ntls") || disabled("sm2") - || disabled("sm3") || disabled("sm4") - || !$no_fips, - "41-ntls-alpn.cnf" => disabled("ntls") || disabled("sm2") - || disabled("sm3") || disabled("sm4") || !$no_fips, ); foreach my $conf (@conf_files) { subtest "Test configuration $conf" => sub { - plan tests => 6 + ($no_fips ? 0 : 3) - + ($conf !~ /^[0-9]+-ntls/ || $no_smtc ? 0 : 3); + plan tests => 6 + ($no_fips ? 0 : 3); test_conf($conf, $conf_dependent_tests{$conf} ? 0 : 1, defined($skip{$conf}) ? $skip{$conf} : $no_tls, @@ -155,10 +135,6 @@ foreach my $conf (@conf_files) { 0, defined($skip{$conf}) ? $skip{$conf} : $no_tls, "fips") unless $no_fips; - test_conf($conf, - 0, - defined($skip{$conf}) ? $skip{$conf} : $no_tls, - "smtc") unless ($conf !~ /^[0-9]+-ntls/ || $no_smtc); }; } @@ -201,10 +177,6 @@ sub test_conf { ok(run(test(["ssl_test", $output_file, $provider, srctop_file("test", "fips-and-base.cnf")])), "running ssl_test $conf"); - } elsif ($provider eq "smtc") { - ok(run(test(["ssl_test", $output_file, $provider, - srctop_file("test", "smtc-and-base.cnf")])), - "running ssl_test $conf"); } else { ok(run(test(["ssl_test", $output_file, $provider])), "running ssl_test $conf"); diff --git a/test/recipes/92-test_tsapi.t b/test/recipes/92-test_tsapi.t new file mode 100644 index 000000000..ba7bb0e0e --- /dev/null +++ b/test/recipes/92-test_tsapi.t @@ -0,0 +1,22 @@ +#! /usr/bin/env perl +# Copyright 2024 The Tongsuo 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://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt + +use OpenSSL::Test qw/:DEFAULT srctop_file/; +use OpenSSL::Test::Simple; +use OpenSSL::Test::Utils; + +setup("test_tsapi"); + +my $no_smtc = disabled('smtc') || disabled('smtc-debug'); + +if (!$no_smtc) { + my $smtcconf = srctop_file("test", "smtc.cnf"); + $ENV{OPENSSL_CONF} = $smtcconf; +} + +simple_test("test_tsapi", "tsapi_test"); diff --git a/test/smtc-and-base.cnf b/test/smtc.cnf similarity index 82% rename from test/smtc-and-base.cnf rename to test/smtc.cnf index 4149104d4..3437335ad 100644 --- a/test/smtc-and-base.cnf +++ b/test/smtc.cnf @@ -10,8 +10,3 @@ providers = provider_sect [provider_sect] smtc = smtc_sect -base = base_sect - -[base_sect] -activate = 1 - diff --git a/test/testutil/provider.c b/test/testutil/provider.c index d073d732d..e817e4a58 100644 --- a/test/testutil/provider.c +++ b/test/testutil/provider.c @@ -57,7 +57,7 @@ int test_arg_libctx(OSSL_LIB_CTX **libctx, OSSL_PROVIDER **default_null_prov, TEST_error("usage: %s", usage); return 0; } - if (strcmp(module_name, "none") == 0) + if (strcmp(module_name, "none") == 0 || strcmp(module_name, "smtc") == 0) return 1; return test_get_libctx(libctx, default_null_prov, test_get_argument(argn + 1), provider, module_name); diff --git a/test/tsapi_test.c b/test/tsapi_test.c new file mode 100644 index 000000000..1c3dabb26 --- /dev/null +++ b/test/tsapi_test.c @@ -0,0 +1,484 @@ +/* + * Copyright 2024 The Tongsuo 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://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt + */ + +#include +#include +#include +#include +#include +#include "testutil.h" +#include "../crypto/sdf/sdf_local.h" +#ifdef SDF_LIB +# include "sdfe_api.h" +#endif + +static int test_TSAPI_Version(void) +{ + char *version = TSAPI_Version(); + + if (!TEST_ptr(version)) + return 0; + + OPENSSL_free(version); + return 1; +} + +static int test_TSAPI_RandBytes(void) +{ + int ret = 0; + size_t len = 32; + unsigned char *buf1 = NULL; + unsigned char *buf2 = NULL; + + buf1 = TSAPI_RandBytes(len); + if (!TEST_ptr(buf1)) + goto end; + + buf2 = TSAPI_RandBytes(len); + if (!TEST_ptr(buf2)) + goto end; + + if (!TEST_mem_ne(buf1, len, buf2, len)) + goto end; + + ret = 1; +end: + OPENSSL_free(buf1); + OPENSSL_free(buf2); + return ret; +} + +#ifndef OPENSSL_NO_SM2 +static int test_TSAPI_SM2Keygen(void) +{ + int ok = 0; + EVP_PKEY *key = NULL, *pubkey = NULL; + unsigned char *sig = NULL; + const char *input = "test"; + size_t siglen; + BIO *tmpbio = NULL; + + key = TSAPI_SM2Keygen(); + if (!TEST_ptr(key)) + return 0; + + tmpbio = BIO_new(BIO_s_mem()); + if (!TEST_ptr(tmpbio)) + goto end; + + if (!TEST_true(PEM_write_bio_PUBKEY(tmpbio, key))) + goto end; + + pubkey = PEM_read_bio_PUBKEY(tmpbio, NULL, NULL, NULL); + if (!TEST_ptr(pubkey)) + goto end; + + sig = TSAPI_SM2Sign(key, (const unsigned char *)input, strlen(input), + &siglen); + if (!TEST_ptr(sig)) + goto end; + + if (!TEST_true(TSAPI_SM2Verify(pubkey, (const unsigned char *)input, + strlen(input), sig, siglen))) + goto end; + + ok = 1; +end: + BIO_free(tmpbio); + OPENSSL_free(sig); + EVP_PKEY_free(pubkey); + EVP_PKEY_free(key); + return ok; +} + +static int test_TSAPI_SM2Sign(void) +{ + int ok = 0; + EVP_PKEY *key = NULL; + const char *input = "test"; + unsigned char *sig = NULL; + size_t siglen; + + key = TSAPI_SM2Keygen(); + if (!TEST_ptr(key)) + return 0; + + sig = TSAPI_SM2Sign(key, (const unsigned char *)input, strlen(input), + &siglen); + if (!TEST_ptr(sig) || !TEST_true(siglen > 0)) + goto end; + + ok = 1; +end: + OPENSSL_free(sig); + EVP_PKEY_free(key); + return ok; +} + +static int test_TSAPI_SM2Verify(void) +{ + int ok = 0; + EVP_PKEY *key = NULL; + BIO *bio = NULL; + const char *pem = "-----BEGIN PUBLIC KEY-----\n" +"MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEOToq2eJ+Q6yqq4WhnTuFWR4UQGFX\n" +"F1rd03v3f/DK+e03/POotPVcA4UjJh/KZjav5qevoqFIKmBvXLOhiy4qHg==\n" +"-----END PUBLIC KEY-----"; + const char *input = "hello world"; + unsigned char sig[] = { + 0x30, 0x45, 0x02, 0x20, 0x6b, 0xa1, 0x2c, 0x29, 0xaf, 0x6a, 0x4d, 0xe7, + 0x6d, 0xb0, 0x85, 0xa1, 0xd3, 0x5f, 0xfa, 0x1d, 0x00, 0x77, 0xfc, 0x6a, + 0x13, 0xe4, 0xac, 0x1b, 0x64, 0xe6, 0x82, 0x9e, 0x34, 0x89, 0x71, 0xfb, + 0x02, 0x21, 0x00, 0xcb, 0xfe, 0xab, 0xc6, 0xcb, 0x61, 0x2d, 0x25, 0xe9, + 0x0a, 0xdc, 0x71, 0xde, 0xe3, 0x9a, 0xdb, 0xfa, 0xcf, 0x62, 0x4e, 0x5a, + 0xa9, 0x4b, 0x8d, 0xac, 0x7c, 0x7b, 0xa8, 0x4b, 0x7b, 0x77, 0x9c,}; + size_t siglen = sizeof(sig); + + bio = BIO_new_mem_buf(pem, -1); + if (!TEST_ptr(bio)) + return 0; + + key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); + if (!TEST_ptr(key)) + goto end; + + if (!TEST_true(TSAPI_SM2Verify(key, (const unsigned char *)input, + strlen(input), sig, siglen))) + goto end; + + ok = 1; +end: + BIO_free(bio); + EVP_PKEY_free(key); + return ok; +} + +static int test_TSAPI_SM2Encrypt(void) +{ + int ok = 0; + EVP_PKEY *key = NULL; + BIO *bio = NULL; + const char *pem = "-----BEGIN PUBLIC KEY-----\n" +"MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEOToq2eJ+Q6yqq4WhnTuFWR4UQGFX\n" +"F1rd03v3f/DK+e03/POotPVcA4UjJh/KZjav5qevoqFIKmBvXLOhiy4qHg==\n" +"-----END PUBLIC KEY-----"; + const char *input = "test"; + unsigned char *out = NULL; + size_t outlen; + + bio = BIO_new_mem_buf(pem, -1); + if (!TEST_ptr(bio)) + return 0; + + key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); + if (!TEST_ptr(key)) + goto end; + + out = TSAPI_SM2Encrypt(key, (const unsigned char *)input, strlen(input), + &outlen); + if (!TEST_ptr(out) + || !TEST_true(outlen > 0)) + goto end; + + ok = 1; +end: + BIO_free(bio); + EVP_PKEY_free(key); + OPENSSL_free(out); + return ok; +} + +# ifdef SDF_LIB +static int bitmap_is_inuse(uint64_t *pu64, int32_t index) +{ + + int32_t pos, offset; + uint64_t mask; + + mask = 0x1ull; + + pos = index >> 6; + offset = (63 - (index & 0x3f)); + mask <<= offset; + + return (pu64[pos] & mask) ? 1 : 0; +} +# endif + +static int test_TSAPI_SM2Decrypt(void) +{ + int ok = 0; +# ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_login_arg_t login_arg; + OSSL_ECCrefPrivateKey *privkey = NULL; + OSSL_ECCrefPublicKey *pubkey = NULL; + sdfe_bitmap_t bitmap; + sdfe_asym_key_ecc_t asym; + OSSL_ECCCipher *pECCCipher = NULL; + uint32_t cnt, i; + int index = -1; + unsigned char out[256]; + unsigned int outlen = sizeof(out); +# else + unsigned char *out = NULL; + size_t outlen; +# endif + EVP_PKEY *key = NULL; + BIO *bio = NULL; + const char *pem = "-----BEGIN PRIVATE KEY-----\n" +"MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQg0JFWczAXva2An9m7\n" +"2MaT9gIwWTFptvlKrxyO4TjMmbWhRANCAAQ5OirZ4n5DrKqrhaGdO4VZHhRAYVcX\n" +"Wt3Te/d/8Mr57Tf886i09VwDhSMmH8pmNq/mp6+ioUgqYG9cs6GLLioe\n" +"-----END PRIVATE KEY-----"; + unsigned char in[] = { + 0x30, 0x81, 0x8A, 0x02, 0x20, 0x46, 0x6B, 0xE2, 0xEF, 0x5C, 0x11, 0x78, + 0x2E, 0xC7, 0x78, 0x64, 0xA0, 0x05, 0x54, 0x17, 0xF4, 0x07, 0xA5, 0xAF, + 0xC1, 0x1D, 0x65, 0x3C, 0x6B, 0xCE, 0x69, 0xE4, 0x17, 0xBB, 0x1D, 0x05, + 0xB6, 0x02, 0x20, 0x62, 0xB5, 0x72, 0xE2, 0x1F, 0xF0, 0xDD, 0xF5, 0xC7, + 0x26, 0xBD, 0x3F, 0x9F, 0xF2, 0xEA, 0xE5, 0x6E, 0x62, 0x94, 0x71, 0x3A, + 0x60, 0x7E, 0x9B, 0x95, 0x25, 0x62, 0x89, 0x65, 0xF6, 0x2C, 0xC8, 0x04, + 0x20, 0x3C, 0x1B, 0x57, 0x13, 0xB5, 0xDB, 0x27, 0x28, 0xEB, 0x7B, 0xF7, + 0x75, 0xE4, 0x4F, 0x46, 0x89, 0xFC, 0x32, 0x66, 0x8B, 0xDC, 0x56, 0x4F, + 0x52, 0xEA, 0x45, 0xB0, 0x9E, 0x8D, 0xF2, 0xA5, 0xF4, 0x04, 0x22, 0x08, + 0x4A, 0x9D, 0x0C, 0xC2, 0x99, 0x70, 0x92, 0xB7, 0xD3, 0xC4, 0x04, 0xFC, + 0xE9, 0x59, 0x56, 0xEB, 0x60, 0x4D, 0x73, 0x2B, 0x23, 0x07, 0xA8, 0xE5, + 0xB8, 0x90, 0x0E, 0xD6, 0x60, 0x8C, 0xA5, 0xB1, 0x97,}; + const char *expected = "The floofy bunnies hop at midnight"; + + bio = BIO_new_mem_buf(pem, -1); + if (!TEST_ptr(bio)) + return 0; + + key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); + if (!TEST_ptr(key)) + goto end; + +# ifdef SDF_LIB + memset(&login_arg, 0, sizeof(login_arg)); + + strcpy((char *)login_arg.name, "admin"); + login_arg.passwd = (uint8_t *)"123123"; + login_arg.passwd_len = 6; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + bitmap.start = 0; + bitmap.cnt = SDFE_BITMAP_U64_MAX_CNT; + if (SDFE_BitmapAsymKey(hSessionHandle, SDFE_ASYM_KEY_AREA_ENC, + SDFE_ASYM_KEY_TYPE_SM2, &bitmap) != OSSL_SDR_OK) + goto end; + + cnt = bitmap.cnt << 6; + for(i = 0; i < cnt; i++){ + if(!bitmap_is_inuse(bitmap.bitmap, i)) { + index = i; + break; + } + } + + if (index < 0) + goto end; + + asym.area = SDFE_ASYM_KEY_AREA_ENC; + asym.index = index; + asym.type = SDFE_ASYM_KEY_TYPE_SM2; + asym.privkey_bits = 256; + asym.privkey_len = asym.privkey_bits >> 3; + asym.pubkey_bits = 256; + asym.pubkey_len = (asym.pubkey_bits >> 3) << 1; + + pubkey = TSAPI_EVP_PKEY_get_ECCrefPublicKey(key); + if (!TEST_ptr(pubkey)) + goto end; + + privkey = TSAPI_EVP_PKEY_get_ECCrefPrivateKey(key); + if (!TEST_ptr(privkey)) + goto end; + + memcpy(asym.pubkey, pubkey, sizeof(*pubkey)); + memcpy(asym.privkey, privkey, sizeof(*privkey)); + + if (SDFE_ImportECCKey(hSessionHandle, &asym, NULL) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_GetPrivateKeyAccessRight(hSessionHandle, index, NULL, 0) + != OSSL_SDR_OK) + goto end; + + pECCCipher = TSAPI_SM2Ciphertext_to_ECCCipher(in, sizeof(in)); + + if (TSAPI_SDF_InternalDecrypt_ECC(hSessionHandle, index, pECCCipher, + out, &outlen) != OSSL_SDR_OK) + goto end; +# else + out = TSAPI_SM2Decrypt(key, in, sizeof(in), &outlen); + if (!TEST_ptr(out)) + goto end; +# endif + + if (!TEST_true(outlen == strlen(expected)) + || !TEST_mem_eq(out, outlen, expected, strlen(expected))) + goto end; + + ok = 1; +end: + BIO_free(bio); + EVP_PKEY_free(key); +# ifdef SDF_LIB + OPENSSL_free(pubkey); + OPENSSL_free(privkey); + OPENSSL_free(pECCCipher); + (void)SDFE_DelECCKey(hSessionHandle, asym.area, index); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +# else + OPENSSL_free(out); +# endif + return ok; +} +#endif + +#ifndef OPENSSL_NO_SM4 +static int test_TSAPI_SM4Encrypt(void) +{ + unsigned char key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + unsigned char iv[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + unsigned char in[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, + 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + unsigned char expected[] = { + 0x26, 0x77, 0xF4, 0x6B, 0x09, 0xC1, 0x22, 0xCC, 0x97, 0x55, 0x33, 0x10, + 0x5B, 0xD4, 0xA2, 0x2A, 0xF6, 0x12, 0x5F, 0x72, 0x75, 0xCE, 0x55, 0x2C, + 0x3A, 0x2B, 0xBC, 0xF5, 0x33, 0xDE, 0x8A, 0x3B, + }; + unsigned char *out = NULL; + size_t outlen; + + out = TSAPI_SM4Encrypt(OSSL_SGD_MODE_CBC, key, sizeof(key), -1, iv, in, + sizeof(in), &outlen); + if (!TEST_ptr(out)) + return 0; + + if (!TEST_mem_eq(out, outlen, expected, sizeof(expected))) { + OPENSSL_free(out); + return 0; + } + + OPENSSL_free(out); + return 1; +} + +static int test_TSAPI_SM4Decrypt(void) +{ + unsigned char key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + unsigned char iv[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + unsigned char in[] = { + 0x26, 0x77, 0xF4, 0x6B, 0x09, 0xC1, 0x22, 0xCC, 0x97, 0x55, 0x33, 0x10, + 0x5B, 0xD4, 0xA2, 0x2A, 0xF6, 0x12, 0x5F, 0x72, 0x75, 0xCE, 0x55, 0x2C, + 0x3A, 0x2B, 0xBC, 0xF5, 0x33, 0xDE, 0x8A, 0x3B, + }; + unsigned char expected[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, + 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + unsigned char *out = NULL; + size_t outlen; + + out = TSAPI_SM4Decrypt(OSSL_SGD_MODE_CBC, key, sizeof(key), -1, iv, in, + sizeof(in), &outlen); + if (!TEST_ptr(out)) + return 0; + + if (!TEST_mem_eq(out, outlen, expected, sizeof(expected))) { + OPENSSL_free(out); + return 0; + } + + OPENSSL_free(out); + return 1; +} +#endif + +#ifndef OPENSSL_NO_SM3 +static int test_TSAPI_SM3(void) +{ + unsigned char in[] = { + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + }; + unsigned char expected[] = { + 0xDE, 0xBE, 0x9F, 0xF9, 0x22, 0x75, 0xB8, 0xA1, 0x38, 0x60, 0x48, 0x89, + 0xC1, 0x8E, 0x5A, 0x4D, 0x6F, 0xDB, 0x70, 0xE5, 0x38, 0x7E, 0x57, 0x65, + 0x29, 0x3d, 0xCb, 0xA3, 0x9C, 0x0C, 0x57, 0x32, + }; + size_t outlen; + unsigned char *out = TSAPI_SM3(in, sizeof(in), &outlen); + + if (!TEST_ptr(out)) + return 0; + + if (!TEST_mem_eq(out, outlen, expected, sizeof(expected))) { + OPENSSL_free(out); + return 0; + } + + OPENSSL_free(out); + return 1; +} +#endif + +int setup_tests(void) +{ + ADD_TEST(test_TSAPI_Version); + ADD_TEST(test_TSAPI_RandBytes); +#ifndef OPENSSL_NO_SM2 + ADD_TEST(test_TSAPI_SM2Keygen); + ADD_TEST(test_TSAPI_SM2Sign); + ADD_TEST(test_TSAPI_SM2Verify); + ADD_TEST(test_TSAPI_SM2Encrypt); + ADD_TEST(test_TSAPI_SM2Decrypt); +#endif +#ifndef OPENSSL_NO_SM4 + ADD_TEST(test_TSAPI_SM4Encrypt); + ADD_TEST(test_TSAPI_SM4Decrypt); +#endif +#ifndef OPENSSL_NO_SM3 + ADD_TEST(test_TSAPI_SM3); +#endif + + return 1; +} diff --git a/util/libcrypto.num b/util/libcrypto.num index 68c6edbf5..2602396b4 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5643,3 +5643,57 @@ PKCS12_create_ex2 5958 3_0_3 EXIST::FUNCTION: ASN1_item_unpack_ex 5960 3_0_3 EXIST::FUNCTION: PKCS12_SAFEBAG_get1_cert_ex 5961 3_0_3 EXIST::FUNCTION: PKCS12_SAFEBAG_get1_crl_ex 5962 3_0_3 EXIST::FUNCTION: +RAND_set_entropy_source 5963 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_OpenDevice 5964 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_CloseDevice 5965 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_OpenSession 5966 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_CloseSession 5967 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_ImportKeyWithKEK 5968 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_Encrypt 5969 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_Decrypt 5970 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_CalculateMAC 5971 3_0_3 EXIST::FUNCTION: +OSSL_enable_syslog 5972 3_0_3 EXIST::FUNCTION: +OSSL_disable_syslog 5973 3_0_3 EXIST::FUNCTION: +OSSL_syslog 5974 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_GetPrivateKeyAccessRight 5975 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_ReleasePrivateKeyAccessRight 5976 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_ImportKeyWithISK_ECC 5977 3_0_3 EXIST::FUNCTION: +TSAPI_GenerateSM2KeyWithIndex 5978 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SDF_GenerateKey 5979 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_DestroyKey 5980 3_0_3 EXIST::FUNCTION: +TSAPI_DelSm2KeyWithIndex 5981 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_UpdateSm2KeyWithIndex 5982 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_ExportSM2PubKeyWithIndex 5983 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SDF_ExportSignPublicKey_ECC 5984 3_0_3 EXIST::FUNCTION: +TSAPI_ImportSM2KeyWithEvlp 5985 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_ExportSM2KeyWithEvlp 5986 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SM2Encrypt 5987 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_EVP_PKEY_new_from_ECCrefKey 5988 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_EVP_PKEY_get_ECCrefPublicKey 5989 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_EVP_PKEY_get_ECCrefPrivateKey 5990 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_ExportSM2KeyWithIndex 5991 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SDF_ExportEncPublicKey_ECC 5992 3_0_3 EXIST::FUNCTION: +TSAPI_ImportSM2Key 5993 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SM3 5994 3_0_3 EXIST::FUNCTION:SM3 +TSAPI_SM2Ciphertext_to_ECCCipher 5995 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SM4Encrypt 5996 3_0_3 EXIST::FUNCTION:SM4 +TSAPI_SM4Decrypt 5997 3_0_3 EXIST::FUNCTION:SM4 +TSAPI_Version 5998 3_0_3 EXIST::FUNCTION: +TSAPI_RandBytes 5999 3_0_3 EXIST::FUNCTION: +OSSL_PROVIDER_reset 6000 3_0_3 EXIST::FUNCTION: +OSSL_PROVIDER_status 6001 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_InternalEncrypt_ECC 6002 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_InternalDecrypt_ECC 6003 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_InternalSign_ECC 6004 3_0_3 EXIST::FUNCTION: +EVP_PKEY_CTX_new_from_name_provided 6005 3_0_3 EXIST::FUNCTION: +EVP_PKEY_CTX_new_from_pkey_provided 6006 3_0_3 EXIST::FUNCTION: +TSAPI_GetEntropy 6007 3_0_3 EXIST::FUNCTION: +TSAPI_FreeEntropy 6008 3_0_3 EXIST::FUNCTION: +TSAPI_ECCCipher_to_SM2Ciphertext 6009 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SM2EncryptWithISK 6010 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SM2DecryptWithISK 6011 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SM2Keygen 6012 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SM2Sign 6013 3_0_3 EXIST::FUNCTION:SM2,SM3 +TSAPI_SM2Verify 6014 3_0_3 EXIST::FUNCTION:SM2,SM3 +TSAPI_SM2Decrypt 6015 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SDF_GenerateRandom 6016 3_0_3 EXIST::FUNCTION: From 73c643f7f8c158d9b7878b5cdc7b72c98ac52be4 Mon Sep 17 00:00:00 2001 From: K1 Date: Fri, 23 Aug 2024 10:48:23 +0800 Subject: [PATCH 64/66] Fix memory leak in TSAPI_ImportSM2Key() privkey and pubkey should be freed at the end of TSAPI_ImportSM2Key(). --- crypto/tsapi/tsapi_lib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crypto/tsapi/tsapi_lib.c b/crypto/tsapi/tsapi_lib.c index cf66021ab..07e91fd16 100644 --- a/crypto/tsapi/tsapi_lib.c +++ b/crypto/tsapi/tsapi_lib.c @@ -430,6 +430,8 @@ int TSAPI_ImportSM2Key(int index, int sign, const char *user, ok = 1; end: + OPENSSL_free(privkey); + OPENSSL_free(pubkey); TSAPI_SDF_CloseSession(hSessionHandle); TSAPI_SDF_CloseDevice(hDeviceHandle); #endif From 6241b23320a1d1a0a9a361015d12f0b1540ef92c Mon Sep 17 00:00:00 2001 From: K1 Date: Tue, 27 Aug 2024 16:57:02 +0800 Subject: [PATCH 65/66] Refactor RAND_set_entropy_source, supports passing in comma-separated sources --- apps/rand.c | 43 ++++------------------------ crypto/err/openssl.txt | 1 + crypto/rand/rand_err.c | 4 ++- crypto/rand/rand_lib.c | 59 ++++++++++++++++++++++++++++++++++++++- include/openssl/rand.h | 2 +- include/openssl/randerr.h | 3 +- 6 files changed, 70 insertions(+), 42 deletions(-) diff --git a/apps/rand.c b/apps/rand.c index 47be38976..e1365da86 100644 --- a/apps/rand.c +++ b/apps/rand.c @@ -22,7 +22,7 @@ typedef enum OPTION_choice { OPT_COMMON, - OPT_OUT, OPT_ENGINE, OPT_BASE64, OPT_HEX, OPT_ENTROPY, OPT_SOURCE, + OPT_OUT, OPT_ENGINE, OPT_BASE64, OPT_HEX, OPT_ENTROPY, OPT_ENTROPY_SOURCE, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; @@ -40,7 +40,7 @@ const OPTIONS rand_options[] = { {"base64", OPT_BASE64, '-', "Base64 encode output"}, {"hex", OPT_HEX, '-', "Hex encode output"}, {"entropy", OPT_ENTROPY, '-', "Output entropy instead of random data"}, - {"source", OPT_SOURCE, 's', "Specify the entropy source"}, + {"entropy_source", OPT_ENTROPY_SOURCE, 's', "Specify the entropy source"}, OPT_R_OPTIONS, OPT_PROV_OPTIONS, @@ -50,43 +50,10 @@ const OPTIONS rand_options[] = { {NULL} }; -static int opt_rand_source(const char *name) -{ - int ret = 0; - - if (strcmp(name, "getrandom") == 0) - ret = RAND_ENTROPY_SOURCE_GETRANDOM; - else if (strcmp(name, "devrandom") == 0) - ret = RAND_ENTROPY_SOURCE_DEVRANDOM; - else if (strcmp(name, "rdtsc") == 0) - ret = RAND_ENTROPY_SOURCE_RDTSC; - else if (strcmp(name, "rdcpu") == 0) - ret = RAND_ENTROPY_SOURCE_RDCPU; - else if (strcmp(name, "egd") == 0) - ret = RAND_ENTROPY_SOURCE_EGD; - else if (strcmp(name, "bcryptgenrandom") == 0) - ret = RAND_ENTROPY_SOURCE_BCRYPTGENRANDOM; - else if (strcmp(name, "cryptgenrandom_def_prov") == 0) - ret = RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_DEF_PROV; - else if (strcmp(name, "cryptgenrandom_intel_prov") == 0) - ret = RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_INTEL_PROV; - else if (strcmp(name, "rtcode") == 0) - ret = RAND_ENTROPY_SOURCE_RTCODE; - else if (strcmp(name, "rtmem") == 0) - ret = RAND_ENTROPY_SOURCE_RTMEM; - else if (strcmp(name, "rtsock") == 0) - ret = RAND_ENTROPY_SOURCE_RTSOCK; - else - BIO_printf(bio_err, "Unknown entropy source '%s'\n", name); - - return ret; -} - int rand_main(int argc, char **argv) { ENGINE *e = NULL; BIO *out = NULL; - int source = 0; char *outfile = NULL, *prog; OPTION_CHOICE o; unsigned char *ent_buf = NULL, *p; @@ -124,9 +91,9 @@ int rand_main(int argc, char **argv) case OPT_ENTROPY: entropy = 1; break; - case OPT_SOURCE: - source |= opt_rand_source(opt_arg()); - RAND_set_entropy_source(source); + case OPT_ENTROPY_SOURCE: + if (!RAND_set_entropy_source(opt_arg())) + goto end; break; case OPT_PROV_CASES: if (!opt_provider(o)) diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index d1973c0eb..3d9bd9c33 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1113,6 +1113,7 @@ RAND_R_FWRITE_ERROR:123:Error writing file RAND_R_GENERATE_ERROR:112:generate error RAND_R_INSUFFICIENT_DRBG_STRENGTH:139:insufficient drbg strength RAND_R_INTERNAL_ERROR:113:internal error +RAND_R_INVALID_ENTROPY_SOURCE:145:invalid entropy source RAND_R_IN_ERROR_STATE:114:in error state RAND_R_NOT_A_REGULAR_FILE:122:Not a regular file RAND_R_NOT_INSTANTIATED:115:not instantiated diff --git a/crypto/rand/rand_err.c b/crypto/rand/rand_err.c index b9c2bf176..e209574b6 100644 --- a/crypto/rand/rand_err.c +++ b/crypto/rand/rand_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 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 @@ -51,6 +51,8 @@ static const ERR_STRING_DATA RAND_str_reasons[] = { {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INSUFFICIENT_DRBG_STRENGTH), "insufficient drbg strength"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INTERNAL_ERROR), "internal error"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INVALID_ENTROPY_SOURCE), + "invalid entropy source"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_IN_ERROR_STATE), "in error state"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_A_REGULAR_FILE), "Not a regular file"}, diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 13092eadf..24ea16047 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -822,9 +822,66 @@ void ossl_random_add_conf_module(void) CONF_module_add("random", random_conf_init, random_conf_deinit); } -void RAND_set_entropy_source(unsigned int type) +static int entropy_source_to_type(const char *name) +{ + int ret; + + if (strcmp(name, "getrandom") == 0) + ret = RAND_ENTROPY_SOURCE_GETRANDOM; + else if (strcmp(name, "devrandom") == 0) + ret = RAND_ENTROPY_SOURCE_DEVRANDOM; + else if (strcmp(name, "rdtsc") == 0) + ret = RAND_ENTROPY_SOURCE_RDTSC; + else if (strcmp(name, "rdcpu") == 0) + ret = RAND_ENTROPY_SOURCE_RDCPU; + else if (strcmp(name, "egd") == 0) + ret = RAND_ENTROPY_SOURCE_EGD; + else if (strcmp(name, "bcryptgenrandom") == 0) + ret = RAND_ENTROPY_SOURCE_BCRYPTGENRANDOM; + else if (strcmp(name, "cryptgenrandom_def_prov") == 0) + ret = RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_DEF_PROV; + else if (strcmp(name, "cryptgenrandom_intel_prov") == 0) + ret = RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_INTEL_PROV; + else if (strcmp(name, "rtcode") == 0) + ret = RAND_ENTROPY_SOURCE_RTCODE; + else if (strcmp(name, "rtmem") == 0) + ret = RAND_ENTROPY_SOURCE_RTMEM; + else if (strcmp(name, "rtsock") == 0) + ret = RAND_ENTROPY_SOURCE_RTSOCK; + else + ret = -1; + + return ret; +} + +int RAND_set_entropy_source(const char *source) { + int ok = 0; + int type = 0, cur_type; + char *val, *valp, *item; + + val = OPENSSL_strdup(source); + if (val == NULL) { + ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE); + return 0; + } + + for (valp = val; (item = strtok(valp, ",")) != NULL; valp = NULL) { + cur_type = entropy_source_to_type(item); + if (cur_type < 0) { + ERR_raise_data(ERR_LIB_RAND, RAND_R_INVALID_ENTROPY_SOURCE, + "source=%s", item); + goto end; + } + + type |= cur_type; + } + ossl_rand_pool_set_default_entropy_source(type); + ok = 1; +end: + OPENSSL_free(val); + return ok; } int RAND_set_DRBG_type(OSSL_LIB_CTX *ctx, const char *drbg, const char *propq, diff --git a/include/openssl/rand.h b/include/openssl/rand.h index 1673631c7..1e46b05ee 100644 --- a/include/openssl/rand.h +++ b/include/openssl/rand.h @@ -87,7 +87,7 @@ int RAND_set_DRBG_type(OSSL_LIB_CTX *ctx, const char *drbg, const char *propq, const char *cipher, const char *digest); int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed, const char *propq); -void RAND_set_entropy_source(unsigned int source); +int RAND_set_entropy_source(const char *source); void RAND_seed(const void *buf, int num); void RAND_keep_random_devices_open(int keep); diff --git a/include/openssl/randerr.h b/include/openssl/randerr.h index b5e08e436..44bb201a8 100644 --- a/include/openssl/randerr.h +++ b/include/openssl/randerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 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 @@ -41,6 +41,7 @@ # define RAND_R_GENERATE_ERROR 112 # define RAND_R_INSUFFICIENT_DRBG_STRENGTH 139 # define RAND_R_INTERNAL_ERROR 113 +# define RAND_R_INVALID_ENTROPY_SOURCE 145 # define RAND_R_IN_ERROR_STATE 114 # define RAND_R_NOT_A_REGULAR_FILE 122 # define RAND_R_NOT_INSTANTIATED 115 From 7438248fe6fc44b3fa847b09a35e7d2f67d3801e Mon Sep 17 00:00:00 2001 From: K1 Date: Thu, 12 Sep 2024 10:49:31 +0800 Subject: [PATCH 66/66] CI upgrade upload-artifact to v4 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8785df435..395c2d45f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,7 +21,7 @@ jobs: fuzz-seconds: 600 dry-run: false - name: Upload Crash - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 if: failure() with: name: artifacts