// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using Microsoft.AspNet.DataProtection.AuthenticatedEncryption; namespace Microsoft.AspNet.DataProtection.Cng { /// /// Base class used for all CNG-related authentication encryption operations. /// internal unsafe abstract class CngAuthenticatedEncryptorBase : IOptimizedAuthenticatedEncryptor, IDisposable { public byte[] Decrypt(ArraySegment ciphertext, ArraySegment additionalAuthenticatedData) { // This wrapper simply converts ArraySegment to byte* and calls the impl method. // Input validation ciphertext.Validate(); additionalAuthenticatedData.Validate(); byte dummy; // used only if plaintext or AAD is empty, since otherwise 'fixed' returns null pointer fixed (byte* pbCiphertextArray = ciphertext.Array) { fixed (byte* pbAdditionalAuthenticatedDataArray = additionalAuthenticatedData.Array) { try { return DecryptImpl( pbCiphertext: (pbCiphertextArray != null) ? &pbCiphertextArray[ciphertext.Offset] : &dummy, cbCiphertext: (uint)ciphertext.Count, pbAdditionalAuthenticatedData: (pbAdditionalAuthenticatedDataArray != null) ? &pbAdditionalAuthenticatedDataArray[additionalAuthenticatedData.Offset] : &dummy, cbAdditionalAuthenticatedData: (uint)additionalAuthenticatedData.Count); } catch (Exception ex) when (ex.RequiresHomogenization()) { // Homogenize to CryptographicException. throw Error.CryptCommon_GenericError(ex); } } } } protected abstract byte[] DecryptImpl(byte* pbCiphertext, uint cbCiphertext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData); public abstract void Dispose(); public byte[] Encrypt(ArraySegment plaintext, ArraySegment additionalAuthenticatedData) { return Encrypt(plaintext, additionalAuthenticatedData, 0, 0); } public byte[] Encrypt(ArraySegment plaintext, ArraySegment additionalAuthenticatedData, uint preBufferSize, uint postBufferSize) { // This wrapper simply converts ArraySegment to byte* and calls the impl method. // Input validation plaintext.Validate(); additionalAuthenticatedData.Validate(); byte dummy; // used only if plaintext or AAD is empty, since otherwise 'fixed' returns null pointer fixed (byte* pbPlaintextArray = plaintext.Array) { fixed (byte* pbAdditionalAuthenticatedDataArray = additionalAuthenticatedData.Array) { try { return EncryptImpl( pbPlaintext: (pbPlaintextArray != null) ? &pbPlaintextArray[plaintext.Offset] : &dummy, cbPlaintext: (uint)plaintext.Count, pbAdditionalAuthenticatedData: (pbAdditionalAuthenticatedDataArray != null) ? &pbAdditionalAuthenticatedDataArray[additionalAuthenticatedData.Offset] : &dummy, cbAdditionalAuthenticatedData: (uint)additionalAuthenticatedData.Count, cbPreBuffer: preBufferSize, cbPostBuffer: postBufferSize); } catch (Exception ex) when (ex.RequiresHomogenization()) { // Homogenize to CryptographicException. throw Error.CryptCommon_GenericError(ex); } } } } protected abstract byte[] EncryptImpl(byte* pbPlaintext, uint cbPlaintext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData, uint cbPreBuffer, uint cbPostBuffer); } }