-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathModuleInit.cs
More file actions
74 lines (69 loc) · 3.03 KB
/
Copy pathModuleInit.cs
File metadata and controls
74 lines (69 loc) · 3.03 KB
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
using System.Runtime.CompilerServices;
using TopSecret;
namespace TopSecret.LinuxTpm;
/// <summary>
/// Auto-registers <see cref="LinuxTpmProtector"/> with the main package's
/// <see cref="KeyAtRestProtectorFactory"/> at assembly load. Consumers do
/// not call this directly — referencing
/// <c>TopSecret.ProtectedString.LinuxTpm</c> from any project that also
/// references <c>TopSecret.ProtectedString</c> is enough.
/// </summary>
/// <remarks>
/// <para>
/// On non-Linux hosts the module initializer still runs, but
/// <see cref="LinuxTpmProtector.IsAvailable"/> returns <see langword="false"/>
/// and <see cref="LinuxTpmProtector.TryCreate"/> returns
/// <see langword="null"/>, so the registration is a no-op in practice. This
/// keeps the package safely referenceable from cross-platform projects.
/// </para>
/// <para>
/// Module initializers run exactly once per assembly load, before any
/// caller-visible member of this assembly is touched. The registration
/// therefore lands before the first <see cref="ProtectedString"/>
/// construction <i>provided</i> the consumer references this assembly
/// strongly enough that the runtime loads it eagerly. If the consumer
/// relies on lazy / dynamic loading, register manually via
/// <see cref="LinuxTpmRegistration.Register"/> in their composition root.
/// </para>
/// </remarks>
internal static class ModuleInit
{
// CA2255: ModuleInitializer is normally for app code, not libraries. We
// use it deliberately here as the no-config wiring contract documented
// in the package description; consumers who need explicit ordering can
// call LinuxTpmRegistration.Register() instead.
#pragma warning disable CA2255
[ModuleInitializer]
#pragma warning restore CA2255
public static void Initialize()
{
LinuxTpmRegistration.Register();
}
}
/// <summary>
/// Public registration entry-point. Call <see cref="Register"/> manually
/// from your composition root if you cannot rely on
/// <see cref="ModuleInit"/> firing in time (e.g. dynamic assembly loading).
/// </summary>
public static class LinuxTpmRegistration
{
private static int s_registered;
/// <summary>
/// Registers <see cref="LinuxTpmProtector"/> with
/// <see cref="KeyAtRestProtectorFactory"/>. Idempotent — repeated calls
/// are no-ops. Safe to call from any platform; the factory delegate
/// returns <see langword="null"/> on non-Linux hosts.
/// </summary>
public static void Register()
{
if (Interlocked.CompareExchange(ref s_registered, 1, 0) != 0) return;
KeyAtRestProtectorFactory.RegisterHardwareBacked(
factory: LinuxTpmProtector.TryCreate,
availabilityProbe: LinuxTpmProtector.IsAvailable,
// TPM 2.0 keeps generated keys in transient slots (≤3 on
// commodity TPMs). Periodic process-key rotation orphans the
// old protectors; without this flag the main package can't
// tell the operator that they're about to hit TPM_RC_RESOURCES.
transientSlotConstrained: true);
}
}