Skip to content

Commit 292436c

Browse files
committed
add net std support and tests
1 parent 776a005 commit 292436c

File tree

8 files changed

+28
-51
lines changed

8 files changed

+28
-51
lines changed

Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<PackageVersion Include="System.Runtime.Serialization.Formatters" Version="4.3.0" />
2323
<PackageVersion Include="System.Runtime.Serialization.Json" Version="4.3.0" />
2424
<PackageVersion Include="System.Runtime.Serialization.Primitives" Version="4.3.0" />
25+
<PackageVersion Include="System.Security.Cryptography.Cng" Version="5.0.0" PrivateAssets="All" />
2526
<PackageVersion Include="System.Security.Cryptography.ProtectedData" Version="4.5.0" />
2627
<PackageVersion Include="System.Security.SecureString" Version="4.3.0" />
2728
<PackageVersion Include="System.ServiceModel.Http" Version="4.5.3" />
@@ -71,7 +72,6 @@
7172
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.35.0" />
7273
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
7374
<PackageVersion Include="System.Reflection.TypeExtensions" Version="4.7.0" />
74-
<PackageVersion Include="System.Security.Cryptography.Cng" Version="5.0.0" />
7575
<PackageVersion Include="System.Text.Json" Version="6.0.10" />
7676
<PackageVersion Include="System.Threading" Version="4.3.0" />
7777
<PackageVersion Include="System.Threading.Tasks" Version="4.3.0" />

build/platform_and_feature_flags.props

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
<PropertyGroup Condition="'$(TargetFramework)' == '$(TargetFrameworkNet)' or '$(TargetFramework)' == '$(TargetFrameworkNetDesktop472)' or '$(TargetFramework)' == '$(TargetFrameworkNetStandard)'">
99
<DefineConstants>$(DefineConstants);SUPPORTS_MTLS;</DefineConstants>
1010
</PropertyGroup>
11-
<PropertyGroup Condition="'$(TargetFramework)' == '$(TargetFrameworkNet)' or '$(TargetFramework)' == '$(TargetFrameworkNetDesktop472)' or '$(TargetFramework)' == '$(TargetFrameworkNetDesktop462)'">
12-
<DefineConstants>$(DefineConstants);SUPPORTS_CNG;</DefineConstants>
13-
</PropertyGroup>
1411
<PropertyGroup Condition="'$(TargetFramework)' == '$(TargetFrameworkNetAndroid)'">
1512
<DefineConstants>$(DefineConstants);ANDROID;SUPPORTS_BROKER</DefineConstants>
1613
</PropertyGroup>

src/client/Microsoft.Identity.Client/Internal/Requests/ManagedIdentityAuthRequest.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// Licensed under the MIT License.
33

44
using System.Collections.Generic;
5-
using System.Net;
6-
using System.Security.Cryptography;
75
using System.Threading;
86
using System.Threading.Tasks;
97
using Microsoft.Identity.Client.ApiConfig.Parameters;

src/client/Microsoft.Identity.Client/ManagedIdentity/KeyProviders/KeyGuardHelper.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Security.Cryptography;
6+
using Microsoft.Identity.Client.Core;
67

78
namespace Microsoft.Identity.Client.ManagedIdentity.KeyGuard
89
{
@@ -13,15 +14,15 @@ internal static class KeyGuardHelper
1314
{
1415
private const string ProviderName = "Microsoft Software Key Storage Provider";
1516
private const string KeyName = "KeyGuardRSAKey";
16-
#if SUPPORTS_CNG
17+
1718
// KeyGuard + per-boot flags
1819
private const CngKeyCreationOptions NCryptUseVirtualIsolationFlag = (CngKeyCreationOptions)0x00020000;
1920
private const CngKeyCreationOptions NCryptUsePerBootKeyFlag = (CngKeyCreationOptions)0x00040000;
2021

2122
/// <summary>
2223
/// Creates a new RSA-2048 Key Guard key.
2324
/// </summary>
24-
public static CngKey CreateFresh()
25+
public static CngKey CreateFresh(ILoggerAdapter logger)
2526
{
2627
var p = new CngKeyCreationParameters
2728
{
@@ -45,12 +46,13 @@ public static CngKey CreateFresh()
4546
catch (CryptographicException ex)
4647
when (IsVbsUnavailable(ex))
4748
{
48-
// wrap in a clearer exception so callers can decide how to react
49-
// for MSAL we can just log and fall back to software keys
50-
throw new PlatformNotSupportedException(
51-
"Key Guard requires Windows Core Isolation (VBS). " +
52-
"Enable it in Windows Security ► Device Security ► Core isolation.",
53-
ex);
49+
logger?.Warning(
50+
"[MI][KeyGuardHelper] VBS key isolation is not available; falling back to software keys. " +
51+
"Ensure that Virtualization Based Security (VBS) is enabled on this machine " +
52+
"(e.g. Credential Guard, Hyper-V, or Windows Defender Application Guard). " +
53+
"Inner exception: " + ex.Message);
54+
55+
return null;
5456
}
5557
}
5658

@@ -72,6 +74,5 @@ private static bool IsVbsUnavailable(CryptographicException ex)
7274
return ex.HResult == NTE_NOT_SUPPORTED ||
7375
ex.Message.Contains("VBS key isolation is not available");
7476
}
75-
#endif
7677
}
7778
}

src/client/Microsoft.Identity.Client/ManagedIdentity/KeyProviders/WindowsCngKeyOperations.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Security.Cryptography;
88
using System.Text;
99
using System.Threading.Tasks;
10+
using Microsoft.Identity.Client.Core;
1011
using Microsoft.Identity.Client.ManagedIdentity.KeyGuard;
1112

1213
namespace Microsoft.Identity.Client.ManagedIdentity.KeyProviders
@@ -20,7 +21,7 @@ internal static class WindowsCngKeyOperations
2021
private const string KeyName = "KeyGuardRSAKey";
2122

2223
// --- KeyGuard path (RSA) ---
23-
public static bool TryGetOrCreateKeyGuard(out RSA rsa)
24+
public static bool TryGetOrCreateKeyGuard(ILoggerAdapter logger, out RSA rsa)
2425
{
2526
rsa = default(RSA);
2627

@@ -34,15 +35,17 @@ public static bool TryGetOrCreateKeyGuard(out RSA rsa)
3435
}
3536
catch (CryptographicException)
3637
{
37-
// Not found -> create fresh
38-
key = KeyGuardHelper.CreateFresh();
38+
// Not found -> create fresh
39+
logger?.Verbose(() => "[MI][WinKeyProvider] KeyGuard key not found; creating fresh.");
40+
key = KeyGuardHelper.CreateFresh(logger);
3941
}
4042

4143
// Ensure actually KeyGuard-protected; recreate if not
4244
if (!KeyGuardHelper.IsKeyGuardProtected(key))
4345
{
46+
logger?.Verbose(() => "[MI][WinKeyProvider] KeyGuard key found but not protected; recreating.");
4447
key.Dispose();
45-
key = KeyGuardHelper.CreateFresh();
48+
key = KeyGuardHelper.CreateFresh(logger);
4649
}
4750

4851
rsa = new RSACng(key);
@@ -57,6 +60,7 @@ public static bool TryGetOrCreateKeyGuard(out RSA rsa)
5760
catch (PlatformNotSupportedException)
5861
{
5962
// VBS/Core Isolation not available => KeyGuard unavailable
63+
logger?.Verbose(() => "[MI][WinKeyProvider] Exception creating KeyGuard key.");
6064
return false;
6165
}
6266
catch (CryptographicException)
@@ -66,7 +70,7 @@ public static bool TryGetOrCreateKeyGuard(out RSA rsa)
6670
}
6771

