| | | 1 | | // Licensed to the .NET Foundation under one or more agreements. |
| | | 2 | | // The .NET Foundation licenses this file to you under the MIT license. |
| | | 3 | | |
| | | 4 | | using System.Diagnostics.CodeAnalysis; |
| | | 5 | | using System.Security.Authentication; |
| | | 6 | | |
| | | 7 | | namespace System.Net.Security |
| | | 8 | | { |
| | | 9 | | /// <summary> |
| | | 10 | | /// Non-blocking TLS state machine driven by caller-supplied byte spans. |
| | | 11 | | /// The session object performs no I/O; the caller is responsible for |
| | | 12 | | /// performing I/O, such as transmitting the output of <see cref="Write"/>. |
| | | 13 | | /// </summary> |
| | | 14 | | /// <remarks> |
| | | 15 | | /// A newly-constructed instance has no <see cref="TlsContext"/>. Call |
| | | 16 | | /// <see cref="TlsSession.SetContext"/> with a client or server context before |
| | | 17 | | /// invoking any operation. Server-side deferred flow (SNI-driven context |
| | | 18 | | /// selection) is supported by passing an empty |
| | | 19 | | /// <see cref="SslServerAuthenticationOptions"/> to <c>TlsContext.CreateServer</c>; |
| | | 20 | | /// the first <c>Handshake</c> call then suspends on |
| | | 21 | | /// <see cref="TlsOperationStatus.NeedsTlsContext"/> so the caller can supply the |
| | | 22 | | /// resolved per-tenant context via <see cref="TlsSession.SetContext"/>. |
| | | 23 | | /// </remarks> |
| | | 24 | | [Experimental(Experimentals.LowLevelTlsDiagId, UrlFormat = Experimentals.SharedUrlFormat)] |
| | | 25 | | public sealed class TlsBufferSession : TlsSession |
| | | 26 | | { |
| | | 27 | | /// <summary>Drives the TLS handshake forward using caller-supplied ciphertext.</summary> |
| | | 28 | | /// <param name="source">Bytes received from the peer.</param> |
| | | 29 | | /// <param name="destination">Buffer to receive any handshake bytes that must be sent to the peer.</param> |
| | | 30 | | /// <param name="bytesConsumed">The number of bytes read from <paramref name="source"/>.</param> |
| | | 31 | | /// <param name="bytesWritten">The number of bytes written to <paramref name="destination"/>.</param> |
| | | 32 | | /// <returns>The outcome of the operation.</returns> |
| | | 33 | | /// <exception cref="ObjectDisposedException">The session has been disposed.</exception> |
| | | 34 | | /// <exception cref="InvalidOperationException">A <see cref="TlsContext"/> has not been assigned via <see cref=" |
| | | 35 | | /// <exception cref="AuthenticationException">The handshake failed.</exception> |
| | | 36 | | public TlsOperationStatus Handshake(ReadOnlySpan<byte> source, Span<byte> destination, out int bytesConsumed, ou |
| | 0 | 37 | | => HandshakeBufferedCore(source, destination, out bytesConsumed, out bytesWritten); |
| | | 38 | | |
| | | 39 | | /// <summary>Encrypts application-plaintext into ciphertext records.</summary> |
| | | 40 | | /// <param name="source">Plaintext bytes to encrypt.</param> |
| | | 41 | | /// <param name="destination">Buffer to receive the produced ciphertext records.</param> |
| | | 42 | | /// <param name="bytesConsumed">The number of plaintext bytes read from <paramref name="source"/>.</param> |
| | | 43 | | /// <param name="bytesWritten">The number of ciphertext bytes written to <paramref name="destination"/>.</param> |
| | | 44 | | /// <returns>The outcome of the operation.</returns> |
| | | 45 | | /// <exception cref="ObjectDisposedException">The session has been disposed.</exception> |
| | | 46 | | /// <exception cref="InvalidOperationException">The handshake has not yet completed.</exception> |
| | | 47 | | public TlsOperationStatus Write(ReadOnlySpan<byte> source, Span<byte> destination, out int bytesConsumed, out in |
| | 0 | 48 | | => WriteBufferedCore(source, destination, out bytesConsumed, out bytesWritten); |
| | | 49 | | |
| | | 50 | | /// <summary>Decrypts ciphertext records into application-plaintext.</summary> |
| | | 51 | | /// <param name="source">Ciphertext bytes received from the peer.</param> |
| | | 52 | | /// <param name="destination">Buffer to receive the decrypted plaintext.</param> |
| | | 53 | | /// <param name="bytesConsumed">The number of ciphertext bytes read from <paramref name="source"/>.</param> |
| | | 54 | | /// <param name="bytesWritten">The number of plaintext bytes written to <paramref name="destination"/>.</param> |
| | | 55 | | /// <returns>The outcome of the operation.</returns> |
| | | 56 | | /// <exception cref="ObjectDisposedException">The session has been disposed.</exception> |
| | | 57 | | /// <exception cref="InvalidOperationException">The handshake has not yet completed.</exception> |
| | | 58 | | public TlsOperationStatus Read(ReadOnlySpan<byte> source, Span<byte> destination, out int bytesConsumed, out int |
| | 0 | 59 | | => ReadBufferedCore(source, destination, out bytesConsumed, out bytesWritten); |
| | | 60 | | |
| | | 61 | | /// <summary>Initiates a TLS <c>close_notify</c> alert; writes the alert record into <paramref name="destination |
| | | 62 | | /// <param name="destination">Buffer to receive the <c>close_notify</c> alert record.</param> |
| | | 63 | | /// <param name="bytesWritten">The number of bytes written to <paramref name="destination"/>.</param> |
| | | 64 | | /// <returns>The outcome of the operation.</returns> |
| | | 65 | | /// <exception cref="ObjectDisposedException">The session has been disposed.</exception> |
| | | 66 | | public TlsOperationStatus Shutdown(Span<byte> destination, out int bytesWritten) |
| | 0 | 67 | | => ShutdownBufferedCore(destination, out bytesWritten); |
| | | 68 | | |
| | | 69 | | /// <summary>Drains any staged pending output (handshake fragments, alerts, encrypted records) into <paramref na |
| | | 70 | | /// <param name="destination">Buffer to receive the pending ciphertext.</param> |
| | | 71 | | /// <param name="bytesWritten">The number of bytes written to <paramref name="destination"/>.</param> |
| | | 72 | | /// <returns>The outcome of the operation.</returns> |
| | | 73 | | /// <exception cref="ObjectDisposedException">The session has been disposed.</exception> |
| | | 74 | | public TlsOperationStatus DrainPendingOutput(Span<byte> destination, out int bytesWritten) |
| | 0 | 75 | | => DrainPendingOutputCore(destination, out bytesWritten); |
| | | 76 | | |
| | | 77 | | /// <summary>Server-side only. Requests a client certificate from the peer: a <c>CertificateRequest</c> for TLS |
| | | 78 | | /// <param name="destination">Buffer to receive the request record.</param> |
| | | 79 | | /// <param name="bytesWritten">The number of bytes written to <paramref name="destination"/>.</param> |
| | | 80 | | /// <returns>The outcome of the operation.</returns> |
| | | 81 | | /// <remarks> |
| | | 82 | | /// If the TLS 1.3 client did not offer post-handshake authentication, no request is sent: the method returns |
| | | 83 | | /// <see cref="TlsOperationStatus.Complete"/> with <paramref name="bytesWritten"/> set to 0, the handshake stays |
| | | 84 | | /// complete, no client certificate is received, and the session remains usable. |
| | | 85 | | /// </remarks> |
| | | 86 | | /// <exception cref="ObjectDisposedException">The session has been disposed.</exception> |
| | | 87 | | /// <exception cref="InvalidOperationException">The session is client-side, or the handshake has not yet complet |
| | | 88 | | /// <exception cref="PlatformNotSupportedException">The current platform does not support post-handshake authent |
| | | 89 | | public TlsOperationStatus RequestClientCertificate(Span<byte> destination, out int bytesWritten) |
| | 0 | 90 | | => RequestClientCertificateBufferedCore(destination, out bytesWritten); |
| | | 91 | | } |
| | | 92 | | } |
| | | 93 | | |