Repository navigation
Support for Intel SHA extensions #256
Copy link
Copy link
Open
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarch-x64area-System.Runtime.Intrinsics
Milestone
Description
Intel SHA instructions assist with hardware acceleration of the SHA-1 and SHA-256 hash algorithms.
Current Ryzen processors that support these instructions can reach SHA-256 speeds of around 2 GB/s, roughly 4x faster than not using SHA instructions.
Support for these instructions via .NET Core's hardware intrinsics would be useful in SHA-heavy workloads.
Proposed API
namespace System.Runtime.Intrinsics.X86
{
public class Sha
{
/// <summary>
/// __m128i _mm_sha1msg1_epu32 (__m128i a, __m128i b)
/// SHA1MSG1 xmm, xmm/m128
/// </summary>
public static Vector128<byte> Sha1MessageSchedule1(Vector128<byte> a, Vector128<byte> b) => MessageSchedule1(a, b);
/// <summary>
/// __m128i _mm_sha1msg2_epu32 (__m128i a, __m128i b)
/// SHA1MSG2 xmm, xmm/m128
/// </summary>
public static Vector128<byte> Sha1MessageSchedule2(Vector128<byte> a, Vector128<byte> b) => MessageSchedule2(a, b);
/// <summary>
/// __m128i _mm_sha1nexte_epu32 (__m128i a, __m128i b)
/// SHA1NEXTE xmm, xmm/m128
/// </summary>
public static Vector128<byte> Sha1NextE(Vector128<byte> a, Vector128<byte> b) => NextE(a, b);
/// <summary>
/// __m128i _mm_sha1rnds4_epu32 (__m128i a, __m128i b, const int func)
/// SHA1RNDS4 xmm, xmm/m128, imm8
/// </summary>
public static Vector128<byte> Sha1Rounds(Vector128<byte> state1, Vector128<byte> state2, byte func) => Rounds(state1, state2, func);
/// <summary>
/// __m128i _mm_sha256msg1_epu32 (__m128i a, __m128i b)
/// SHA256MSG1 xmm, xmm/m128
/// </summary>
public static Vector128<byte> Sha256MessageSchedule1(Vector128<byte> a, Vector128<byte> b) => MessageSchedule1(a, b);
/// <summary>
/// __m128i _mm_sha256msg2_epu32 (__m128i a, __m128i b)
/// SHA256MSG2 xmm, xmm/m128
/// </summary>
public static Vector128<byte> Sha256MessageSchedule2(Vector128<byte> a, Vector128<byte> b) => MessageSchedule2(a, b);
/// <summary>
/// __m128i _mm_sha256rnds2_epu32 (__m128i a, __m128i b, __m128i k)
/// SHA256RNDS2 xmm, xmm/m128, <XMM0>
/// </summary>
public static Vector128<byte> Sha256Rounds(Vector128<byte> state1, Vector128<byte> state2, Vector128<byte> message) => Rounds(state1, state2, message);
}
}The naming of the functions and parameters still need work.
Reacted by Gregory Bell, Dai, OmariO, neon-sunset, Robin Lindner, Coding Enthusiast, Joel Verhagen and Cole Tobin
Metadata
Metadata
Assignees
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarch-x64area-System.Runtime.Intrinsics
Activity
tannergooding commentedon Nov 26, 2019
@Thealexbarney thanks for the proposal. Our API review process is detailed here: https://github.com/dotnet/runtime/blob/master/docs/project/api-review-process.md
Could you please try to rewrite the original post to explicitly call out the APIs you would like to be added. We have a "good example" of a complete proposal here: https://github.com/dotnet/corefx/issues/271
Namely, we are looking for something like the
Proposed APIsection at a minimum, but adding additional sections can help with the overall review process.In this particular case it looks like there are 7 APIs that would be split between
System.Runtime.Intrinsics.X86.Sha1andSystem.Runtime.Intrinsics.X86.Sha256vcsjones commentedon Nov 26, 2019
I'm curious what the use case is for these intrinisics? The SHA implementations provided by OpenSSL, CNG, etc should already be using these intrinisics. For example, https://github.com/openssl/openssl/blob/3c957bcd54d097167e53660fa100aa1ba85d63b5/crypto/sha/asm/sha256-mb-x86_64.pl#L539
tannergooding commentedon Nov 26, 2019
Realistically no one should be using these intrinsics and they should only be using the known good implementations from locations like
System.Security.However, we've also said that we don't see a reason to block developers from having access to them as other languages (C, C++, Rust, etc) expose the corresponding intrinsics and there may be valid use cases for non-cryptographic scenarios (for example, a fast checksum of a downloaded web file without taking a dependency on a third party, not installed by default, library).
Thealexbarney commentedon Nov 26, 2019
The use case would be similar to the use case of AES-NI intrinsics.
Calling out to an outside implementation often has a performance impact, especially when working with small message sizes. Support for intrinsics would avoid that overhead by keeping that computation in-process. I suppose it also gives developers more freedom in creating their own implementations, although I don't know what benefit that would provide.
GrabYourPitchforks commentedon Nov 26, 2019
I agree that we should make these public for symmetry with AES, but I would strongly implore any developer not to use these APIs unless you really, really, really know what you're doing. Normally, writing secure assembly-level cryptography involves exercising tight control over register allocation, stack spilling, and knowledge about where your thread might be interrupted. The .NET Framework doesn't give developers such low-level control over program compilation and execution, and it's enormously easy to shoot yourself in the foot by making an algorithm which appears to be faster but which in actuality inadvertently leaks secrets.
Thealexbarney commentedon Nov 26, 2019
I've updated the top comment with what the API would look like. The naming of the functions and parameters still need work.
And as a side-note, my current use cases for both AES and SHA intrinsics don't need to be completely secure. Access to intrinsics has greatly sped up AES modes that aren't supported by .NET, close to the performance hand-written assembly would get. XTS mode is ~3-4x faster and doesn't require any tricks to reduce overhead from the crypto API calls.
GrabYourPitchforks commentedon Jan 29, 2020
@tannergooding is there anything missing from the proposal? If not I suppose we can mark it ready for review.
14 remaining items
deeprobin commentedon Dec 19, 2021
@tannergooding, happy to assign to me. :)
danmoseley commentedon Dec 20, 2021
Did we end up with the linked analyzer proposal mentioned above?
deeprobin commentedon Jan 7, 2022
@tannergooding You said in the Approval video that there are two different CPUID flags.
However, under x86 there is only one CPUID flag "SHA".
Also, it is difficult to generate these classes with the ThunkGenerator (see #62999 (comment)), as this is an exceptional case (for reference: C# Discord #lowlevel conversation).
Could you enlighten us? If this was a mistake, I would suggest the following:
/cc @saucecontrol
/cc @MichalStrehovsky
deeprobin commentedon Jan 7, 2022
Judging from the title of Issue dotnet/roslyn-analyzers#3646, the issue is not only AES-specific but general for cryptographic types
tannergooding commentedon Jan 7, 2022
It was likely a misstatement or misremembering, etc.
The proposed names look like what I was going to suggest, but we'll need to take it back to API review in either case.
tannergooding commentedon Jan 11, 2022
Updated the proposal, it needs to go back through API review.
bartonjs commentedon Jan 18, 2022
Video
Generally looks good as proposed.
Parameter names and the
*Roundsmethod names were aligned with the previously approved version.tannergooding commentedon Jan 18, 2022
The baseline should be
SSE2, matchingAES. This is dependent on theSIMDregisters (and so therefore dependent onSSE) and is dependent on the integer based SIMD support (and so therefore dependent onSSE2).Most ISAs in the architecture manual have documentation similar to the following:
Unfortunately the SHA Extensions ISA does not have any such documentation; not even a section stating to just check
CPUID.07H:EBX.SHA[bit 29] = 1. However, given when it was released, the features it uses, and other considerations SSE2 is the logical dependency.I'll be following up with our friends at Intel/AMD to confirm it isn't something later instead; but SSE2 is the correct starting point.
deeprobin commentedon May 25, 2022
For tracking: The implementation is basically ready in #62999 - only the changes to the JIT/VM are buggy (bad codegen ->
SEHException).SEHException.If someone JIT-experienced is looking for a little challenge, you are welcome to have a look.