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

Commit d490291

Browse files
committed
Add CreateOpenSslCryptographicException helper method and use it.
CreateOpenSslCryptographicException will drain out the error stack, using the first reported error for the exception. If the error was an ERR_R_MALLOC_FAILURE code, use an OutOfMemoryException, otherwise a CryptographicException. A pass was made over the code, and any throw statements which were preceded by a call into libcrypto use the new helper method. Calls into NativeCrypto throw an unadorned CryptographicException. This change also introduces CheckValidOpenSslHandle to make the handle checks easier on the eyes, and a few locations were noticed which did not check handle validity with the same thoroughness as the rest of the code.
1 parent 9f89acb commit d490291

File tree

10 files changed

+86
-84
lines changed

10 files changed

+86
-84
lines changed

src/Common/src/Interop/Unix/libcrypto/Interop.ASN1.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ internal static string OBJ_obj2txt_helper(IntPtr asn1ObjectPtr)
7878

7979
if (bytesNeeded < 0)
8080
{
81-
throw new CryptographicException(GetOpenSslErrorString());
81+
throw CreateOpenSslCryptographicException();
8282
}
8383

8484
Debug.Assert(bytesNeeded != 0, "OBJ_obj2txt reported a zero-length response");
@@ -95,7 +95,7 @@ internal static string OBJ_obj2txt_helper(IntPtr asn1ObjectPtr)
9595

9696
if (bytesNeeded < 0)
9797
{
98-
throw new CryptographicException(GetOpenSslErrorString());
98+
throw CreateOpenSslCryptographicException();
9999
}
100100

101101
Debug.Assert(

src/Common/src/Interop/Unix/libcrypto/Interop.ERR.cs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// Copyright (c) Microsoft. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4+
using System;
45
using System.Runtime.InteropServices;
6+
using System.Security.Cryptography;
57
using System.Text;
68

79
internal static partial class Interop
@@ -17,13 +19,56 @@ internal static partial class libcrypto
1719
[DllImport(Libraries.LibCrypto, CharSet = CharSet.Ansi)]
1820
private static extern void ERR_error_string_n(uint e, StringBuilder buf, int len);
1921

20-
internal static string GetOpenSslErrorString()
22+
private static string ERR_error_string_n(uint error)
2123
{
22-
uint error = ERR_get_error();
2324
StringBuilder buf = new StringBuilder(1024);
24-
25+
2526
ERR_error_string_n(error, buf, buf.Capacity);
2627
return buf.ToString();
2728
}
29+
30+
internal static Exception CreateOpenSslCryptographicException()
31+
{
32+
const uint ReasonMask = 0x0FFF;
33+
const uint ERR_R_MALLOC_FAILURE = 64 | 1;
34+
35+
uint error = ERR_get_error();
36+
uint last = error;
37+
38+
while (last != 0)
39+
{
40+
last = ERR_get_error();
41+
}
42+
43+
if (error == 0)
44+
{
45+
return new CryptographicException();
46+
}
47+
48+
uint reason = error & ReasonMask;
49+
50+
if (reason == ERR_R_MALLOC_FAILURE)
51+
{
52+
return new OutOfMemoryException();
53+
}
54+
55+
return new CryptographicException(ERR_error_string_n(error));
56+
}
57+
58+
internal static void CheckValidOpenSslHandle(SafeHandle handle)
59+
{
60+
if (handle == null || handle.IsInvalid)
61+
{
62+
throw CreateOpenSslCryptographicException();
63+
}
64+
}
65+
66+
internal static void CheckValidOpenSslHandle(IntPtr handle)
67+
{
68+
if (handle == IntPtr.Zero)
69+
{
70+
throw CreateOpenSslCryptographicException();
71+
}
72+
}
2873
}
2974
}

src/Common/src/Interop/Unix/libcrypto/Interop.d2i.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,7 @@ internal static unsafe THandle OpenSslD2I<THandle>(D2IFunc<THandle> d2i, byte[]
2727

2828
THandle handle = d2i(IntPtr.Zero, ppData, data.Length);
2929

30-
if (handle.IsInvalid)
31-
{
32-
throw new CryptographicException(GetOpenSslErrorString());
33-
}
30+
CheckValidOpenSslHandle(handle);
3431

3532
return handle;
3633
}

src/System.Security.Cryptography.Encryption.Aes/src/Internal/Cryptography/AesOpenSslCryptoTransform.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -305,12 +305,7 @@ private static void CheckBoolReturn(bool returnValue)
305305
return;
306306
}
307307

308-
throw CreateOpenSslException();
309-
}
310-
311-
private static Exception CreateOpenSslException()
312-
{
313-
return new CryptographicException(Interop.libcrypto.GetOpenSslErrorString());
308+
throw Interop.libcrypto.CreateOpenSslCryptographicException();
314309
}
315310
}
316311
}

