File: src\libraries\Common\src\Interop\Unix\System.Security.Cryptography.Native\Interop.EvpPkey.SlhDsa.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.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using Microsoft.Win32.SafeHandles;
 
internal static partial class Interop
{
    internal static partial class Crypto
    {
        [LibraryImport(Libraries.CryptoNative, StringMarshalling = StringMarshalling.Utf8)]
        private static partial SafeEvpPKeyHandle CryptoNative_SlhDsaGenerateKey(string keyType);
 
        internal static SafeEvpPKeyHandle SlhDsaGenerateKey(string algorithmName)
        {
            SafeEvpPKeyHandle handle = CryptoNative_SlhDsaGenerateKey(algorithmName);
            Debug.Assert(handle != null, "handle != null");
 
            if (handle.IsInvalid)
            {
                Exception ex = Interop.Crypto.CreateOpenSslCryptographicException();
                handle.Dispose();
                throw ex;
            }
 
            return handle;
        }
 
        // Must be kept in sync with PalSlhDsaId in native shim.
        internal enum PalSlhDsaAlgorithmId
        {
            Unknown = 0,
            SlhDsaSha2_128s = 1,
            SlhDsaShake128s = 2,
            SlhDsaSha2_128f = 3,
            SlhDsaShake128f = 4,
            SlhDsaSha2_192s = 5,
            SlhDsaShake192s = 6,
            SlhDsaSha2_192f = 7,
            SlhDsaShake192f = 8,
            SlhDsaSha2_256s = 9,
            SlhDsaShake256s = 10,
            SlhDsaSha2_256f = 11,
            SlhDsaShake256f = 12,
        }
 
        [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SlhDsaGetPalId")]
        private static partial int CryptoNative_SlhDsaGetPalId(
            SafeEvpPKeyHandle slhDsa,
            out PalSlhDsaAlgorithmId slhDsaId);
 
        internal static PalSlhDsaAlgorithmId GetSlhDsaAlgorithmId(SafeEvpPKeyHandle key)
        {
            const int Success = 1;
            const int Fail = 0;
            int result = CryptoNative_SlhDsaGetPalId(key, out PalSlhDsaAlgorithmId slhDsaId);
 
            return result switch
            {
                Success => slhDsaId,
                Fail => throw CreateOpenSslCryptographicException(),
                int other => throw FailThrow(other),
            };
 
            static Exception FailThrow(int result)
            {
                Debug.Fail($"Unexpected return value {result} from {nameof(CryptoNative_SlhDsaGetPalId)}.");
                return new CryptographicException();
            }
        }
 
        [LibraryImport(Libraries.CryptoNative)]
        private static partial int CryptoNative_SlhDsaSignPure(
            SafeEvpPKeyHandle pkey, IntPtr extraHandle,
            ReadOnlySpan<byte> msg, int msgLength,
            ReadOnlySpan<byte> context, int contextLength,
            Span<byte> destination, int destinationLength);
 
        internal static void SlhDsaSignPure(
            SafeEvpPKeyHandle pkey,
            ReadOnlySpan<byte> msg,
            ReadOnlySpan<byte> context,
            Span<byte> destination)
        {
            int ret = CryptoNative_SlhDsaSignPure(
                pkey, GetExtraHandle(pkey),
                msg, msg.Length,
                context, context.Length,
                destination, destination.Length);
 
            if (ret != 1)
            {
                throw Interop.Crypto.CreateOpenSslCryptographicException();
            }
        }
 
        [LibraryImport(Libraries.CryptoNative)]
        private static partial int CryptoNative_SlhDsaVerifyPure(
            SafeEvpPKeyHandle pkey, IntPtr extraHandle,
            ReadOnlySpan<byte> msg, int msgLength,
            ReadOnlySpan<byte> context, int contextLength,
            ReadOnlySpan<byte> signature, int signatureLength);
 
        internal static bool SlhDsaVerifyPure(
            SafeEvpPKeyHandle pkey,
            ReadOnlySpan<byte> msg,
            ReadOnlySpan<byte> context,
            ReadOnlySpan<byte> signature)
        {
            int ret = CryptoNative_SlhDsaVerifyPure(
                pkey, GetExtraHandle(pkey),
                msg, msg.Length,
                context, context.Length,
                signature, signature.Length);
 
            if (ret == 1)
            {
                return true;
            }
            else if (ret == 0)
            {
                return false;
            }
            else
            {
                throw Interop.Crypto.CreateOpenSslCryptographicException();
            }
        }
 
        [LibraryImport(Libraries.CryptoNative)]
        private static partial int CryptoNative_SlhDsaSignPreEncoded(
            SafeEvpPKeyHandle pkey, IntPtr extraHandle,
            ReadOnlySpan<byte> msg, int msgLength,
            Span<byte> destination, int destinationLength);
 
        internal static void SlhDsaSignPreEncoded(
            SafeEvpPKeyHandle pkey,
            ReadOnlySpan<byte> msg,
            Span<byte> destination)
        {
            int ret = CryptoNative_SlhDsaSignPreEncoded(
                pkey, GetExtraHandle(pkey),
                msg, msg.Length,
                destination, destination.Length);
 
            if (ret != 1)
            {
                throw Interop.Crypto.CreateOpenSslCryptographicException();
            }
        }
 
        [LibraryImport(Libraries.CryptoNative)]
        private static partial int CryptoNative_SlhDsaVerifyPreEncoded(
            SafeEvpPKeyHandle pkey, IntPtr extraHandle,
            ReadOnlySpan<byte> msg, int msgLength,
            ReadOnlySpan<byte> signature, int signatureLength);
 
        internal static bool SlhDsaVerifyPreEncoded(
            SafeEvpPKeyHandle pkey,
            ReadOnlySpan<byte> msg,
            ReadOnlySpan<byte> signature)
        {
            int ret = CryptoNative_SlhDsaVerifyPreEncoded(
                pkey, GetExtraHandle(pkey),
                msg, msg.Length,
                signature, signature.Length);
 
            if (ret == 1)
            {
                return true;
            }
            else if (ret == 0)
            {
                return false;
            }
            else
            {
                throw Interop.Crypto.CreateOpenSslCryptographicException();
            }
        }
 
        [LibraryImport(Libraries.CryptoNative)]
        private static partial int CryptoNative_SlhDsaExportSecretKey(SafeEvpPKeyHandle pkey, Span<byte> destination, int destinationLength);
 
        [LibraryImport(Libraries.CryptoNative)]
        private static partial int CryptoNative_SlhDsaExportPublicKey(SafeEvpPKeyHandle pkey, Span<byte> destination, int destinationLength);
 
        internal static void SlhDsaExportSecretKey(SafeEvpPKeyHandle key, Span<byte> destination) =>
            Interop.Crypto.ExportKeyContents(key, destination, CryptoNative_SlhDsaExportSecretKey);
 
        internal static void SlhDsaExportPublicKey(SafeEvpPKeyHandle key, Span<byte> destination) =>
            Interop.Crypto.ExportKeyContents(key, destination, CryptoNative_SlhDsaExportPublicKey);
    }
}