Skip to content

Commit c8c3963

Browse files
authored
[macOS] Implement RSA, ECC through new macOS 10.12 APIs (#51620)
1 parent fa7c6a9 commit c8c3963

File tree

10 files changed

+128
-383
lines changed

10 files changed

+128
-383
lines changed

src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Ecc.cs

+16-17
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Runtime.InteropServices;
66
using System.Security.Cryptography;
77
using System.Security.Cryptography.Apple;
8+
using Microsoft.Win32.SafeHandles;
89

910
internal static partial class Interop
1011
{
@@ -13,10 +14,9 @@ internal static partial class AppleCrypto
1314
[DllImport(Libraries.AppleCryptoNative)]
1415
private static extern int AppleCryptoNative_EccGenerateKey(
1516
int keySizeInBits,
16-
SafeKeychainHandle tempKeychain,
1717
out SafeSecKeyRefHandle pPublicKey,
1818
out SafeSecKeyRefHandle pPrivateKey,
19-
out int pOSStatus);
19+
out SafeCFErrorHandle pErrorOut);
2020

2121
[DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_EccGetKeySizeInBits")]
2222
internal static extern long EccGetKeySizeInBits(SafeSecKeyRefHandle publicKey);
@@ -26,20 +26,19 @@ internal static void EccGenerateKey(
2626
out SafeSecKeyRefHandle pPublicKey,
2727
out SafeSecKeyRefHandle pPrivateKey)
2828
{
29-
using (SafeTemporaryKeychainHandle tempKeychain = CreateTemporaryKeychain())
29+
SafeSecKeyRefHandle keychainPublic;
30+
SafeSecKeyRefHandle keychainPrivate;
31+
SafeCFErrorHandle error;
32+
33+
int result = AppleCryptoNative_EccGenerateKey(
34+
keySizeInBits,
35+
out keychainPublic,
36+
out keychainPrivate,
37+
out error);
38+
39+
using (error)
3040
{
31-
SafeSecKeyRefHandle keychainPublic;
32-
SafeSecKeyRefHandle keychainPrivate;
33-
int osStatus;
34-
35-
int result = AppleCryptoNative_EccGenerateKey(
36-
keySizeInBits,
37-
tempKeychain,
38-
out keychainPublic,
39-
out keychainPrivate,
40-
out osStatus);
41-
42-
if (result == 1)
41+
if (result == kSuccess)
4342
{
4443
pPublicKey = keychainPublic;
4544
pPrivateKey = keychainPrivate;
@@ -49,9 +48,9 @@ internal static void EccGenerateKey(
4948
using (keychainPrivate)
5049
using (keychainPublic)
5150
{
52-
if (result == 0)
51+
if (result == kErrorSeeError)
5352
{
54-
throw CreateExceptionForOSStatus(osStatus);
53+
throw CreateExceptionForCFError(error);
5554
}
5655

5756
Debug.Fail($"Unexpected result from AppleCryptoNative_EccGenerateKey: {result}");

src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.RSA.cs

+15-20
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@ internal static partial class AppleCrypto
1515
[DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_RsaGenerateKey")]
1616
private static extern int AppleCryptoNative_RsaGenerateKey(
1717
int keySizeInBits,
18-
SafeKeychainHandle keychain,
1918
out SafeSecKeyRefHandle pPublicKey,
2019
out SafeSecKeyRefHandle pPrivateKey,
21-
out int pOSStatus);
20+
out SafeCFErrorHandle pErrorOut);
2221

2322
[DllImport(Libraries.AppleCryptoNative)]
2423
private static extern int AppleCryptoNative_RsaSignaturePrimitive(
@@ -125,20 +124,19 @@ internal static void RsaGenerateKey(
125124
out SafeSecKeyRefHandle pPublicKey,
126125
out SafeSecKeyRefHandle pPrivateKey)
127126
{
128-
using (SafeTemporaryKeychainHandle tempKeychain = CreateTemporaryKeychain())
127+
SafeSecKeyRefHandle keychainPublic;
128+
SafeSecKeyRefHandle keychainPrivate;
129+
SafeCFErrorHandle error;
130+
131+
int result = AppleCryptoNative_RsaGenerateKey(
132+
keySizeInBits,
133+
out keychainPublic,
134+
out keychainPrivate,
135+
out error);
136+
137+
using (error)
129138
{
130-
SafeSecKeyRefHandle keychainPublic;
131-
SafeSecKeyRefHandle keychainPrivate;
132-
int osStatus;
133-
134-
int result = AppleCryptoNative_RsaGenerateKey(
135-
keySizeInBits,
136-
tempKeychain,
137-
out keychainPublic,
138-
out keychainPrivate,
139-
out osStatus);
140-
141-
if (result == 1)
139+
if (result == kSuccess)
142140
{
143141
pPublicKey = keychainPublic;
144142
pPrivateKey = keychainPrivate;
@@ -148,9 +146,9 @@ internal static void RsaGenerateKey(
148146
using (keychainPrivate)
149147
using (keychainPublic)
150148
{
151-
if (result == 0)
149+
if (result == kErrorSeeError)
152150
{
153-
throw CreateExceptionForOSStatus(osStatus);
151+
throw CreateExceptionForCFError(error);
154152
}
155153

156154
Debug.Fail($"Unexpected result from AppleCryptoNative_RsaGenerateKey: {result}");
@@ -258,9 +256,6 @@ private static bool ProcessPrimitiveResponse(
258256
Span<byte> destination,
259257
out int bytesWritten)
260258
{
261-
const int kErrorSeeError = -2;
262-
const int kSuccess = 1;
263-
264259
if (returnValue == kErrorSeeError)
265260
{
266261
throw CreateExceptionForCFError(cfError);

src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecKeyRef.cs

+5-9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ internal static partial class Interop
1212
{
1313
internal static partial class AppleCrypto
1414
{
15+
private const int kSuccess = 1;
16+
private const int kErrorSeeError = -2;
17+
1518
private static int AppleCryptoNative_SecKeyImportEphemeral(
1619
ReadOnlySpan<byte> pbKeyBlob,
1720
int isPrivateKey,
@@ -129,9 +132,6 @@ private static extern int AppleCryptoNative_VerifySignatureWithHashAlgorithm(
129132

130133
private static byte[] ExecuteTransform(ReadOnlySpan<byte> source, SecKeyTransform transform)
131134
{
132-
const int Success = 1;
133-
const int kErrorSeeError = -2;
134-
135135
SafeCFDataHandle data;
136136
SafeCFErrorHandle error;
137137

@@ -140,7 +140,7 @@ private static byte[] ExecuteTransform(ReadOnlySpan<byte> source, SecKeyTransfor
140140
using (error)
141141
using (data)
142142
{
143-
if (ret == Success)
143+
if (ret == kSuccess)
144144
{
145145
return CoreFoundation.CFGetData(data);
146146
}
@@ -169,11 +169,9 @@ private static bool TryExecuteTransform(
169169
using (errorHandle)
170170
using (outputHandle)
171171
{
172-
const int Success = 1;
173-
const int kErrorSeeError = -2;
174172
switch (ret)
175173
{
176-
case Success:
174+
case kSuccess:
177175
return CoreFoundation.TryCFWriteData(outputHandle, destination, out bytesWritten);
178176
case kErrorSeeError:
179177
throw CreateExceptionForCFError(errorHandle);
@@ -292,7 +290,6 @@ internal static bool VerifySignature(
292290

293291
const int True = 1;
294292
const int False = 0;
295-
const int kErrorSeeError = -2;
296293

297294
using (error)
298295
{
@@ -331,7 +328,6 @@ internal static bool VerifySignature(
331328

332329
const int True = 1;
333330
const int False = 0;
334-
const int kErrorSeeError = -2;
335331

336332
using (error)
337333
{

src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_ecc.c

+12-20
Original file line numberDiff line numberDiff line change
@@ -3,55 +3,47 @@
33

44
#include "pal_ecc.h"
55

6-
#if !defined(TARGET_MACCATALYST) && !defined(TARGET_IOS) && !defined(TARGET_TVOS)
7-
int32_t AppleCryptoNative_EccGenerateKey(
8-
int32_t keySizeBits, SecKeychainRef tempKeychain, SecKeyRef* pPublicKey, SecKeyRef* pPrivateKey, int32_t* pOSStatus)
6+
int32_t AppleCryptoNative_EccGenerateKey(int32_t keySizeBits,
7+
SecKeyRef* pPublicKey,
8+
SecKeyRef* pPrivateKey,
9+
CFErrorRef* pErrorOut)
910
{
1011
if (pPublicKey != NULL)
1112
*pPublicKey = NULL;
1213
if (pPrivateKey != NULL)
1314
*pPrivateKey = NULL;
1415

15-
if (pPublicKey == NULL || pPrivateKey == NULL || pOSStatus == NULL)
16+
if (pPublicKey == NULL || pPrivateKey == NULL || pErrorOut == NULL)
1617
return kErrorBadInput;
1718

19+
int32_t ret = kErrorSeeError;
1820
CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(NULL, 3, &kCFTypeDictionaryKeyCallBacks, NULL);
19-
2021
CFNumberRef cfKeySizeValue = CFNumberCreate(NULL, kCFNumberIntType, &keySizeBits);
21-
OSStatus status;
2222

2323
if (attributes != NULL && cfKeySizeValue != NULL)
2424
{
2525
CFDictionaryAddValue(attributes, kSecAttrKeyType, kSecAttrKeyTypeEC);
2626
CFDictionaryAddValue(attributes, kSecAttrKeySizeInBits, cfKeySizeValue);
27-
CFDictionaryAddValue(attributes, kSecUseKeychain, tempKeychain);
28-
29-
status = SecKeyGeneratePair(attributes, pPublicKey, pPrivateKey);
30-
31-
if (status == noErr)
32-
{
33-
status = ExportImportKey(pPublicKey, kSecItemTypePublicKey);
34-
}
3527

36-
if (status == noErr)
28+
*pPrivateKey = SecKeyCreateRandomKey(attributes, pErrorOut);
29+
if (*pPrivateKey != NULL)
3730
{
38-
status = ExportImportKey(pPrivateKey, kSecItemTypePrivateKey);
31+
*pPublicKey = SecKeyCopyPublicKey(*pPrivateKey);
32+
ret = 1;
3933
}
4034
}
4135
else
4236
{
43-
status = errSecAllocate;
37+
ret = errSecAllocate;
4438
}
4539

4640
if (attributes != NULL)
4741
CFRelease(attributes);
4842
if (cfKeySizeValue != NULL)
4943
CFRelease(cfKeySizeValue);
5044

51-
*pOSStatus = status;
52-
return status == noErr;
45+
return ret;
5346
}
54-
#endif
5547

5648
uint64_t AppleCryptoNative_EccGetKeySizeInBits(SecKeyRef publicKey)
5749
{

src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_ecc.h

+2-5
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,15 @@
88

99
#include <Security/Security.h>
1010

11-
#if !defined(TARGET_MACCATALYST) && !defined(TARGET_IOS) && !defined(TARGET_TVOS)
1211
/*
1312
Generate an ECC keypair of the specified size.
1413
15-
Returns 1 on success, 0 on failure. On failure, *pOSStatus should carry the OS failure code.
14+
Follows pal_seckey return conventions.
1615
*/
1716
PALEXPORT int32_t AppleCryptoNative_EccGenerateKey(int32_t keySizeBits,
18-
SecKeychainRef tempKeychain,
1917
SecKeyRef* pPublicKey,
2018
SecKeyRef* pPrivateKey,
21-
int32_t* pOSStatus);
22-
#endif
19+
CFErrorRef* pErrorOut);
2320

2421
/*
2522
Get the keysize, in bits, of an ECC key.

0 commit comments

Comments
 (0)