src/System.Security.Cryptography.Hashing.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Unix.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ private static void Check(int result)
177177
if (result != Success)
178178
{
179179
Debug.Assert(result == 0);
180-
throw new CryptographicException(Interop.libcrypto.GetOpenSslErrorString());
180+
throw Interop.libcrypto.CreateOpenSslCryptographicException();
181181
}
182182
}
183183
}

src/System.Security.Cryptography.RSA/src/Internal/Cryptography/RsaOpenSsl.cs

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public override unsafe void ImportParameters(RSAParameters parameters)
160160
SafeRsaHandle key = Interop.libcrypto.RSA_new();
161161
bool imported = false;
162162

163-
CheckInvalidNewKey(key);
163+
Interop.libcrypto.CheckValidOpenSslHandle(key);
164164

165165
try
166166
{
@@ -266,19 +266,11 @@ private static void CheckInvalidKey(SafeRsaHandle key)
266266
}
267267
}
268268

269-
private static void CheckInvalidNewKey(SafeRsaHandle key)
270-
{
271-
if (key == null || key.IsInvalid)
272-
{
273-
throw CreateOpenSslException();
274-
}
275-
}
276-
277269
private static void CheckReturn(int returnValue)
278270
{
279271
if (returnValue == -1)
280272
{
281-
throw CreateOpenSslException();
273+
throw Interop.libcrypto.CreateOpenSslCryptographicException();
282274
}
283275
}
284276

@@ -289,15 +281,15 @@ private static void CheckBoolReturn(int returnValue)
289281
return;
290282
}
291283

292-
throw CreateOpenSslException();
284+
throw Interop.libcrypto.CreateOpenSslCryptographicException();
293285
}
294286

295287
private SafeRsaHandle GenerateKey()
296288
{
297289
SafeRsaHandle key = Interop.libcrypto.RSA_new();
298290
bool generated = false;
299291

300-
CheckInvalidNewKey(key);
292+
Interop.libcrypto.CheckValidOpenSslHandle(key);
301293

302294
try
303295
{
@@ -327,11 +319,6 @@ private SafeRsaHandle GenerateKey()
327319
return key;
328320
}
329321

330-
private static Exception CreateOpenSslException()
331-
{
332-
return new CryptographicException(Interop.libcrypto.GetOpenSslErrorString());
333-
}
334-
335322
internal byte[] HashData(byte[] buffer, int offset, int count, HashAlgorithmName hashAlgorithmName)
336323
{
337324
using (HashAlgorithm hasher = GetHashAlgorithm(hashAlgorithmName))
@@ -365,7 +352,7 @@ internal byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithmName)
365352

366353
if (!success)
367354
{
368-
throw CreateOpenSslException();
355+
throw Interop.libcrypto.CreateOpenSslCryptographicException();
369356
}
370357

371358
Debug.Assert(

src/System.Security.Cryptography.RandomNumberGenerator/src/System/Security/Cryptography/RNGCryptoServiceProvider.Unix.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public sealed override unsafe void GetBytes(byte[] data)
1414
{
1515
if (Interop.libcrypto.RAND_pseudo_bytes(buf, data.Length) == -1)
1616
{
17-
throw new CryptographicException();
17+
throw Interop.libcrypto.CreateOpenSslCryptographicException();
1818
}
1919
}
2020
}

src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509CertificateReader.cs

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ internal OpenSslX509CertificateReader(SafeX509Handle handle)
2929

3030
if (!init)
3131
{
32-
throw new CryptographicException(Interop.libcrypto.GetOpenSslErrorString());
32+
throw Interop.libcrypto.CreateOpenSslCryptographicException();
3333
}
3434

3535
_cert = handle;
@@ -45,6 +45,8 @@ internal unsafe OpenSslX509CertificateReader(byte[] data)
4545
{
4646
using (SafeBioHandle bio = Interop.libcrypto.BIO_new(Interop.libcrypto.BIO_s_mem()))
4747
{
48+
Interop.libcrypto.CheckValidOpenSslHandle(bio);
49+
4850
Interop.libcrypto.BIO_write(bio, data, data.Length);
4951
cert = Interop.libcrypto.PEM_read_bio_X509_AUX(bio, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
5052
}
@@ -54,18 +56,15 @@ internal unsafe OpenSslX509CertificateReader(byte[] data)
5456
cert = Interop.libcrypto.OpenSslD2I(Interop.libcrypto.d2i_X509, data);
5557
}
5658

57-
if (cert.IsInvalid)
58-
{
59-
throw new CryptographicException(Interop.libcrypto.GetOpenSslErrorString());
60-
}
59+
Interop.libcrypto.CheckValidOpenSslHandle(cert);
6160

6261
// X509_check_purpose has the effect of populating the sha1_hash value,
6362
// and other "initialize" type things.
6463
bool init = Interop.libcrypto.X509_check_purpose(cert, -1, 0);
6564

6665
if (!init)
6766
{
68-
throw new CryptographicException(Interop.libcrypto.GetOpenSslErrorString());
67+
throw Interop.libcrypto.CreateOpenSslCryptographicException();
6968
}
7069

7170
_cert = cert;
@@ -275,28 +274,18 @@ public IEnumerable<X509Extension> Extensions
275274
{
276275
IntPtr ext = Interop.libcrypto.X509_get_ext(_cert, i);
277276

278-
if (ext == IntPtr.Zero)
279-
{
280-
// This would happen on a bounds violation, but no error code is set.
281-
throw new CryptographicException();
282-
}
277+
Interop.libcrypto.CheckValidOpenSslHandle(ext);
283278

284279
IntPtr oidPtr = Interop.libcrypto.X509_EXTENSION_get_object(ext);
285280

286-
if (oidPtr == IntPtr.Zero)
287-
{
288-
throw new CryptographicException();
289-
}
281+
Interop.libcrypto.CheckValidOpenSslHandle(oidPtr);
290282

291283
string oidValue = Interop.libcrypto.OBJ_obj2txt_helper(oidPtr);
292284
Oid oid = new Oid(oidValue);
293285

294286
IntPtr dataPtr = Interop.libcrypto.X509_EXTENSION_get_data(ext);
295287

296-
if (dataPtr == IntPtr.Zero)
297-
{
298-
throw new CryptographicException();
299-
}
288+
Interop.libcrypto.CheckValidOpenSslHandle(dataPtr);
300289

301290
byte[] extData = Interop.NativeCrypto.GetAsn1StringBytes(dataPtr);
302291
bool critical = Interop.libcrypto.X509_EXTENSION_get_critical(ext);
@@ -330,7 +319,7 @@ public string GetNameInfo(X509NameType nameType, bool forIssuer)
330319

331320
if (read < 0)
332321
{
333-
throw new CryptographicException(Interop.libcrypto.GetOpenSslErrorString());
322+
throw Interop.libcrypto.CreateOpenSslCryptographicException();
334323
}
335324

336325
return builder.ToString();
@@ -352,10 +341,7 @@ public void Dispose()
352341

353342
private static X500DistinguishedName LoadX500Name(IntPtr namePtr)
354343
{
355-
if (namePtr == IntPtr.Zero)
356-
{
357-
throw new CryptographicException();
358-
}
344+
Interop.libcrypto.CheckValidOpenSslHandle(namePtr);
359345

360346
int negativeSize = Interop.NativeCrypto.GetX509NameRawBytes(namePtr, null, 0);
361347

src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509ChainProcessor.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,16 @@ public static IChainPal BuildChain(
5353
using (SafeX509StoreHandle store = Interop.libcrypto.X509_STORE_new())
5454
using (SafeX509StoreCtxHandle storeCtx = Interop.libcrypto.X509_STORE_CTX_new())
5555
{
56-
if (store.IsInvalid || storeCtx.IsInvalid)
57-
{
58-
throw new CryptographicException();
59-
}
56+
Interop.libcrypto.CheckValidOpenSslHandle(store);
57+
Interop.libcrypto.CheckValidOpenSslHandle(storeCtx);
6058

6159
foreach (X509Certificate2 cert in candidates)
6260
{
6361
OpenSslX509CertificateReader pal = (OpenSslX509CertificateReader)cert.Pal;
6462

6563
if (!Interop.libcrypto.X509_STORE_add_cert(store, pal.SafeHandle))
6664
{
67-
throw new CryptographicException();
65+
throw Interop.libcrypto.CreateOpenSslCryptographicException();
6866
}
6967
}
7068

@@ -75,7 +73,7 @@ public static IChainPal BuildChain(
7573

7674
if (!Interop.libcrypto.X509_STORE_CTX_init(storeCtx, store, leafHandle, IntPtr.Zero))
7775
{
78-
throw new CryptographicException(Interop.libcrypto.GetOpenSslErrorString());
76+
throw Interop.libcrypto.CreateOpenSslCryptographicException();
7977
}
8078

8179
Interop.NativeCrypto.SetX509ChainVerifyTime(storeCtx, verificationTime);
@@ -84,7 +82,7 @@ public static IChainPal BuildChain(
8482

8583
if (verify < 0)
8684
{
87-
throw new CryptographicException(Interop.libcrypto.GetOpenSslErrorString());
85+
throw Interop.libcrypto.CreateOpenSslCryptographicException();
8886
}
8987

9088
using (SafeX509StackHandle chainStack = Interop.libcrypto.X509_STORE_CTX_get1_chain(storeCtx))

0 commit comments

Comments
 (0)