diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Cipher.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Cipher.cs index 39c980bdfab125..8de978aea5df30 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Cipher.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Cipher.cs @@ -64,7 +64,15 @@ internal static void CipherSetNonceLength(SafeEvpCipherCtxHandle ctx, int nonceL [GeneratedDllImport(Libraries.AndroidCryptoNative, EntryPoint = "AndroidCryptoNative_CipherReset")] [return: MarshalAs(UnmanagedType.Bool)] - internal static partial bool EvpCipherReset(SafeEvpCipherCtxHandle ctx); + private static unsafe partial bool EvpCipherReset(SafeEvpCipherCtxHandle ctx, byte* pIv, int cIv); + + internal static unsafe bool EvpCipherReset(SafeEvpCipherCtxHandle ctx, ReadOnlySpan iv) + { + fixed (byte* pIv = &MemoryMarshal.GetReference(iv)) + { + return EvpCipherReset(ctx, pIv, iv.Length); + } + } [GeneratedDllImport(Libraries.AndroidCryptoNative, EntryPoint = "AndroidCryptoNative_CipherCtxSetPadding")] [return: MarshalAs(UnmanagedType.Bool)] diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs index 68d18a56983d41..b9496982622504 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs @@ -76,7 +76,15 @@ internal static void EvpCipherSetCcmNonceLength(SafeEvpCipherCtxHandle ctx, int [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherReset")] [return: MarshalAs(UnmanagedType.Bool)] - internal static partial bool EvpCipherReset(SafeEvpCipherCtxHandle ctx); + private static unsafe partial bool EvpCipherReset(SafeEvpCipherCtxHandle ctx, byte* pIv, int cIv); + + internal static unsafe bool EvpCipherReset(SafeEvpCipherCtxHandle ctx, ReadOnlySpan iv) + { + fixed (byte* pIv = &MemoryMarshal.GetReference(iv)) + { + return EvpCipherReset(ctx, pIv, iv.Length); + } + } [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherCtxSetPadding")] [return: MarshalAs(UnmanagedType.Bool)] diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/OpenSslCipherLite.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/OpenSslCipherLite.cs index c378dc81140476..4568c042742081 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/OpenSslCipherLite.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/OpenSslCipherLite.cs @@ -125,7 +125,7 @@ public unsafe int Transform(ReadOnlySpan input, Span output) public void Reset(ReadOnlySpan iv) { - bool status = Interop.Crypto.EvpCipherReset(_ctx); + bool status = Interop.Crypto.EvpCipherReset(_ctx, iv); CheckBoolReturn(status); #if DEBUG diff --git a/src/native/libs/System.Security.Cryptography.Native.Android/pal_cipher.c b/src/native/libs/System.Security.Cryptography.Native.Android/pal_cipher.c index 4dd95a119de599..0b52b0a100a8c9 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Android/pal_cipher.c +++ b/src/native/libs/System.Security.Cryptography.Native.Android/pal_cipher.c @@ -316,7 +316,7 @@ int32_t AndroidCryptoNative_CipherCtxSetPadding(CipherCtx* ctx, int32_t padding) } } -int32_t AndroidCryptoNative_CipherReset(CipherCtx* ctx) +int32_t AndroidCryptoNative_CipherReset(CipherCtx* ctx, uint8_t* pIv, int32_t cIv) { if (!ctx) return FAIL; @@ -334,6 +334,20 @@ int32_t AndroidCryptoNative_CipherReset(CipherCtx* ctx) if (CheckJNIExceptions(env)) return FAIL; + if (pIv) + { + if (ctx->ivLength != cIv) + { + return FAIL; + } + + SaveTo(pIv, &ctx->iv, (size_t)ctx->ivLength, /* overwrite */ true); + } + else if (cIv != 0) + { + return FAIL; + } + return ReinitializeCipher(ctx); } diff --git a/src/native/libs/System.Security.Cryptography.Native.Android/pal_cipher.h b/src/native/libs/System.Security.Cryptography.Native.Android/pal_cipher.h index 28d2fc52e8225a..6b9555967a5a73 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Android/pal_cipher.h +++ b/src/native/libs/System.Security.Cryptography.Native.Android/pal_cipher.h @@ -31,7 +31,7 @@ PALEXPORT int32_t AndroidCryptoNative_CipherSetTagLength(CipherCtx* ctx, int32_t PALEXPORT int32_t AndroidCryptoNative_CipherSetKeyAndIV(CipherCtx* ctx, uint8_t* key, uint8_t* iv, int32_t enc); PALEXPORT int32_t AndroidCryptoNative_CipherSetNonceLength(CipherCtx* ctx, int32_t ivLength); PALEXPORT void AndroidCryptoNative_CipherDestroy(CipherCtx* ctx); -PALEXPORT int32_t AndroidCryptoNative_CipherReset(CipherCtx* ctx); +PALEXPORT int32_t AndroidCryptoNative_CipherReset(CipherCtx* ctx, uint8_t* pIv, int32_t cIv); PALEXPORT int32_t AndroidCryptoNative_CipherCtxSetPadding(CipherCtx* ctx, int32_t padding); PALEXPORT int32_t AndroidCryptoNative_CipherUpdateAAD(CipherCtx* ctx, uint8_t* in, int32_t inl); PALEXPORT int32_t AndroidCryptoNative_CipherUpdate(CipherCtx* ctx, uint8_t* out, int32_t* outl, uint8_t* in, int32_t inl); diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h index a64aac0c676e9c..bad52f66bde0c6 100644 --- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h @@ -298,7 +298,6 @@ const EVP_CIPHER* EVP_chacha20_poly1305(void); LEGACY_FUNCTION(EVP_CIPHER_CTX_cleanup) \ REQUIRED_FUNCTION(EVP_CIPHER_CTX_ctrl) \ FALLBACK_FUNCTION(EVP_CIPHER_CTX_free) \ - LIGHTUP_FUNCTION(EVP_CIPHER_CTX_get_original_iv) \ LEGACY_FUNCTION(EVP_CIPHER_CTX_init) \ FALLBACK_FUNCTION(EVP_CIPHER_CTX_new) \ FALLBACK_FUNCTION(EVP_CIPHER_CTX_reset) \ @@ -757,7 +756,6 @@ FOR_ALL_OPENSSL_FUNCTIONS #define EVP_CIPHER_CTX_cleanup EVP_CIPHER_CTX_cleanup_ptr #define EVP_CIPHER_CTX_ctrl EVP_CIPHER_CTX_ctrl_ptr #define EVP_CIPHER_CTX_free EVP_CIPHER_CTX_free_ptr -#define EVP_CIPHER_CTX_get_original_iv EVP_CIPHER_CTX_get_original_iv_ptr #define EVP_CIPHER_CTX_init EVP_CIPHER_CTX_init_ptr #define EVP_CIPHER_CTX_new EVP_CIPHER_CTX_new_ptr #define EVP_CIPHER_CTX_reset EVP_CIPHER_CTX_reset_ptr diff --git a/src/native/libs/System.Security.Cryptography.Native/osslcompat_30.h b/src/native/libs/System.Security.Cryptography.Native/osslcompat_30.h index f7de24624eb98a..095dd3176e7aa4 100644 --- a/src/native/libs/System.Security.Cryptography.Native/osslcompat_30.h +++ b/src/native/libs/System.Security.Cryptography.Native/osslcompat_30.h @@ -18,7 +18,6 @@ typedef struct ossl_lib_ctx_st OSSL_LIB_CTX; void ERR_new(void); void ERR_set_debug(const char *file, int line, const char *func); void ERR_set_error(int lib, int reason, const char *fmt, ...); -int EVP_CIPHER_CTX_get_original_iv(EVP_CIPHER_CTX *ctx, void *buf, size_t len); int EVP_CIPHER_get_nid(const EVP_CIPHER *e); int EVP_MD_get_size(const EVP_MD* md); int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX* ctx, int bits); diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp_cipher.c b/src/native/libs/System.Security.Cryptography.Native/pal_evp_cipher.c index 351a2cd1ca8cc7..ae2c0df5aae02c 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp_cipher.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp_cipher.c @@ -123,36 +123,12 @@ void CryptoNative_EvpCipherDestroy(EVP_CIPHER_CTX* ctx) } } -int32_t CryptoNative_EvpCipherReset(EVP_CIPHER_CTX* ctx) -{ - // EVP_CipherInit_ex with all nulls preserves the algorithm, resets the IV, - // and maintains the key. - // - // The only thing that you can't do is change the encryption direction, - // that requires passing the key and IV in again. - // - // But since we have a different object returned for CreateEncryptor - // and CreateDecryptor we don't need to worry about that. - uint8_t* iv = NULL; - -#ifdef NEED_OPENSSL_3_0 - // OpenSSL 3.0 alpha 13 does not properly reset the IV. Work around that by - // asking for the original IV, and giving it back. - uint8_t tmpIV[EVP_MAX_IV_LENGTH]; - - // If we're direct against 3.0, or we're portable and found 3.0 - if (API_EXISTS(EVP_CIPHER_CTX_get_original_iv)) - { - if (EVP_CIPHER_CTX_get_original_iv(ctx, tmpIV, sizeof(tmpIV)) != 1) - { - return 0; - } - - iv = tmpIV; - } -#endif +int32_t CryptoNative_EvpCipherReset(EVP_CIPHER_CTX* ctx, uint8_t* pIv, int32_t cIv) +{ + assert(cIv >= 0 && (pIv != NULL || cIv == 0)); + (void)cIv; - return EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, KEEP_CURRENT_DIRECTION); + return EVP_CipherInit_ex(ctx, NULL, NULL, NULL, pIv, KEEP_CURRENT_DIRECTION); } int32_t CryptoNative_EvpCipherCtxSetPadding(EVP_CIPHER_CTX* x, int32_t padding) diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp_cipher.h b/src/native/libs/System.Security.Cryptography.Native/pal_evp_cipher.h index e9586fa93e9587..0899cea9dbe3af 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp_cipher.h +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp_cipher.h @@ -35,7 +35,7 @@ EvpCipherReset Resets an EVP_CIPHER_CTX instance for a new computation. */ -PALEXPORT int32_t CryptoNative_EvpCipherReset(EVP_CIPHER_CTX* ctx); +PALEXPORT int32_t CryptoNative_EvpCipherReset(EVP_CIPHER_CTX* ctx, uint8_t* pIv, int32_t cIv); /* Function: