File: src\libraries\Common\src\Interop\Unix\System.Security.Cryptography.Native\Interop.Encode.cs
Web Access
Project: src\src\libraries\System.Security.Cryptography\src\System.Security.Cryptography.csproj (System.Security.Cryptography)
// 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);
        }
    }
}