-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Managed HPKE #133804
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Managed HPKE #133804
Changes from all commits
Commits
Show all changes
60 commits
Select commit
Hold shift + click to select a range
f8e9316
Add experimental HPKE cipher suite descriptors
vcsjones 68258cf
Complete HpkeSuite metadata and public API
vcsjones 939cd7d
Add managed HPKE foundation
vcsjones e87f872
Split managed HPKE KEM adapters
vcsjones f57271e
Add HPKE key factory APIs
vcsjones fa21cda
Implement HPKE decapsulation key export
vcsjones d035fc0
Implement HPKE encapsulation key export
vcsjones f589d5a
Checkpoint HPKE Seal and managed AEAD adapters
vcsjones e621f1c
Add HPKE KEM encapsulation and key schedule adapters
vcsjones ce437ba
Implement HPKE single-shot sealing
vcsjones 7ea28a5
Use stack buffers for fixed-size HPKE intermediates
vcsjones 576af50
Implement HPKE single-shot opening
vcsjones 6e25e20
Add abstract HPKE sender and recipient contexts
vcsjones 1b0907f
Implement stateful HPKE sender creation and sealing
vcsjones c2ff6cd
Implement stateful HPKE recipient creation and opening
vcsjones cfc2d3b
Implement HPKE PSK sender and recipient modes
vcsjones 8f4fd22
Implement P-521 DHKEM support for HPKE
vcsjones a798ae5
Implement HPKE context secret export
vcsjones 4a10e1d
Implement HPKE key import APIs
vcsjones 6f8aa63
Reject concurrent HPKE sender sealing
vcsjones 4152869
Validate HPKE sender buffer overlaps
vcsjones 9d8e8b6
Complete HPKE single-shot API documentation
vcsjones 0961d98
Fix HPKE target wiring in Microsoft.Bcl.Cryptography
vcsjones 6a80474
Validate HPKE Open and Export buffer overlaps
vcsjones 32f473c
Refine HPKE validation order and temporary buffers
vcsjones 850ea5f
Remove redundant HPKE key-schedule output staging
vcsjones b26bfdd
Stop clearing non-secret HPKE buffers
vcsjones f0afdec
Derive HPKE KEM suite IDs from enum values
vcsjones 9badba1
Assert the internal HPKE export-length invariant
vcsjones 68535fa
Reuse the KDF adapter across HPKE key operations
vcsjones 60e3a09
Stream HPKE SHAKE inputs through public APIs
vcsjones 52c1bc7
Merge remote-tracking branch 'ms/main' into hpke-impl
vcsjones 6624230
Add shared HPKE contract tests
vcsjones eac840c
Add a representative HPKE test-vector corpus
vcsjones 7dad5f4
Bound HPKE test exporter contexts to 1024 bytes
vcsjones b2b0339
Add shared HPKE sender and recipient contract tests
vcsjones af31501
Add shared HPKE key tests and prune legacy tests
vcsjones a4318a9
Add shared HPKE implementation tests
vcsjones c37a857
Simplify HPKE recipient documentation
vcsjones 93cf8e5
Simplify HPKE sender and suite documentation
vcsjones 627779e
Separate HPKE static validation from instance contracts
vcsjones 2d362f9
Refine HPKE export tests and browser build exclusions
vcsjones befd9b0
Add comment clarifying why OpenCore does not have a concurrency guard
vcsjones efb532e
Fixup docs
vcsjones bdd4fb5
More code review fixes
vcsjones ba53a2f
Switch to hex for enum values
vcsjones 795ec2d
Fix build
vcsjones e6a3a89
Undo object-initializer in usings
vcsjones 16253ea
Merge remote-tracking branch 'ms/main' into hpke-impl
vcsjones f20a6c7
Use AssertExtensions.SequenceEqual in more places
vcsjones 686665a
Address some HPKE feedback
vcsjones fb47087
Remove redundant asserts
vcsjones 86fa2b6
Undo ORP
vcsjones c69dcec
Rename file
vcsjones 8410650
Rollback defensive dispose pattern
vcsjones afb25c5
Use HKDF API for label extraction
vcsjones fe65479
Refactor HPKE to use HKDF APIs directly. Add input limits since we ca…
vcsjones 5637921
Fix build for .NET Framework
vcsjones 8f908a6
Fix failing tests and translate exception for Windows
vcsjones 74477e5
Merge branch 'main' into hpke-impl
vcsjones File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1,519 changes: 1,519 additions & 0 deletions
1,519
src/libraries/Common/src/System/Security/Cryptography/Hpke.cs
Large diffs are not rendered by default.
Oops, something went wrong.
30 changes: 30 additions & 0 deletions
30
src/libraries/Common/src/System/Security/Cryptography/HpkeAead.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Diagnostics.CodeAnalysis; | ||
|
|
||
| namespace System.Security.Cryptography | ||
| { | ||
| /// <summary> | ||
| /// Specifies an authenticated encryption with associated data (AEAD) algorithm for an HPKE cipher suite. | ||
| /// </summary> | ||
| /// <seealso cref="HpkeSuite" /> | ||
| [Experimental(Experimentals.HpkeExperimentalDiagId, UrlFormat = Experimentals.SharedUrlFormat)] | ||
| public enum HpkeAead | ||
| { | ||
| /// <summary> | ||
| /// Indicates that authenticated encryption uses AES-GCM with a 128-bit key. | ||
| /// </summary> | ||
| AES_128_GCM = 0x0001, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that authenticated encryption uses AES-GCM with a 256-bit key. | ||
| /// </summary> | ||
| AES_256_GCM = 0x0002, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that authenticated encryption uses ChaCha20-Poly1305. | ||
| /// </summary> | ||
| ChaCha20Poly1305 = 0x0003, | ||
| } | ||
| } |
39 changes: 39 additions & 0 deletions
39
src/libraries/Common/src/System/Security/Cryptography/HpkeAeadMetadata.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| namespace System.Security.Cryptography | ||
| { | ||
| internal sealed partial class HpkeAeadMetadata | ||
| { | ||
| internal HpkeAead Aead { get; } | ||
| internal int Nk { get; } | ||
| internal int Nn { get; } | ||
| internal int Nt { get; } | ||
| internal string Name { get; } | ||
|
|
||
| private HpkeAeadMetadata(HpkeAead aead, int nk, int nn, int nt, string name) | ||
| { | ||
| Aead = aead; | ||
| Nk = nk; | ||
| Nn = nn; | ||
| Nt = nt; | ||
| Name = name; | ||
| } | ||
|
|
||
| internal static HpkeAeadMetadata? Create(HpkeAead aead) | ||
| { | ||
| // https://datatracker.ietf.org/doc/html/draft-ietf-hpke-hpke-04#section-7.3 | ||
| switch (aead) | ||
| { | ||
| case HpkeAead.AES_128_GCM: | ||
| return new HpkeAeadMetadata(aead, nk: 16, nn: 12, nt: 16, name: "AES-128-GCM"); | ||
| case HpkeAead.AES_256_GCM: | ||
| return new HpkeAeadMetadata(aead, nk: 32, nn: 12, nt: 16, name: "AES-256-GCM"); | ||
| case HpkeAead.ChaCha20Poly1305: | ||
| return new HpkeAeadMetadata(aead, nk: 32, nn: 12, nt: 16, name: "ChaCha20Poly1305"); | ||
| default: | ||
| return null; | ||
| } | ||
| } | ||
| } | ||
| } | ||
40 changes: 40 additions & 0 deletions
40
src/libraries/Common/src/System/Security/Cryptography/HpkeKdf.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Diagnostics.CodeAnalysis; | ||
|
|
||
| namespace System.Security.Cryptography | ||
| { | ||
| /// <summary> | ||
| /// Specifies a key derivation function (KDF) for an HPKE cipher suite. | ||
| /// </summary> | ||
| /// <seealso cref="HpkeSuite" /> | ||
| [Experimental(Experimentals.HpkeExperimentalDiagId, UrlFormat = Experimentals.SharedUrlFormat)] | ||
| public enum HpkeKdf | ||
| { | ||
| /// <summary> | ||
| /// Indicates that key derivation uses HKDF with SHA-256. | ||
| /// </summary> | ||
| HKDF_SHA256 = 0x0001, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that key derivation uses HKDF with SHA-384. | ||
| /// </summary> | ||
| HKDF_SHA384 = 0x0002, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that key derivation uses HKDF with SHA-512. | ||
| /// </summary> | ||
| HKDF_SHA512 = 0x0003, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that key derivation uses SHAKE128. | ||
| /// </summary> | ||
| SHAKE128 = 0x0010, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that key derivation uses SHAKE256. | ||
| /// </summary> | ||
| SHAKE256 = 0x0011 | ||
| } | ||
| } |
71 changes: 71 additions & 0 deletions
71
src/libraries/Common/src/System/Security/Cryptography/HpkeKdfMetadata.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Diagnostics; | ||
|
|
||
| namespace System.Security.Cryptography | ||
| { | ||
| internal sealed partial class HpkeKdfMetadata | ||
| { | ||
| internal HpkeKdf Kdf { get; } | ||
| internal int Nh { get; } | ||
| internal bool IsTwoStage { get; } | ||
| internal string Name { get; } | ||
| internal int MaximumExporterContextLength { get; } | ||
| internal int MaximumInfoLength { get; } | ||
| internal int MaximumPskLength { get; } | ||
| internal int MaximumPskIdLength { get; } | ||
|
|
||
| // HKDF is limited to 255 hash blocks; HPKE encodes SHAKE output lengths in two bytes. | ||
| // https://datatracker.ietf.org/doc/html/draft-ietf-hpke-hpke-04#section-4.4 | ||
| internal int MaximumExportLength => IsTwoStage ? 255 * Nh : ushort.MaxValue; | ||
|
vcsjones marked this conversation as resolved.
|
||
|
|
||
| private HpkeKdfMetadata(HpkeKdf kdf, int nh, bool isTwoStage, string name) | ||
| { | ||
| Debug.Assert(nh <= 64, "Nh value is larger than 64."); | ||
|
|
||
| Kdf = kdf; | ||
| Nh = nh; | ||
| IsTwoStage = isTwoStage; | ||
| Name = name; | ||
| MaximumExporterContextLength = Hpke.MaximumInputSizeInBytes; | ||
|
|
||
| if (IsTwoStage) | ||
| { | ||
| MaximumInfoLength = Hpke.MaximumInputSizeInBytes; | ||
| MaximumPskLength = Hpke.MaximumInputSizeInBytes; | ||
| MaximumPskIdLength = Hpke.MaximumInputSizeInBytes; | ||
| } | ||
| else | ||
| { | ||
| // One-stage KDFs length-prefix each of these inputs with a 16-bit length. | ||
| // https://datatracker.ietf.org/doc/html/draft-ietf-hpke-hpke-04#section-5.1 | ||
| MaximumInfoLength = ushort.MaxValue; | ||
| MaximumPskLength = ushort.MaxValue; | ||
| MaximumPskIdLength = ushort.MaxValue; | ||
| } | ||
| } | ||
|
|
||
| internal static HpkeKdfMetadata? Create(HpkeKdf kdf) | ||
| { | ||
| switch (kdf) | ||
| { | ||
| // HKDF's limits exceed the maximum input size supported by the HPKE API. | ||
| // https://datatracker.ietf.org/doc/html/draft-ietf-hpke-hpke-04#section-7.2 | ||
| case HpkeKdf.HKDF_SHA256: | ||
| return new HpkeKdfMetadata(kdf, nh: 32, isTwoStage: true, name: "HKDF-SHA256"); | ||
| case HpkeKdf.HKDF_SHA384: | ||
| return new HpkeKdfMetadata(kdf, nh: 48, isTwoStage: true, name: "HKDF-SHA384"); | ||
| case HpkeKdf.HKDF_SHA512: | ||
| return new HpkeKdfMetadata(kdf, nh: 64, isTwoStage: true, name: "HKDF-SHA512"); | ||
| case HpkeKdf.SHAKE128: | ||
| return new HpkeKdfMetadata(kdf, nh: 32, isTwoStage: false, name: "SHAKE128"); | ||
| case HpkeKdf.SHAKE256: | ||
| return new HpkeKdfMetadata(kdf, nh: 64, isTwoStage: false, name: "SHAKE256"); | ||
|
|
||
| default: | ||
| return null; | ||
| } | ||
| } | ||
| } | ||
| } | ||
60 changes: 60 additions & 0 deletions
60
src/libraries/Common/src/System/Security/Cryptography/HpkeKem.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Diagnostics.CodeAnalysis; | ||
|
|
||
| namespace System.Security.Cryptography | ||
| { | ||
| /// <summary> | ||
| /// Specifies a key encapsulation mechanism (KEM) for an HPKE cipher suite. | ||
| /// </summary> | ||
| /// <seealso cref="HpkeSuite" /> | ||
| [Experimental(Experimentals.HpkeExperimentalDiagId, UrlFormat = Experimentals.SharedUrlFormat)] | ||
| public enum HpkeKem | ||
| { | ||
| /// <summary> | ||
| /// Indicates that key encapsulation uses DHKEM with the NIST P-256 curve and HKDF-SHA-256. | ||
| /// </summary> | ||
| DHKEM_P256_HKDF_SHA256 = 0x0010, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that key encapsulation uses DHKEM with the NIST P-384 curve and HKDF-SHA-384. | ||
| /// </summary> | ||
| DHKEM_P384_HKDF_SHA384 = 0x0011, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that key encapsulation uses DHKEM with the NIST P-521 curve and HKDF-SHA-512. | ||
| /// </summary> | ||
| DHKEM_P521_HKDF_SHA512 = 0x0012, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that key encapsulation uses DHKEM with X25519 and HKDF-SHA-256. | ||
| /// </summary> | ||
| DHKEM_X25519_HKDF_SHA256 = 0x0020, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that key encapsulation uses ML-KEM-512. | ||
| /// </summary> | ||
| MLKEM_512 = 0x0040, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that key encapsulation uses ML-KEM-768. | ||
| /// </summary> | ||
| MLKEM_768 = 0x0041, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that key encapsulation uses ML-KEM-1024. | ||
| /// </summary> | ||
| MLKEM_1024 = 0x0042, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that key encapsulation combines ML-KEM-768 with ECDH using the NIST P-256 curve. | ||
| /// </summary> | ||
| MLKEM768_P256 = 0x0050, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that key encapsulation combines ML-KEM-1024 with ECDH using the NIST P-384 curve. | ||
| /// </summary> | ||
| MLKEM1024_P384 = 0x0051, | ||
| } | ||
| } |
65 changes: 65 additions & 0 deletions
65
src/libraries/Common/src/System/Security/Cryptography/HpkeKemMetadata.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| namespace System.Security.Cryptography | ||
| { | ||
| internal sealed partial class HpkeKemMetadata | ||
| { | ||
| internal const int MaximumInputKeyingMaterialLength = Hpke.MaximumInputSizeInBytes; | ||
|
|
||
| internal HpkeKem Kem { get; } | ||
| internal int Nsk { get; } | ||
| internal int Npk { get; } | ||
| internal int Nenc { get; } | ||
| internal int Nsecret { get; } | ||
| internal string Name { get; } | ||
|
|
||
| private HpkeKemMetadata(HpkeKem kem, int nsecret, int nenc, int npk, int nsk, string name) | ||
| { | ||
| Kem = kem; | ||
| Nsk = nsk; | ||
| Npk = npk; | ||
| Nenc = nenc; | ||
| Nsecret = nsecret; | ||
| Name = name; | ||
| Setup(); | ||
| } | ||
|
|
||
| partial void Setup(); | ||
|
|
||
| internal static HpkeKemMetadata? Create(HpkeKem kem) | ||
| { | ||
| switch (kem) | ||
| { | ||
| // https://datatracker.ietf.org/doc/html/draft-ietf-hpke-hpke-04#section-7.1 | ||
| case HpkeKem.DHKEM_P256_HKDF_SHA256: | ||
| return new HpkeKemMetadata(kem, nsecret: 32, nenc: 65, npk: 65, nsk: 32, name: "DHKEM(P-256, HKDF-SHA256)"); | ||
| case HpkeKem.DHKEM_P384_HKDF_SHA384: | ||
| return new HpkeKemMetadata(kem, nsecret: 48, nenc: 97, npk: 97, nsk: 48, name: "DHKEM(P-384, HKDF-SHA384)"); | ||
| case HpkeKem.DHKEM_P521_HKDF_SHA512: | ||
| return new HpkeKemMetadata(kem, nsecret: 64, nenc: 133, npk: 133, nsk: 66, name: "DHKEM(P-521, HKDF-SHA512)"); | ||
| case HpkeKem.DHKEM_X25519_HKDF_SHA256: | ||
| return new HpkeKemMetadata(kem, nsecret: 32, nenc: 32, npk: 32, nsk: 32, name: "DHKEM(X25519, HKDF-SHA256)"); | ||
|
|
||
| // https://datatracker.ietf.org/doc/html/draft-ietf-hpke-pq-05#section-8.1 | ||
| // Nsk is the 64-byte seed, not the expanded ML-KEM decapsulation key. | ||
| case HpkeKem.MLKEM_512: | ||
| return new HpkeKemMetadata(kem, nsecret: 32, nenc: 768, npk: 800, nsk: 64, name: "ML-KEM-512"); | ||
| case HpkeKem.MLKEM_768: | ||
| return new HpkeKemMetadata(kem, nsecret: 32, nenc: 1088, npk: 1184, nsk: 64, name: "ML-KEM-768"); | ||
| case HpkeKem.MLKEM_1024: | ||
| return new HpkeKemMetadata(kem, nsecret: 32, nenc: 1568, npk: 1568, nsk: 64, name: "ML-KEM-1024"); | ||
|
|
||
| // https://datatracker.ietf.org/doc/html/draft-ietf-hpke-pq-05#section-8.2 | ||
| // Nsk is the 32-byte seed used to derive both component key pairs. | ||
| case HpkeKem.MLKEM768_P256: | ||
| return new HpkeKemMetadata(kem, nsecret: 32, nenc: 1153, npk: 1249, nsk: 32, name: "MLKEM768-P256"); | ||
| case HpkeKem.MLKEM1024_P384: | ||
| return new HpkeKemMetadata(kem, nsecret: 32, nenc: 1665, npk: 1665, nsk: 32, name: "MLKEM1024-P384"); | ||
|
|
||
| default: | ||
| return null; | ||
| } | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.