Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,34 @@ internal static bool EvpCipherFinalEx(
return EvpCipherFinalEx(ctx, ref MemoryMarshal.GetReference(output), out bytesWritten);
}

[LibraryImport(Libraries.AndroidCryptoNative, EntryPoint = "AndroidCryptoNative_AeadCipherFinalEx")]
[return: MarshalAs(UnmanagedType.Bool)]
private static unsafe partial bool EvpAeadCipherFinalEx(
SafeEvpCipherCtxHandle ctx,
byte* outm,
out int outl,
[MarshalAs(UnmanagedType.Bool)] out bool authTagMismatch);
Comment thread
vcsjones marked this conversation as resolved.

internal static unsafe bool EvpAeadCipherFinalEx(
SafeEvpCipherCtxHandle ctx,
Span<byte> output,
out int bytesWritten,
out bool authTagMismatch)
{
scoped Span<byte> notNullOutput = output;

// We can't pass null down to the native shim, so create a valid pointer if we have an empty span.
if (notNullOutput.IsEmpty)
{
notNullOutput = (stackalloc byte[1]).Slice(1);
}

fixed (byte* pOutput = &MemoryMarshal.GetReference(notNullOutput))
{
return EvpAeadCipherFinalEx(ctx, pOutput, out bytesWritten, out authTagMismatch);
}
}

[LibraryImport(Libraries.AndroidCryptoNative, EntryPoint = "AndroidCryptoNative_CipherSetTagLength")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool CipherSetTagLength(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,12 @@ protected AsymmetricSignatureFormatter() { }
public abstract void SetHashAlgorithm(string strName);
public abstract void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key);
}
public sealed partial class AuthenticationTagMismatchException : System.Security.Cryptography.CryptographicException
{
public AuthenticationTagMismatchException() { }
public AuthenticationTagMismatchException(string? message) { }
public AuthenticationTagMismatchException(string? message, System.Exception? inner) { }
}
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@
<Compile Include="System\Security\Cryptography\AsymmetricKeyExchangeFormatter.cs" />
<Compile Include="System\Security\Cryptography\AsymmetricSignatureDeformatter.cs" />
<Compile Include="System\Security\Cryptography\AsymmetricSignatureFormatter.cs" />
<Compile Include="System\Security\Cryptography\AuthenticationTagMismatchException.cs" />
<Compile Include="System\Security\Cryptography\Base64Transforms.cs" />
<Compile Include="System\Security\Cryptography\BasicSymmetricCipher.cs" />
<Compile Include="System\Security\Cryptography\ChaCha20Poly1305.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public static unsafe void Decrypt(
CryptographicOperations.ZeroMemory(plaintext);
}

throw new CryptographicException(SR.Cryptography_AuthTagMismatch);
throw new AuthenticationTagMismatchException();
default:
throw CreateCryptographicException(ntStatus);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,13 @@ private void EncryptCore(
throw new CryptographicException();
}

if (!Interop.Crypto.EvpCipherFinalEx(
if (!Interop.Crypto.EvpAeadCipherFinalEx(
ctx,
ciphertextAndTag.Slice(ciphertextBytesWritten),
out int bytesWritten))
out int bytesWritten,
out bool authTagMismatch))
{
Debug.Assert(!authTagMismatch);
throw new CryptographicException();
}