6872
// --- Hardware (TPM/KSP) path (RSA) ---
69-
public static bool TryGetOrCreateHardwareRsa(out RSA rsa)
73+
public static bool TryGetOrCreateHardwareRsa(ILoggerAdapter logger, out RSA rsa)
7074
{
7175
rsa = default(RSA);
7276

@@ -96,11 +100,13 @@ public static bool TryGetOrCreateHardwareRsa(out RSA rsa)
96100
{ rsa.KeySize = 2048; }
97101
catch { }
98102
}
99-
103+
104+
logger?.Info("[MI][WinKeyProvider] Using Hardware key (RSA).");
100105
return true;
101106
}
102107
catch (CryptographicException)
103108
{
109+
logger?.Verbose(() => "[MI][WinKeyProvider] Exception creating Hardware key.");
104110
return false;
105111
}
106112
}

src/client/Microsoft.Identity.Client/ManagedIdentity/KeyProviders/WindowsManagedIdentityKeyProvider.cs

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ public async Task<ManagedIdentityKeyInfo> GetOrCreateKeyAsync(
5151
}
5252

5353
var messageBuilder = new StringBuilder();
54-
#if SUPPORTS_CNG
54+
5555
// 1) KeyGuard (RSA-2048 under VBS isolation)
5656
try
5757
{
5858
logger.Info("[MI][WinKeyProvider] Trying KeyGuard key.");
59-
if (WindowsCngKeyOperations.TryGetOrCreateKeyGuard(out RSA kgRsa))
59+
if (WindowsCngKeyOperations.TryGetOrCreateKeyGuard(logger, out RSA kgRsa))
6060
{
6161
messageBuilder.AppendLine("KeyGuard RSA key created successfully.");
6262
_cached = new ManagedIdentityKeyInfo(kgRsa, ManagedIdentityKeyType.KeyGuard, messageBuilder.ToString());
@@ -81,7 +81,7 @@ public async Task<ManagedIdentityKeyInfo> GetOrCreateKeyAsync(
8181
try
8282
{
8383
logger?.Verbose(() => "[MI][WinKeyProvider] Trying Hardware (TPM/KSP) key.");
84-
if (WindowsCngKeyOperations.TryGetOrCreateHardwareRsa(out RSA hwRsa))
84+
if (WindowsCngKeyOperations.TryGetOrCreateHardwareRsa(logger, out RSA hwRsa))
8585
{
8686
messageBuilder.AppendLine("Hardware RSA key created successfully.");
8787
_cached = new ManagedIdentityKeyInfo(hwRsa, ManagedIdentityKeyType.Hardware, messageBuilder.ToString());
@@ -101,22 +101,6 @@ public async Task<ManagedIdentityKeyInfo> GetOrCreateKeyAsync(
101101
$"[MI][WinKeyProvider] Exception creating Hardware key: {ex}",
102102
$"[MI][WinKeyProvider] Exception creating Hardware key: {ex.GetType().Name}");
103103
}
104-
#endif
105-
// 3) Fallback to portable in-memory provider
106-
logger?.Verbose(() => "[MI][WinKeyProvider] Falling back to InMemory key provider.");
107-
messageBuilder.AppendLine("Falling back to in-memory RSA key provider.");
108-
109-
var memProvider = new InMemoryManagedIdentityKeyProvider();
110-
ManagedIdentityKeyInfo memKeyInfo = await memProvider.GetOrCreateKeyAsync(logger, ct).ConfigureAwait(false);
111-
112-
if (!string.IsNullOrEmpty(memKeyInfo.ProviderMessage))
113-
{
114-
messageBuilder.AppendLine(memKeyInfo.ProviderMessage.TrimEnd());
115-
}
116-
117-
_cached = new ManagedIdentityKeyInfo(memKeyInfo.Key, ManagedIdentityKeyType.InMemory, messageBuilder.ToString());
118-
119-
logger?.Info($"[MI][WinKeyProvider] Using InMemory key. Success={(memKeyInfo.Key != null)}.");
120104

121105
return _cached;
122106
}

src/client/Microsoft.Identity.Client/ManagedIdentity/ManagedIdentityKeyProviderFactory.cs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,22 +55,15 @@ internal static IManagedIdentityKeyProvider GetOrCreateProvider(ILoggerAdapter l
5555
/// </summary>
5656
private static IManagedIdentityKeyProvider CreateProviderCore(ILoggerAdapter logger)
5757
{
58-
#if !SUPPORTS_CNG
59-
// When CNG support (KeyGuard / TPM) is not compiled in, we only have the in-memory provider.
60-
logger?.Verbose(() => "[MI][KeyProviderFactory] CNG not supported - using InMemory provider.");
61-
return new InMemoryManagedIdentityKeyProvider();
62-
#else
63-
// SUPPORTS_CNG defined: we can attempt Windows-specific providers if on Windows.
6458
if (DesktopOsHelper.IsWindows())
6559
{
6660
logger?.Info("[MI][KeyProviderFactory] Windows detected with CNG support - using Windows managed identity key provider.");
6761
return new WindowsManagedIdentityKeyProvider();
6862
}
6963

70-
// Non-Windows OS with SUPPORTS_CNG defined still falls back to in-memory implementation.
64+
// Non-Windows OS - we will fall back to in-memory implementation.
7165
logger?.Info("[MI][KeyProviderFactory] Non-Windows platform (with CNG) - using InMemory provider.");
7266
return new InMemoryManagedIdentityKeyProvider();
73-
#endif
7467
}
7568
}
7669
}

src/client/Microsoft.Identity.Client/Microsoft.Identity.Client.csproj

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@
8080
<Compile Include="$(PathToMsalSources)\**\*.cs" Exclude="$(PathToMsalSources)\obj\**\*.*" />
8181
<Compile Remove="$(PathToMsalSources)\Platforms\**\*.*;$(PathToMsalSources)\Resources\*.cs" />
8282
<Compile Remove="$(PathToMsalSources)\PlatformsCommon\PlatformNotSupported\ApiConfig\SystemWebViewOptions.cs" />
83-
<Compile Remove="$(PathToMsalSources)\ManagedIdentity\KeyProviders\WindowsCngKeyOperations.cs" />
8483
<EmbeddedResource Include="$(PathToMsalSources)\Properties\Microsoft.Identity.Client.rd.xml" />
8584
<None Include="$(PathToMsalSources)\..\..\..\README.md" Pack="true" PackagePath="\" />
8685
<None Include="Platforms\net\JsonObjectAttribute.cs" />
@@ -95,6 +94,7 @@
9594
<Compile Include="$(PathToMsalSources)\Platforms\Features\OpenTelemetry\**\*.cs" />
9695

9796
<PackageReference Include="System.Diagnostics.DiagnosticSource" />
97+
<PackageReference Include="System.Security.Cryptography.Cng" />
9898
</ItemGroup>
9999

100100
<ItemGroup Condition="'$(TargetFramework)' == '$(TargetFrameworkNet)'">
@@ -103,7 +103,6 @@
103103
<Compile Include="$(PathToMsalSources)\Platforms\Features\DefaultOSBrowser\**\*.cs" />
104104
<Compile Include="$(PathToMsalSources)\Platforms\Features\DesktopOS\**\*.cs" />
105105
<Compile Include="$(PathToMsalSources)\Platforms\Features\OpenTelemetry\**\*.cs" />
106-
<Compile Include="$(PathToMsalSources)\ManagedIdentity\KeyProviders\WindowsCngKeyOperations.cs" />
107106

108107
<!--System.Text.Json replaces internal NewtonSoft for NET -->
109108
<Compile Remove="$(PathToMsalSources)\json\**\*.*" />
@@ -127,7 +126,6 @@
127126
<Compile Include="$(PathToMsalSources)\Platforms\Features\DefaultOSBrowser\**\*.cs" />
128127
<Compile Include="$(PathToMsalSources)\Platforms\Features\WinFormsLegacyWebUi\**\*.cs" />
129128
<Compile Include="$(PathToMsalSources)\Platforms\Features\DesktopOS\**\*.cs" />
130-
<Compile Include="$(PathToMsalSources)\ManagedIdentity\KeyProviders\WindowsCngKeyOperations.cs" />
131129

132130
<Reference Include="System" />
133131
<Reference Include="System.Core" />

0 commit comments

Comments
 (0)