/
ECDsaOpenSsl.cs
109 lines (98 loc) · 4.41 KB
/
ECDsaOpenSsl.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using Microsoft.Win32.SafeHandles;
namespace System.Security.Cryptography
{
public sealed partial class ECDsaOpenSsl : ECDsa
{
/// <summary>
/// Create an ECDsaOpenSsl from an <see cref="SafeEvpPKeyHandle"/> whose value is an existing
/// OpenSSL <c>EVP_PKEY*</c> wrapping an <c>EC_KEY*</c>
/// </summary>
/// <param name="pkeyHandle">A SafeHandle for an OpenSSL <c>EVP_PKEY*</c></param>
/// <exception cref="ArgumentNullException"><paramref name="pkeyHandle"/> is <c>null</c></exception>
/// <exception cref="ArgumentException"><paramref name="pkeyHandle"/> <see cref="SafeHandle.IsInvalid" /></exception>
/// <exception cref="CryptographicException"><paramref name="pkeyHandle"/> is not a valid enveloped <c>EC_KEY*</c></exception>
[UnsupportedOSPlatform("android")]
[UnsupportedOSPlatform("browser")]
[UnsupportedOSPlatform("ios")]
[UnsupportedOSPlatform("tvos")]
[UnsupportedOSPlatform("windows")]
public ECDsaOpenSsl(SafeEvpPKeyHandle pkeyHandle)
{
ArgumentNullException.ThrowIfNull(pkeyHandle);
if (pkeyHandle.IsInvalid)
throw new ArgumentException(SR.Cryptography_OpenInvalidHandle, nameof(pkeyHandle));
ThrowIfNotSupported();
// If ecKey is valid it has already been up-ref'd, so we can just use this handle as-is.
SafeEcKeyHandle key = Interop.Crypto.EvpPkeyGetEcKey(pkeyHandle);
if (key.IsInvalid)
{
key.Dispose();
throw Interop.Crypto.CreateOpenSslCryptographicException();
}
_key = new ECOpenSsl(key);
KeySizeValue = _key.KeySize;
}
/// <summary>
/// Create an ECDsaOpenSsl from an existing <see cref="IntPtr"/> whose value is an
/// existing OpenSSL <c>EC_KEY*</c>.
/// </summary>
/// <remarks>
/// This method will increase the reference count of the <c>EC_KEY*</c>, the caller should
/// continue to manage the lifetime of their reference.
/// </remarks>
/// <param name="handle">A pointer to an OpenSSL <c>EC_KEY*</c></param>
/// <exception cref="ArgumentException"><paramref name="handle" /> is invalid</exception>
[UnsupportedOSPlatform("android")]
[UnsupportedOSPlatform("browser")]
[UnsupportedOSPlatform("ios")]
[UnsupportedOSPlatform("tvos")]
[UnsupportedOSPlatform("windows")]
public ECDsaOpenSsl(IntPtr handle)
{
if (handle == IntPtr.Zero)
throw new ArgumentException(SR.Cryptography_OpenInvalidHandle, nameof(handle));
ThrowIfNotSupported();
SafeEcKeyHandle ecKeyHandle = SafeEcKeyHandle.DuplicateHandle(handle);
_key = new ECOpenSsl(ecKeyHandle);
KeySizeValue = _key.KeySize;
}
/// <summary>
/// Obtain a SafeHandle version of an EVP_PKEY* which wraps an EC_KEY* equivalent
/// to the current key for this instance.
/// </summary>
/// <returns>A SafeHandle for the EC_KEY key in OpenSSL</returns>
public SafeEvpPKeyHandle DuplicateKeyHandle()
{
ThrowIfDisposed();
SafeEcKeyHandle currentKey = _key.Value;
SafeEvpPKeyHandle pkeyHandle = Interop.Crypto.EvpPkeyCreate();
try
{
// Wrapping our key in an EVP_PKEY will up_ref our key.
// When the EVP_PKEY is Disposed it will down_ref the key.
// So everything should be copacetic.
if (!Interop.Crypto.EvpPkeySetEcKey(pkeyHandle, currentKey))
{
throw Interop.Crypto.CreateOpenSslCryptographicException();
}
return pkeyHandle;
}
catch
{
pkeyHandle.Dispose();
throw;
}
}
static partial void ThrowIfNotSupported()
{
if (!Interop.OpenSslNoInit.OpenSslIsAvailable)
{
throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_AlgorithmNotSupported, nameof(ECDsaOpenSsl)));
}
}
}
}