|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
internal static partial class Interop
{
internal static partial class Crypto
{
internal delegate int GetEncodedSizeFunc<in THandle>(THandle handle);
internal delegate int EncodeFunc<in THandle>(THandle handle, byte[] buf);
internal static byte[] OpenSslEncode<THandle>(
GetEncodedSizeFunc<THandle> getSize,
EncodeFunc<THandle> encode,
THandle handle)
where THandle : SafeHandle
{
int size = getSize(handle);
if (size < 1)
{
throw CreateOpenSslCryptographicException();
}
byte[] data = new byte[size];
int size2 = encode(handle, data);
if (size2 < 1)
{
Debug.Fail(
$"{nameof(OpenSslEncode)}: {nameof(getSize)} succeeded ({size}) and {nameof(encode)} failed ({size2})");
// If it ever happens, ensure the error queue gets cleared.
// And since it didn't write the data, reporting an exception is good too.
throw CreateOpenSslCryptographicException();
}
Debug.Assert(size == size2);
return data;
}
internal static ArraySegment<byte> OpenSslRentEncode<THandle>(
GetEncodedSizeFunc<THandle> getSize,
EncodeFunc<THandle> encode,
THandle handle)
where THandle : SafeHandle
{
int size = getSize(handle);
if (size < 1)
{
throw CreateOpenSslCryptographicException();
}
byte[] data = CryptoPool.Rent(size);
int size2 = encode(handle, data);
if (size2 < 1)
{
Debug.Fail(
$"{nameof(OpenSslEncode)}: {nameof(getSize)} succeeded ({size}) and {nameof(encode)} failed ({size2})");
// Since we don't know what was written, assume it was secret and have the
// CryptoPool.Return clear the whole array.
// (It doesn't matter much, since we're behind Debug.Fail)
CryptoPool.Return(data);
// If it ever happens, ensure the error queue gets cleared.
// And since it didn't write the data, reporting an exception is good too.
throw CreateOpenSslCryptographicException();
}
Debug.Assert(size == size2);
return new ArraySegment<byte>(data, 0, size2);
}
}
}
|