Expand Down Expand Up @@ -141,13 +143,20 @@ private void DecryptCore(

plaintextBytesWritten += bytesWritten;

if (!Interop.Crypto.EvpCipherFinalEx(
if (!Interop.Crypto.EvpAeadCipherFinalEx(
ctx,
plaintext.Slice(plaintextBytesWritten),
out bytesWritten))
out bytesWritten,
out bool authTagMismatch))
{
CryptographicOperations.ZeroMemory(plaintext);
throw new CryptographicException(SR.Cryptography_AuthTagMismatch);

if (authTagMismatch)
{
throw new AuthenticationTagMismatchException();
}

throw new CryptographicException(SR.Arg_CryptographyException);
Comment thread
vcsjones marked this conversation as resolved.
}

plaintextBytesWritten += bytesWritten;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ private void DecryptCore(
if (!Interop.Crypto.EvpCipherUpdate(ctx, plaintext, out int plaintextBytesWritten, ciphertext))
{
plaintext.Clear();
throw new CryptographicException(SR.Cryptography_AuthTagMismatch);
throw new AuthenticationTagMismatchException();
}

if (plaintextBytesWritten != plaintext.Length)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,13 @@ private void EncryptCore(
throw new CryptographicException();
}

if (!Interop.Crypto.EvpCipherFinalEx(
if (!Interop.Crypto.EvpAeadCipherFinalEx(
_ctxHandle,
ciphertextAndTag.Slice(ciphertextBytesWritten),
out int bytesWritten))
out int bytesWritten,
out bool authTagMismatch))
{
Debug.Assert(!authTagMismatch);
throw new CryptographicException();
}

Expand Down Expand Up @@ -141,13 +143,20 @@ private void DecryptCore(

plaintextBytesWritten += bytesWritten;

if (!Interop.Crypto.EvpCipherFinalEx(
if (!Interop.Crypto.EvpAeadCipherFinalEx(
_ctxHandle,
plaintext.Slice(plaintextBytesWritten),
out bytesWritten))
out bytesWritten,
out bool authTagMismatch))
{
CryptographicOperations.ZeroMemory(plaintext);
throw new CryptographicException(SR.Cryptography_AuthTagMismatch);

if (authTagMismatch)
{
throw new AuthenticationTagMismatchException();
}

throw new CryptographicException(SR.Arg_CryptographyException);
}

plaintextBytesWritten += bytesWritten;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ private void DecryptCore(
out int bytesWritten))
{
CryptographicOperations.ZeroMemory(plaintext);
throw new CryptographicException(SR.Cryptography_AuthTagMismatch);
throw new AuthenticationTagMismatchException();
}

plaintextBytesWritten += bytesWritten;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Security.Cryptography
{
/// <summary>
/// The exception that is thrown when a decryption operation with an authenticated cipher
/// has an authentication tag mismatch.
/// </summary>
public sealed class AuthenticationTagMismatchException : CryptographicException
{
/// <summary>
/// Initializes a new instance of the <see cref="AuthenticationTagMismatchException" /> class with default
/// properties.
/// </summary>
public AuthenticationTagMismatchException() : base(SR.Cryptography_AuthTagMismatch)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="AuthenticationTagMismatchException" /> class with a specified
/// error message.
/// </summary>
/// <param name="message">
/// The error message that explains the reason for the exception.
/// </param>
public AuthenticationTagMismatchException(string? message) : base(message)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="AuthenticationTagMismatchException" /> class with a specified
/// error message and a reference to the inner exception that is the cause of this exception.
/// </summary>
/// <param name="message">
/// The error message that explains the reason for the exception.
/// </param>
/// <param name="inner">
/// The exception that is the cause of the current exception. If the parameter is not
/// <see langword="null" />, the current exception is raised in a catch block that handles the inner exception.
/// </param>
public AuthenticationTagMismatchException(string? message, Exception? inner)
: base(message, inner)
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,13 @@ private void EncryptCore(
throw new CryptographicException();
}

if (!Interop.Crypto.EvpCipherFinalEx(
if (!Interop.Crypto.EvpAeadCipherFinalEx(
_ctxHandle,
ciphertextAndTag.Slice(ciphertextBytesWritten),
out int bytesWritten))
out int bytesWritten,
out bool authTagMismatch))
{
Debug.Assert(!authTagMismatch);
throw new CryptographicException();
}

Expand Down Expand Up @@ -133,13 +135,20 @@ private void DecryptCore(

plaintextBytesWritten += bytesWritten;

if (!Interop.Crypto.EvpCipherFinalEx(
if (!Interop.Crypto.EvpAeadCipherFinalEx(
_ctxHandle,
plaintext.Slice(plaintextBytesWritten),
out bytesWritten))
out bytesWritten,
out bool authTagMismatch))
{
CryptographicOperations.ZeroMemory(plaintext);
throw new CryptographicException(SR.Cryptography_AuthTagMismatch);

if (authTagMismatch)
{
throw new AuthenticationTagMismatchException();
}

throw new CryptographicException(SR.Arg_CryptographyException);
}

plaintextBytesWritten += bytesWritten;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ private void DecryptCore(
out int bytesWritten))
{
CryptographicOperations.ZeroMemory(plaintext);
throw new CryptographicException(SR.Cryptography_AuthTagMismatch);
throw new AuthenticationTagMismatchException();
}

plaintextBytesWritten += bytesWritten;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static void EncryptTamperAADDecrypt(int dataLength, int additionalDataLen
additionalData[0] ^= 1;

byte[] decrypted = new byte[dataLength];
Assert.Throws<CryptographicException>(
Assert.Throws<AuthenticationTagMismatchException>(
() => aesCcm.Decrypt(nonce, ciphertext, tag, decrypted, additionalData));
}
}
Expand Down Expand Up @@ -305,7 +305,7 @@ public static void InplaceEncryptTamperTagDecrypt()

tag[0] ^= 1;

Assert.Throws<CryptographicException>(
Assert.Throws<AuthenticationTagMismatchException>(
() => aesCcm.Decrypt(nonce, data, tag, data));
Assert.Equal(new byte[data.Length], data);
}
Expand Down Expand Up @@ -347,7 +347,7 @@ public static void AesCcmNistTestsTamperTag(AEADTest testCase)

byte[] plaintext = new byte[testCase.Plaintext.Length];
RandomNumberGenerator.Fill(plaintext);
Assert.Throws<CryptographicException>(
Assert.Throws<AuthenticationTagMismatchException>(
() => aesCcm.Decrypt(testCase.Nonce, ciphertext, tag, plaintext, testCase.AssociatedData));
Assert.Equal(new byte[plaintext.Length], plaintext);
}
Expand All @@ -370,7 +370,7 @@ public static void AesCcmNistTestsTamperCiphertext(AEADTest testCase)

byte[] plaintext = new byte[testCase.Plaintext.Length];
RandomNumberGenerator.Fill(plaintext);
Assert.Throws<CryptographicException>(
Assert.Throws<AuthenticationTagMismatchException>(
() => aesCcm.Decrypt(testCase.Nonce, ciphertext, tag, plaintext, testCase.AssociatedData));
Assert.Equal(new byte[plaintext.Length], plaintext);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static void EncryptTamperAADDecrypt(int dataLength, int additionalDataLen
additionalData[0] ^= 1;

byte[] decrypted = new byte[dataLength];
Assert.Throws<CryptographicException>(
Assert.Throws<AuthenticationTagMismatchException>(
() => aesGcm.Decrypt(nonce, ciphertext, tag, decrypted, additionalData));
}
}
Expand Down Expand Up @@ -312,7 +312,7 @@ public static void InplaceEncryptTamperTagDecrypt()

tag[0] ^= 1;

Assert.Throws<CryptographicException>(
Assert.Throws<AuthenticationTagMismatchException>(
() => aesGcm.Decrypt(nonce, data, tag, data));
Assert.Equal(new byte[data.Length], data);
}
Expand Down Expand Up @@ -354,7 +354,7 @@ public static void AesGcmNistTestsTamperTag(AEADTest testCase)

byte[] plaintext = new byte[testCase.Plaintext.Length];
RandomNumberGenerator.Fill(plaintext);
Assert.Throws<CryptographicException>(
Assert.Throws<AuthenticationTagMismatchException>(
() => aesGcm.Decrypt(testCase.Nonce, ciphertext, tag, plaintext, testCase.AssociatedData));
Assert.Equal(new byte[plaintext.Length], plaintext);
}
Expand All @@ -377,7 +377,7 @@ public static void AesGcmNistTestsTamperCiphertext(AEADTest testCase)

byte[] plaintext = new byte[testCase.Plaintext.Length];
RandomNumberGenerator.Fill(plaintext);
Assert.Throws<CryptographicException>(
Assert.Throws<AuthenticationTagMismatchException>(
() => aesGcm.Decrypt(testCase.Nonce, ciphertext, tag, plaintext, testCase.AssociatedData));
Assert.Equal(new byte[plaintext.Length], plaintext);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public static void EncryptTamperAADDecrypt(int dataLength, int additionalDataLen
additionalData[0] ^= 1;

byte[] decrypted = new byte[dataLength];
Assert.Throws<CryptographicException>(
Assert.Throws<AuthenticationTagMismatchException>(
() => chaChaPoly.Decrypt(nonce, ciphertext, tag, decrypted, additionalData));
}
}
Expand Down Expand Up @@ -271,7 +271,7 @@ public static void InplaceEncryptTamperTagDecrypt()

tag[0] ^= 1;

Assert.Throws<CryptographicException>(
Assert.Throws<AuthenticationTagMismatchException>(
() => chaChaPoly.Decrypt(nonce, data, tag, data));
Assert.Equal(new byte[data.Length], data);
}
Expand Down Expand Up @@ -310,7 +310,7 @@ public static void Rfc8439TestsTamperTag(AEADTest testCase)
tag[0] ^= 1;

byte[] plaintext = RandomNumberGenerator.GetBytes(testCase.Plaintext.Length);
Assert.Throws<CryptographicException>(
Assert.Throws<AuthenticationTagMismatchException>(
() => chaChaPoly.Decrypt(testCase.Nonce, ciphertext, tag, plaintext, testCase.AssociatedData));
Assert.Equal(new byte[plaintext.Length], plaintext);
}
Expand Down
Loading