{
internal static partial class AppleCrypto
{
+ private static int AppleCryptoNative_SecKeyImportEphemeral(
+ ReadOnlySpan<byte> pbKeyBlob,
+ int isPrivateKey,
+ out SafeSecKeyRefHandle ppKeyOut,
+ out int pOSStatus) =>
+ AppleCryptoNative_SecKeyImportEphemeral(
+ ref MemoryMarshal.GetReference(pbKeyBlob),
+ pbKeyBlob.Length,
+ isPrivateKey,
+ out ppKeyOut,
+ out pOSStatus);
+
[DllImport(Libraries.AppleCryptoNative)]
private static extern int AppleCryptoNative_SecKeyImportEphemeral(
- byte[] pbKeyBlob,
+ ref byte pbKeyBlob,
int cbKeyBlob,
int isPrivateKey,
out SafeSecKeyRefHandle ppKeyOut,
private static int AppleCryptoNative_GenerateSignature(
SafeSecKeyRefHandle privateKey,
ReadOnlySpan<byte> pbDataHash,
- int cbDataHash,
out SafeCFDataHandle pSignatureOut,
out SafeCFErrorHandle pErrorOut) =>
AppleCryptoNative_GenerateSignature(
- privateKey, ref MemoryMarshal.GetReference(pbDataHash), cbDataHash, out pSignatureOut, out pErrorOut);
+ privateKey,
+ ref MemoryMarshal.GetReference(pbDataHash),
+ pbDataHash.Length,
+ out pSignatureOut,
+ out pErrorOut);
[DllImport(Libraries.AppleCryptoNative)]
private static extern int AppleCryptoNative_GenerateSignature(
private static int AppleCryptoNative_GenerateSignatureWithHashAlgorithm(
SafeSecKeyRefHandle privateKey,
ReadOnlySpan<byte> pbDataHash,
- int cbDataHash,
PAL_HashAlgorithm hashAlgorithm,
out SafeCFDataHandle pSignatureOut,
out SafeCFErrorHandle pErrorOut) =>
AppleCryptoNative_GenerateSignatureWithHashAlgorithm(
- privateKey, ref MemoryMarshal.GetReference(pbDataHash), cbDataHash, hashAlgorithm, out pSignatureOut, out pErrorOut);
+ privateKey,
+ ref MemoryMarshal.GetReference(pbDataHash),
+ pbDataHash.Length,
+ hashAlgorithm,
+ out pSignatureOut,
+ out pErrorOut);
[DllImport(Libraries.AppleCryptoNative)]
private static extern int AppleCryptoNative_GenerateSignatureWithHashAlgorithm(
private static int AppleCryptoNative_VerifySignature(
SafeSecKeyRefHandle publicKey,
ReadOnlySpan<byte> pbDataHash,
- int cbDataHash,
ReadOnlySpan<byte> pbSignature,
- int cbSignature,
out SafeCFErrorHandle pErrorOut) =>
AppleCryptoNative_VerifySignature(
publicKey,
ref MemoryMarshal.GetReference(pbDataHash),
- cbDataHash,
+ pbDataHash.Length,
ref MemoryMarshal.GetReference(pbSignature),
- cbSignature,
+ pbSignature.Length,
out pErrorOut);
[DllImport(Libraries.AppleCryptoNative)]
private static int AppleCryptoNative_VerifySignatureWithHashAlgorithm(
SafeSecKeyRefHandle publicKey,
ReadOnlySpan<byte> pbDataHash,
- int cbDataHash,
ReadOnlySpan<byte> pbSignature,
- int cbSignature,
PAL_HashAlgorithm hashAlgorithm,
out SafeCFErrorHandle pErrorOut) =>
AppleCryptoNative_VerifySignatureWithHashAlgorithm(
publicKey,
ref MemoryMarshal.GetReference(pbDataHash),
- cbDataHash,
+ pbDataHash.Length,
ref MemoryMarshal.GetReference(pbSignature),
- cbSignature,
+ pbSignature.Length,
hashAlgorithm,
out pErrorOut);
}
}
- internal static SafeSecKeyRefHandle ImportEphemeralKey(byte[] keyBlob, bool hasPrivateKey)
+ internal static SafeSecKeyRefHandle ImportEphemeralKey(ReadOnlySpan<byte> keyBlob, bool hasPrivateKey)
{
Debug.Assert(keyBlob != null);
int ret = AppleCryptoNative_SecKeyImportEphemeral(
keyBlob,
- keyBlob.Length,
hasPrivateKey ? 1 : 0,
out keyHandle,
out osStatus);
AppleCryptoNative_GenerateSignature(
privateKey,
source,
- source.Length,
out signature,
out error));
}
AppleCryptoNative_GenerateSignatureWithHashAlgorithm(
privateKey,
source,
- source.Length,
hashAlgorithm,
out signature,
out error));
delegate (ReadOnlySpan<byte> innerSource, out SafeCFDataHandle outputHandle, out SafeCFErrorHandle errorHandle)
{
return AppleCryptoNative_GenerateSignatureWithHashAlgorithm(
- privateKey, innerSource, innerSource.Length, hashAlgorithm, out outputHandle, out errorHandle);
+ privateKey, innerSource, hashAlgorithm, out outputHandle, out errorHandle);
});
}
int ret = AppleCryptoNative_VerifySignature(
publicKey,
dataHash,
- dataHash.Length,
signature,
- signature.Length,
out error);
const int True = 1;
int ret = AppleCryptoNative_VerifySignatureWithHashAlgorithm(
publicKey,
dataHash,
- dataHash.Length,
signature,
- signature.Length,
hashAlgorithm,
out error);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_RsaDestroy")]
internal static extern void RsaDestroy(IntPtr rsa);
+ internal static SafeRsaHandle DecodeRsaPublicKey(ReadOnlySpan<byte> buf) =>
+ DecodeRsaPublicKey(ref MemoryMarshal.GetReference(buf), buf.Length);
+
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeRsaPublicKey")]
- internal static extern SafeRsaHandle DecodeRsaPublicKey(byte[] buf, int len);
+ private static extern SafeRsaHandle DecodeRsaPublicKey(ref byte buf, int len);
internal static int RsaPublicEncrypt(
int flen,
out key);
}
+ internal static ReadOnlyMemory<byte> ReadSubjectPublicKeyInfo(
+ ReadOnlyMemory<byte> source,
+ out int bytesRead)
+ {
+ return KeyFormatHelper.ReadSubjectPublicKeyInfo(
+ s_validOids,
+ source,
+ out bytesRead);
+ }
+
internal static void ReadPkcs8(
ReadOnlySpan<byte> source,
out int bytesRead,
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Buffers;
using System.Diagnostics;
using System.IO;
using System.Numerics;
+using System.Runtime.InteropServices;
using System.Security.Cryptography.Apple;
using System.Security.Cryptography.Asn1;
using Internal.Cryptography;
private static SafeSecKeyRefHandle ImportKey(DSAParameters parameters)
{
- bool hasPrivateKey = parameters.X != null;
- byte[] blob;
-
- if (hasPrivateKey)
+ if (parameters.X != null)
{
- Debug.Assert(parameters.X != null);
-
// DSAPrivateKey ::= SEQUENCE(
// version INTEGER,
// p INTEGER,
privateKeyWriter.WriteKeyParameterInteger(parameters.Y);
privateKeyWriter.WriteKeyParameterInteger(parameters.X);
privateKeyWriter.PopSequence();
- blob = privateKeyWriter.Encode();
+ return Interop.AppleCrypto.ImportEphemeralKey(privateKeyWriter.EncodeAsSpan(), true);
}
}
else
{
using (AsnWriter writer = DSAKeyFormatHelper.WriteSubjectPublicKeyInfo(parameters))
{
- blob = writer.Encode();
+ return Interop.AppleCrypto.ImportEphemeralKey(writer.EncodeAsSpan(), false);
}
}
+ }
+
+ public override unsafe void ImportSubjectPublicKeyInfo(
+ ReadOnlySpan<byte> source,
+ out int bytesRead)
+ {
+ fixed (byte* ptr = &MemoryMarshal.GetReference(source))
+ {
+ using (MemoryManager<byte> manager = new PointerMemoryManager<byte>(ptr, source.Length))
+ {
+ // Validate the DER value and get the number of bytes.
+ DSAKeyFormatHelper.ReadSubjectPublicKeyInfo(
+ manager.Memory,
+ out int localRead);
- return Interop.AppleCrypto.ImportEphemeralKey(blob, hasPrivateKey);
+ SafeSecKeyRefHandle publicKey = Interop.AppleCrypto.ImportEphemeralKey(source.Slice(0, localRead), false);
+ SetKey(SecKeyPair.PublicOnly(publicKey));
+
+ bytesRead = localRead;
+ }
+ }
}
public override byte[] CreateSignature(byte[] rgbHash)
KeySizeValue = _ecc.ImportParameters(parameters);
}
+ public override void ImportSubjectPublicKeyInfo(
+ ReadOnlySpan<byte> source,
+ out int bytesRead)
+ {
+ KeySizeValue = _ecc.ImportSubjectPublicKeyInfo(source, out bytesRead);
+ }
+
public override void GenerateKey(ECCurve curve)
{
KeySizeValue = _ecc.GenerateKey(curve);
out key);
}
+ internal static ReadOnlyMemory<byte> ReadSubjectPublicKeyInfo(
+ ReadOnlyMemory<byte> source,
+ out int bytesRead)
+ {
+ return KeyFormatHelper.ReadSubjectPublicKeyInfo(
+ s_validOids,
+ source,
+ out bytesRead);
+ }
+
internal static void ReadEncryptedPkcs8(
ReadOnlySpan<byte> source,
ReadOnlySpan<char> password,
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Buffers;
using System.Diagnostics;
+using System.Runtime.InteropServices;
using System.Security.Cryptography.Apple;
using System.Security.Cryptography.Asn1;
using Internal.Cryptography;
}
}
- public int ImportParameters(ECParameters parameters)
+ internal int ImportParameters(ECParameters parameters)
{
parameters.Validate();
private static SafeSecKeyRefHandle ImportKey(ECParameters parameters)
{
- bool isPrivateKey = parameters.D != null;
- byte[] blob;
-
- if (isPrivateKey)
+ if (parameters.D != null)
{
using (AsnWriter privateKey = EccKeyFormatHelper.WriteECPrivateKey(parameters))
{
- blob = privateKey.Encode();
+ return Interop.AppleCrypto.ImportEphemeralKey(privateKey.EncodeAsSpan(), true);
}
}
else
{
using (AsnWriter publicKey = EccKeyFormatHelper.WriteSubjectPublicKeyInfo(parameters))
{
- blob = publicKey.Encode();
+ return Interop.AppleCrypto.ImportEphemeralKey(publicKey.EncodeAsSpan(), false);
}
}
+ }
+
+ internal unsafe int ImportSubjectPublicKeyInfo(
+ ReadOnlySpan<byte> source,
+ out int bytesRead)
+ {
+ fixed (byte* ptr = &MemoryMarshal.GetReference(source))
+ {
+ using (MemoryManager<byte> manager = new PointerMemoryManager<byte>(ptr, source.Length))
+ {
+ // Validate the DER value and get the number of bytes.
+ EccKeyFormatHelper.ReadSubjectPublicKeyInfo(
+ manager.Memory,
+ out int localRead);
- return Interop.AppleCrypto.ImportEphemeralKey(blob, isPrivateKey);
+ SafeSecKeyRefHandle publicKey = Interop.AppleCrypto.ImportEphemeralKey(source.Slice(0, localRead), false);
+ SecKeyPair newKeys = SecKeyPair.PublicOnly(publicKey);
+ int size = GetKeySize(newKeys);
+ SetKey(newKeys);
+
+ bytesRead = localRead;
+ return size;
+ }
+ }
}
}
}
using System.Buffers;
using System.Diagnostics;
using System.IO;
-
+using System.Runtime.InteropServices;
+using System.Security.Cryptography.Asn1;
using Microsoft.Win32.SafeHandles;
using Internal.Cryptography;
ForceSetKeySize(BitsPerByte * Interop.Crypto.RsaSize(key));
}
+ public override unsafe void ImportRSAPublicKey(ReadOnlySpan<byte> source, out int bytesRead)
+ {
+ fixed (byte* ptr = &MemoryMarshal.GetReference(source))
+ {
+ using (MemoryManager<byte> manager = new PointerMemoryManager<byte>(ptr, source.Length))
+ {
+ AsnReader reader = new AsnReader(manager.Memory, AsnEncodingRules.BER);
+ ReadOnlyMemory<byte> firstElement = reader.PeekEncodedValue();
+
+ SafeRsaHandle key = Interop.Crypto.DecodeRsaPublicKey(firstElement.Span);
+
+ Interop.Crypto.CheckValidOpenSslHandle(key);
+
+ FreeKey();
+ _key = new Lazy<SafeRsaHandle>(key);
+
+ // Use ForceSet instead of the property setter to ensure that LegalKeySizes doesn't interfere
+ // with the already loaded key.
+ ForceSetKeySize(BitsPerByte * Interop.Crypto.RsaSize(key));
+
+ bytesRead = firstElement.Length;
+ }
+ }
+ }
+
protected override void Dispose(bool disposing)
{
if (disposing)
using System.Diagnostics;
using System.IO;
using System.Numerics;
+using System.Runtime.InteropServices;
using System.Security.Cryptography.Apple;
using System.Security.Cryptography.Asn1;
using Internal.Cryptography;
}
}
+ public override unsafe void ImportSubjectPublicKeyInfo(
+ ReadOnlySpan<byte> source,
+ out int bytesRead)
+ {
+ fixed (byte* ptr = &MemoryMarshal.GetReference(source))
+ {
+ using (MemoryManager<byte> manager = new PointerMemoryManager<byte>(ptr, source.Length))
+ {
+ // Validate the DER value and get the number of bytes.
+ RSAKeyFormatHelper.ReadSubjectPublicKeyInfo(
+ manager.Memory,
+ out int localRead);
+
+ SafeSecKeyRefHandle publicKey = Interop.AppleCrypto.ImportEphemeralKey(source.Slice(0, localRead), false);
+ SetKey(SecKeyPair.PublicOnly(publicKey));
+
+ bytesRead = localRead;
+ }
+ }
+ }
+
+ public override unsafe void ImportRSAPublicKey(ReadOnlySpan<byte> source, out int bytesRead)
+ {
+ fixed (byte* ptr = &MemoryMarshal.GetReference(source))
+ {
+ using (MemoryManager<byte> manager = new PointerMemoryManager<byte>(ptr, source.Length))
+ {
+ AsnReader reader = new AsnReader(manager.Memory, AsnEncodingRules.BER);
+ ReadOnlyMemory<byte> firstElement = reader.PeekEncodedValue();
+
+ SubjectPublicKeyInfoAsn spki = new SubjectPublicKeyInfoAsn
+ {
+ Algorithm = new AlgorithmIdentifierAsn
+ {
+ Algorithm = new Oid(Oids.Rsa),
+ Parameters = AlgorithmIdentifierAsn.ExplicitDerNull,
+ },
+ SubjectPublicKey = firstElement,
+ };
+
+ using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
+ {
+ spki.Encode(writer);
+ ImportSubjectPublicKeyInfo(writer.EncodeAsSpan(), out _);
+ }
+
+ bytesRead = firstElement.Length;
+ }
+ }
+ }
+
public override byte[] Encrypt(byte[] data, RSAEncryptionPadding padding)
{
if (data == null)
private static SafeSecKeyRefHandle ImportKey(RSAParameters parameters)
{
- bool isPrivateKey = parameters.D != null;
- byte[] pkcs1Blob;
-
- if (isPrivateKey)
+ if (parameters.D != null)
{
using (AsnWriter pkcs1PrivateKey = RSAKeyFormatHelper.WritePkcs1PrivateKey(parameters))
{
- pkcs1Blob = pkcs1PrivateKey.Encode();
+ return Interop.AppleCrypto.ImportEphemeralKey(pkcs1PrivateKey.EncodeAsSpan(), true);
}
}
else
{
using (AsnWriter pkcs1PublicKey = RSAKeyFormatHelper.WriteSubjectPublicKeyInfo(parameters))
{
- pkcs1Blob = pkcs1PublicKey.Encode();
+ return Interop.AppleCrypto.ImportEphemeralKey(pkcs1PublicKey.EncodeAsSpan(), false);
}
}
-
- return Interop.AppleCrypto.ImportEphemeralKey(pkcs1Blob, isPrivateKey);
}
}
<Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeEvpPKeyHandle.Unix.cs">
<Link>Common\Microsoft\Win32\SafeHandles\SafeEvpPKeyHandle.Unix.cs</Link>
</Compile>
+ <Compile Include="$(CommonPath)\System\Memory\PointerMemoryManager.cs">
+ <Link>Common\System\Memory\PointerMemoryManager.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)\System\Security\Cryptography\Asn1V2.cs">
<Link>Common\System\Security\Cryptography\Asn1V2.cs</Link>
</Compile>
private static AsymmetricAlgorithm DecodeRsaPublicKey(byte[] encodedKeyValue)
{
- AlgorithmIdentifierAsn ignored = default;
- RSAKeyFormatHelper.ReadRsaPublicKey(
- encodedKeyValue,
- ignored,
- out RSAParameters rsaParameters);
-
RSA rsa = RSA.Create();
try
{
- rsa.ImportParameters(rsaParameters);
+ rsa.ImportRSAPublicKey(encodedKeyValue.AsSpan(), out _);
return rsa;
}
catch (Exception)
private static AsymmetricAlgorithm DecodeDsaPublicKey(byte[] encodedKeyValue, byte[] encodedParameters)
{
- DSAKeyFormatHelper.ReadDsaPublicKey(
- encodedKeyValue,
- new AlgorithmIdentifierAsn { Parameters = encodedParameters },
- out DSAParameters dsaParameters);
-
- DSA dsa = DSA.Create();
- try
+ SubjectPublicKeyInfoAsn spki = new SubjectPublicKeyInfoAsn
{
- dsa.ImportParameters(dsaParameters);
- return dsa;
- }
- catch (Exception)
+ Algorithm = new AlgorithmIdentifierAsn { Algorithm = new Oid(Oids.Dsa, null), Parameters = encodedParameters },
+ SubjectPublicKey = encodedKeyValue,
+ };
+
+ using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
{
- dsa.Dispose();
- throw;
+ spki.Encode(writer);
+ DSA dsa = DSA.Create();
+ try
+ {
+ dsa.ImportSubjectPublicKeyInfo(writer.EncodeAsSpan(), out _);
+ return dsa;
+ }
+ catch (Exception)
+ {
+ dsa.Dispose();
+ throw;
+ }
}
}
private static RSA BuildRsaPublicKey(byte[] encodedData)
{
- using (SafeRsaHandle rsaHandle = Interop.Crypto.DecodeRsaPublicKey(encodedData, encodedData.Length))
+ RSA rsa = new RSAOpenSsl();
+ try
{
- Interop.Crypto.CheckValidOpenSslHandle(rsaHandle);
-
- RSAParameters rsaParameters = Interop.Crypto.ExportRsaParameters(rsaHandle, false);
- RSA rsa = new RSAOpenSsl();
- rsa.ImportParameters(rsaParameters);
- return rsa;
+ rsa.ImportRSAPublicKey(encodedData.AsSpan(), out _);
+ }
+ catch (Exception)
+ {
+ rsa.Dispose();
+ throw;
}
+ return rsa;
}
- private static DSA BuildDsaPublicKey(byte[] encodedKey, byte[] encodedParameters)
+ private static DSA BuildDsaPublicKey(byte[] encodedKeyValue, byte[] encodedParameters)
{
SubjectPublicKeyInfoAsn spki = new SubjectPublicKeyInfoAsn
{
- Algorithm = new AlgorithmIdentifierAsn { Algorithm = new Oid(Oids.Dsa), Parameters = encodedParameters },
- SubjectPublicKey = encodedKey,
+ Algorithm = new AlgorithmIdentifierAsn { Algorithm = new Oid(Oids.Dsa, null), Parameters = encodedParameters },
+ SubjectPublicKey = encodedKeyValue,
};
using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
{
- DSA dsa = new DSAOpenSsl();
spki.Encode(writer);
- dsa.ImportSubjectPublicKeyInfo(writer.EncodeAsSpan(), out _);
- return dsa;
+ DSA dsa = new DSAOpenSsl();
+ try
+ {
+ dsa.ImportSubjectPublicKeyInfo(writer.EncodeAsSpan(), out _);
+ return dsa;
+ }
+ catch (Exception)
+ {
+ dsa.Dispose();
+ throw;
+ }
}
}
}