Skip to content

[API Proposal]: Add public [Compute/Verify]IntegrityCheck methods to NegotiateAuthentication #86950

Closed
@filipnavara

Description

@filipnavara

Background and motivation

The NegotiateAuthentication API (#69920) was added in .NET 7. It exposes functionality for Negotiate, NTLM and Kerberos authentication. It's implemented as a wrapper over GSSAPI (Unix), SSPI (Windows), and there's managed NTLM implementation for other platforms (Android, tvOS) where native API is not available. The initial API shape was driven by the goal of removing reflection access to internal NTAuthentication class, with focus on meeting the needs of email protocols (SASL in context of IMAP, SMTP), SQL protocols (SQL Server and PostgreSQL), client-side HTTP, and server-side HTTP in ASP.NET.

One omission in the original proposal and its later updates are the GetMIC and VerifyMIC operations defined in GSSAPI (https://datatracker.ietf.org/doc/html/rfc2743). These APIs are not used in any of the scenarios above, but they are needed for more specialized protocols, like the NegotiateStream. It is thus desirable to expose them for public use as well.

The operations implemented by the API are generating a "message integrity code" on one side of the communication protocol and verifying it on the other side. It is usually implemented as cryptographic signing operation with a negotiated key.

API Proposal

namespace System.Net.Security;

public sealed class NegotiateAuthentication : IDisposable
{
    /// <summary>
    /// Computes the message integrity check of a given message.
    /// </summary>
    /// <param name="message">Input message for MIC calculation.</param>
    /// <param name="signature">Buffer writer where the MIC is written.</param>
    /// <remarks>
    /// Implements the GSSAPI GetMIC operation.
    ///
    /// The method modifies the internal state and may update sequence numbers depending on the
    /// selected algorithm. Two successive invocations thus don't produce the same result and
    /// it's important to carefully pair GetMIC and VerifyMIC calls on the both sides of the
    /// authenticated session.
    /// </remarks>
    public void ComputeIntegrityCheck(ReadOnlySpan<byte> message, IBufferWriter<byte> signature);

    /// <summary>
    /// Verifies the message integrity check of a given message.
    /// </summary>
    /// <param name="message">Input message for MIC calculation.</param>
    /// <param name="signature">MIC to be verified.</param>
    /// <returns>For successfully verified MIC, the method returns true.</returns>
    /// <remarks>
    /// Implements the GSSAPI VerifyMIC operation.
    ///
    /// The method modifies the internal state and may update sequence numbers depending on the
    /// selected algorithm. Two successive invocations thus don't produce the same result and
    /// it's important to carefully pair GetMIC and VerifyMIC calls on the both sides of the
    /// authenticated session.
    /// </remarks>
    public bool VerifyIntegrityCheck(ReadOnlySpan<byte> message, ReadOnlySpan<byte> signature);
}

API Usage

// Client:
var signatureBuffer = new ArrayBufferWriter<byte>();
negotiateAuthentication.ComputeIntegrityCheck(message, signatureBuffer);
// Send (message, signatureSize: signatureBuffer.WrittenBytes, signatureSpan: signatureBuffer.WrittenSpan) to server

// Server:
// Reconstruct (message, signatureSize, signatureSpan) from the wire format
if (!negotiateAuthentication.VerifyIntegrityCheck(message, signatureSpan))
    throw new FormatException("The message has been altered");
// Process the message

Alternative Designs

No response

Risks

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions