Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit fedf648

Browse files
author
Ian Hays
committed
Fix ECDsa ExportParameters segfault
ECDSa.Export(Explicit)Parameters(includePrivateParameters:true) on an EC object containing only a public key will currently segfault on Linux. It is supposed to throw a CryptographicException, so this commit changes it to do so.
1 parent c30b3ed commit fedf648

File tree

3 files changed

+56
-8
lines changed

3 files changed

+56
-8
lines changed

src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcDsa.ImportExport.cs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ internal static SafeEcKeyHandle EcKeyCreateByExplicitCurve(ECCurve curve)
9797

9898

9999
[DllImport(Libraries.CryptoNative)]
100-
private static extern bool CryptoNative_GetECKeyParameters(
100+
private static extern int CryptoNative_GetECKeyParameters(
101101
SafeEcKeyHandle key,
102102
bool includePrivate,
103103
out SafeBignumHandle qx_bn, out int x_cb,
@@ -117,12 +117,18 @@ internal static ECParameters GetECKeyParameters(
117117
try
118118
{
119119
key.DangerousAddRef(ref refAdded); // Protect access to d_bn_not_owned
120-
if (!CryptoNative_GetECKeyParameters(
120+
int rc = CryptoNative_GetECKeyParameters(
121121
key,
122122
includePrivate,
123123
out qx_bn, out qx_cb,
124124
out qy_bn, out qy_cb,
125-
out d_bn_not_owned, out d_cb))
125+
out d_bn_not_owned, out d_cb);
126+
127+
if (rc == -1)
128+
{
129+
throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey);
130+
}
131+
else if (rc != 1)
126132
{
127133
throw Interop.Crypto.CreateOpenSslCryptographicException();
128134
}
@@ -160,7 +166,7 @@ internal static ECParameters GetECKeyParameters(
160166
}
161167

162168
[DllImport(Libraries.CryptoNative)]
163-
private static extern bool CryptoNative_GetECCurveParameters(
169+
private static extern int CryptoNative_GetECCurveParameters(
164170
SafeEcKeyHandle key,
165171
bool includePrivate,
166172
out ECCurve.ECCurveType curveType,
@@ -189,7 +195,7 @@ internal static ECParameters GetECCurveParameters(
189195
try
190196
{
191197
key.DangerousAddRef(ref refAdded); // Protect access to d_bn_not_owned
192-
if (!CryptoNative_GetECCurveParameters(
198+
int rc = CryptoNative_GetECCurveParameters(
193199
key,
194200
includePrivate,
195201
out curveType,
@@ -203,7 +209,13 @@ internal static ECParameters GetECCurveParameters(
203209
out gy_bn, out gy_cb,
204210
out order_bn, out order_cb,
205211
out cofactor_bn, out cofactor_cb,
206-
out seed_bn, out seed_cb))
212+
out seed_bn, out seed_cb);
213+
214+
if (rc == -1)
215+
{
216+
throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey);
217+
}
218+
else if (rc != 1)
207219
{
208220
throw Interop.Crypto.CreateOpenSslCryptographicException();
209221
}

src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44

55
using Xunit;
6+
using Test.Cryptography;
67

78
namespace System.Security.Cryptography.EcDsa.Tests
89
{
@@ -265,6 +266,32 @@ public static void TestNamedCurveWithExplicitKey()
265266
}
266267
}
267268

269+
[ConditionalFact(nameof(ECExplicitCurvesSupported))]
270+
public static void ExportIncludingPrivateOnPublicOnlyKey()
271+
{
272+
ECParameters iutParameters = new ECParameters
273+
{
274+
Curve = ECCurve.NamedCurves.nistP521,
275+
Q =
276+
{
277+
X = "00d45615ed5d37fde699610a62cd43ba76bedd8f85ed31005fe00d6450fbbd101291abd96d4945a8b57bc73b3fe9f4671105309ec9b6879d0551d930dac8ba45d255".HexToByteArray(),
278+
Y = "01425332844e592b440c0027972ad1526431c06732df19cd46a242172d4dd67c2c8c99dfc22e49949a56cf90c6473635ce82f25b33682fb19bc33bd910ed8ce3a7fa".HexToByteArray(),
279+
},
280+
D = "00816f19c1fb10ef94d4a1d81c156ec3d1de08b66761f03f06ee4bb9dcebbbfe1eaa1ed49a6a990838d8ed318c14d74cc872f95d05d07ad50f621ceb620cd905cfb8".HexToByteArray(),
281+
};
282+
283+
using (ECDsa iut = ECDsaFactory.Create())
284+
using (ECDsa cavs = ECDsaFactory.Create())
285+
{
286+
iut.ImportParameters(iutParameters);
287+
cavs.ImportParameters(iut.ExportParameters(false));
288+
289+
// Linux throws an Interop.Crypto.OpenSslCryptographicException : CryptographicException
290+
Assert.ThrowsAny<CryptographicException>(() => cavs.ExportExplicitParameters(true));
291+
Assert.ThrowsAny<CryptographicException>(() => cavs.ExportParameters(true));
292+
}
293+
}
294+
268295
private static void VerifyNamedCurve(ECParameters parameters, ECDsa ec, int keySize, bool includePrivate)
269296
{
270297
parameters.Validate();

src/Native/Unix/System.Security.Cryptography.Native/pal_ecc_import_export.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,17 @@ extern "C" int32_t CryptoNative_GetECKeyParameters(
108108

109109
if (includePrivate)
110110
{
111-
*d = const_cast<BIGNUM*>(EC_KEY_get0_private_key(key));
112-
*cbD = BN_num_bytes(*d);
111+
const BIGNUM* const_bignum_privateKey = EC_KEY_get0_private_key(key);
112+
if (const_bignum_privateKey != nullptr)
113+
{
114+
*d = const_cast<BIGNUM*>(const_bignum_privateKey);
115+
*cbD = BN_num_bytes(*d);
116+
}
117+
else
118+
{
119+
rc = -1;
120+
goto error;
121+
}
113122
}
114123
else
115124
{

0 commit comments

Comments
 (0)