summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/ssl/sslexp.h
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/ssl/sslexp.h')
-rw-r--r--security/nss/lib/ssl/sslexp.h358
1 files changed, 358 insertions, 0 deletions
diff --git a/security/nss/lib/ssl/sslexp.h b/security/nss/lib/ssl/sslexp.h
new file mode 100644
index 000000000..569add861
--- /dev/null
+++ b/security/nss/lib/ssl/sslexp.h
@@ -0,0 +1,358 @@
+/*
+ * This file contains prototypes for experimental SSL functions.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __sslexp_h_
+#define __sslexp_h_
+
+#include "ssl.h"
+#include "sslerr.h"
+
+SEC_BEGIN_PROTOS
+
+/* The functions in this header file are not guaranteed to remain available in
+ * future NSS versions. Code that uses these functions needs to safeguard
+ * against the function not being available. */
+
+#define SSL_EXPERIMENTAL_API(name, arglist, args) \
+ (SSL_GetExperimentalAPI(name) \
+ ? ((SECStatus(*) arglist)SSL_GetExperimentalAPI(name))args \
+ : SECFailure)
+#define SSL_DEPRECATED_EXPERIMENTAL_API \
+ (PR_SetError(SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API, 0), SECFailure)
+
+/*
+ * SSL_GetExtensionSupport() returns whether NSS supports a particular TLS
+ * extension.
+ *
+ * - ssl_ext_none indicates that NSS does not support the extension and
+ * extension hooks can be installed.
+ *
+ * - ssl_ext_native indicates that NSS supports the extension natively, but
+ * allows an application to override that support and install its own
+ * extension hooks.
+ *
+ * - ssl_ext_native_only indicates that NSS supports the extension natively
+ * and does not permit custom extension hooks to be installed. These
+ * extensions are critical to the functioning of NSS.
+ */
+typedef enum {
+ ssl_ext_none,
+ ssl_ext_native,
+ ssl_ext_native_only
+} SSLExtensionSupport;
+
+#define SSL_GetExtensionSupport(extension, support) \
+ SSL_EXPERIMENTAL_API("SSL_GetExtensionSupport", \
+ (PRUint16 _extension, \
+ SSLExtensionSupport * _support), \
+ (extension, support))
+
+/*
+ * Custom extension hooks.
+ *
+ * The SSL_InstallExtensionHooks() registers two callback functions for use
+ * with the identified extension type.
+ *
+ * Installing extension hooks disables the checks in TLS 1.3 that ensure that
+ * extensions are only added to the correct messages. The application is
+ * responsible for ensuring that extensions are only sent with the right message
+ * or messages.
+ *
+ * Installing an extension handler does not disable checks for whether an
+ * extension can be used in a message that is a response to an extension in
+ * another message. Extensions in ServerHello, EncryptedExtensions and the
+ * server Certificate messages are rejected unless the client sends an extension
+ * in the ClientHello. Similarly, a client Certificate message cannot contain
+ * extensions that don't appear in a CertificateRequest (in TLS 1.3).
+ *
+ * Setting both |writer| and |handler| to NULL removes any existing hooks for
+ * that extension.
+ *
+ * == SSLExtensionWriter
+ *
+ * An SSLExtensionWriter function is responsible for constructing the contents
+ * of an extension. This function is called during the construction of all
+ * handshake messages where an extension might be included.
+ *
+ * - The |fd| argument is the socket file descriptor.
+ *
+ * - The |message| argument is the TLS handshake message type. The writer will
+ * be called for every handshake message that NSS sends. Most extensions
+ * should only be sent in a subset of messages. NSS doesn’t check that
+ * extension writers don’t violate protocol rules regarding which message an
+ * extension can be sent in.
+ *
+ * - The |data| argument is a pointer to a buffer that should be written to with
+ * any data for the extension.
+ *
+ * - The |len| argument is an outparam indicating how many bytes were written to
+ * |data|. The value referenced by |len| is initialized to zero, so an
+ * extension that is empty does not need to write to this value.
+ *
+ * - The |maxLen| indicates the maximum number of bytes that can be written to
+ * |data|.
+ *
+ * - The |arg| argument is the value of the writerArg that was passed during
+ * installation.
+ *
+ * An SSLExtensionWriter function returns PR_TRUE if an extension should be
+ * written, and PR_FALSE otherwise.
+ *
+ * If there is an error, return PR_FALSE; if the error is truly fatal, the
+ * application can mark the connection as failed. However, recursively calling
+ * functions that alter the file descriptor in the callback - such as PR_Close()
+ * - should be avoided.
+ *
+ * Note: The ClientHello message can be sent twice in TLS 1.3. An
+ * SSLExtensionWriter will be called twice with the same arguments in that case;
+ * NSS does not distinguish between a first and second ClientHello. It is up to
+ * the application to track this if it needs to act differently each time. In
+ * most cases the correct behaviour is to provide an identical extension on each
+ * invocation.
+ *
+ * == SSLExtensionHandler
+ *
+ * An SSLExtensionHandler function consumes a handshake message. This function
+ * is called when an extension is present.
+ *
+ * - The |fd| argument is the socket file descriptor.
+ *
+ * - The |message| argument is the TLS handshake message type. This can be used
+ * to validate that the extension was included in the correct handshake
+ * message.
+ *
+ * - The |data| argument points to the contents of the extension.
+ *
+ * - The |len| argument contains the length of the extension.
+ *
+ * - The |alert| argument is an outparam that allows an application to choose
+ * which alert is sent in the case of a fatal error.
+ *
+ * - The |arg| argument is the value of the handlerArg that was passed during
+ * installation.
+ *
+ * An SSLExtensionHandler function returns SECSuccess when the extension is
+ * process successfully. It can return SECFailure to cause the handshake to
+ * fail. If the value of alert is written to, NSS will generate a fatal alert
+ * using the provided alert code. The value of |alert| is otherwise not used.
+ */
+typedef PRBool(PR_CALLBACK *SSLExtensionWriter)(
+ PRFileDesc *fd, SSLHandshakeType message,
+ PRUint8 *data, unsigned int *len, unsigned int maxLen, void *arg);
+
+typedef SECStatus(PR_CALLBACK *SSLExtensionHandler)(
+ PRFileDesc *fd, SSLHandshakeType message,
+ const PRUint8 *data, unsigned int len,
+ SSLAlertDescription *alert, void *arg);
+
+#define SSL_InstallExtensionHooks(fd, extension, writer, writerArg, \
+ handler, handlerArg) \
+ SSL_EXPERIMENTAL_API("SSL_InstallExtensionHooks", \
+ (PRFileDesc * _fd, PRUint16 _extension, \
+ SSLExtensionWriter _writer, void *_writerArg, \
+ SSLExtensionHandler _handler, void *_handlerArg), \
+ (fd, extension, writer, writerArg, \
+ handler, handlerArg))
+
+/*
+ * Setup the anti-replay buffer for supporting 0-RTT in TLS 1.3 on servers.
+ *
+ * To use 0-RTT on a server, you must call this function. Failing to call this
+ * function will result in all 0-RTT being rejected. Connections will complete,
+ * but early data will be rejected.
+ *
+ * NSS uses a Bloom filter to track the ClientHello messages that it receives
+ * (specifically, it uses the PSK binder). This function initializes a pair of
+ * Bloom filters. The two filters are alternated over time, with new
+ * ClientHello messages recorded in the current filter and, if they are not
+ * already present, being checked against the previous filter. If the
+ * ClientHello is found, then early data is rejected, but the handshake is
+ * allowed to proceed.
+ *
+ * The false-positive probability of Bloom filters means that some valid
+ * handshakes will be marked as potential replays. Early data will be rejected
+ * for a false positive. To minimize this and to allow a trade-off of space
+ * against accuracy, the size of the Bloom filter can be set by this function.
+ *
+ * The first tuning parameter to consider is |window|, which determines the
+ * window over which ClientHello messages will be tracked. This also causes
+ * early data to be rejected if a ClientHello contains a ticket age parameter
+ * that is outside of this window (see Section 4.2.10.4 of
+ * draft-ietf-tls-tls13-20 for details). Set |window| to account for any
+ * potential sources of clock error. |window| is the entire width of the
+ * window, which is symmetrical. Therefore to allow 5 seconds of clock error in
+ * both directions, set the value to 10 seconds (i.e., 10 * PR_USEC_PER_SEC).
+ *
+ * After calling this function, early data will be rejected until |window|
+ * elapses. This prevents replay across crashes and restarts. Only call this
+ * function once to avoid inadvertently disabling 0-RTT (use PR_CallOnce() to
+ * avoid this problem).
+ *
+ * The primary tuning parameter is |bits| which determines the amount of memory
+ * allocated to each Bloom filter. NSS will allocate two Bloom filters, each
+ * |2^(bits - 3)| octets in size. The value of |bits| is primarily driven by
+ * the number of connections that are expected in any time window. Note that
+ * this needs to account for there being two filters both of which have
+ * (presumably) independent false positive rates. The following formulae can be
+ * used to find a value of |bits| and |k| given a chosen false positive
+ * probability |p| and the number of requests expected in a given window |n|:
+ *
+ * bits = log2(n) + log2(-ln(1 - sqrt(1 - p))) + 1.0575327458897952
+ * k = -log2(p)
+ *
+ * ... where log2 and ln are base 2 and e logarithms respectively. For a target
+ * false positive rate of 1% and 1000 handshake attempts, this produces bits=14
+ * and k=7. This results in two Bloom filters that are 2kB each in size. Note
+ * that rounding |k| and |bits| up causes the false positive probability for
+ * these values to be a much lower 0.123%.
+ *
+ * IMPORTANT: This anti-replay scheme has several weaknesses. See the TLS 1.3
+ * specification for the details of the generic problems with this technique.
+ *
+ * In addition to the generic anti-replay weaknesses, the state that the server
+ * maintains is in local memory only. Servers that operate in a cluster, even
+ * those that use shared memory for tickets, will not share anti-replay state.
+ * Early data can be replayed at least once with every server instance that will
+ * accept tickets that are encrypted with the same key.
+ */
+#define SSL_SetupAntiReplay(window, k, bits) \
+ SSL_EXPERIMENTAL_API("SSL_SetupAntiReplay", \
+ (PRTime _window, unsigned int _k, unsigned int _bits), \
+ (window, k, bits))
+
+/*
+ * This function allows a server application to generate a session ticket that
+ * will embed the provided token.
+ *
+ * This function will cause a NewSessionTicket message to be sent by a server.
+ * This happens even if SSL_ENABLE_SESSION_TICKETS is disabled. This allows a
+ * server to suppress the usually automatic generation of a session ticket at
+ * the completion of the handshake - which do not include any token - and to
+ * control when session tickets are transmitted.
+ *
+ * This function will fail unless the socket has an active TLS 1.3 session.
+ * Earlier versions of TLS do not support the spontaneous sending of the
+ * NewSessionTicket message.
+ */
+#define SSL_SendSessionTicket(fd, appToken, appTokenLen) \
+ SSL_EXPERIMENTAL_API("SSL_SendSessionTicket", \
+ (PRFileDesc * _fd, const PRUint8 *_appToken, \
+ unsigned int _appTokenLen), \
+ (fd, appToken, appTokenLen))
+
+/*
+ * A stateless retry handler gives an application some control over NSS handling
+ * of ClientHello messages.
+ *
+ * SSL_HelloRetryRequestCallback() installs a callback that allows an
+ * application to control how NSS sends HelloRetryRequest messages. This
+ * handler is only used on servers and will only be called if the server selects
+ * TLS 1.3. Support for older TLS versions could be added in other releases.
+ *
+ * The SSLHelloRetryRequestCallback is invoked during the processing of a
+ * TLS 1.3 ClientHello message. It takes the following arguments:
+ *
+ * - |firstHello| indicates if the NSS believes that this is an initial
+ * ClientHello. An initial ClientHello will never include a cookie extension,
+ * though it may contain a session ticket.
+ *
+ * - |clientToken| includes a token previously provided by the application. If
+ * |clientTokenLen| is 0, then |clientToken| may be NULL.
+ *
+ * - If |firstHello| is PR_FALSE, the value that was provided in the
+ * |retryToken| outparam of previous invocations of this callback will be
+ * present here.
+ *
+ * - If |firstHello| is PR_TRUE, and the handshake is resuming a session, then
+ * this will contain any value that was passed in the |token| parameter of
+ * SSL_SendNewSessionTicket() method (see below). If this is not resuming a
+ * session, then the token will be empty (and this value could be NULL).
+ *
+ * - |clientTokenLen| is the length of |clientToken|.
+ *
+ * - |retryToken| is an item that callback can write to. This provides NSS with
+ * a token. This token is encrypted and integrity protected and embedded in
+ * the cookie extension of a HelloRetryRequest. The value of this field is
+ * only used if the handler returns ssl_stateless_retry_check. NSS allocates
+ * space for this value.
+ *
+ * - |retryTokenLen| is an outparam for the length of the token. If this value
+ * is not set, or set to 0, an empty token will be sent.
+ *
+ * - |retryTokenMax| is the size of the space allocated for retryToken. An
+ * application cannot write more than this many bytes to retryToken.
+ *
+ * - |arg| is the same value that was passed to
+ * SSL_InstallStatelessRetryHandler().
+ *
+ * The handler can validate any the value of |clientToken|, query the socket
+ * status (using SSL_GetPreliminaryChannelInfo() for example) and decide how to
+ * proceed:
+ *
+ * - Returning ssl_hello_retry_fail causes the handshake to fail. This might be
+ * used if the token is invalid or the application wishes to abort the
+ * handshake.
+ *
+ * - Returning ssl_hello_retry_accept causes the handshake to proceed.
+ *
+ * - Returning ssl_hello_retry_request causes NSS to send a HelloRetryRequest
+ * message and request a second ClientHello. NSS generates a cookie extension
+ * and embeds the value of |retryToken|. The value of |retryToken| value may
+ * be left empty if the application does not require any additional context to
+ * validate a second ClientHello attempt. This return code cannot be used to
+ * reject a second ClientHello (i.e., when firstHello is PR_FALSE); NSS will
+ * abort the handshake if this value is returned from a second call.
+ *
+ * An application that chooses to perform a stateless retry can discard the
+ * server socket. All necessary state to continue the TLS handshake will be
+ * included in the cookie extension. This makes it possible to use a new socket
+ * to handle the remainder of the handshake. The existing socket can be safely
+ * discarded.
+ *
+ * If the same socket is retained, the information in the cookie will be checked
+ * for consistency against the existing state of the socket. Any discrepancy
+ * will result in the connection being closed.
+ *
+ * Tokens should be kept as small as possible. NSS sets a limit on the size of
+ * tokens, which it passes in |retryTokenMax|. Depending on circumstances,
+ * observing a smaller limit might be desirable or even necessary. For
+ * instance, having HelloRetryRequest and ClientHello fit in a single packet has
+ * significant performance benefits.
+ */
+typedef enum {
+ ssl_hello_retry_fail,
+ ssl_hello_retry_accept,
+ ssl_hello_retry_request
+} SSLHelloRetryRequestAction;
+
+typedef SSLHelloRetryRequestAction(PR_CALLBACK *SSLHelloRetryRequestCallback)(
+ PRBool firstHello, const PRUint8 *clientToken, unsigned int clientTokenLen,
+ PRUint8 *retryToken, unsigned int *retryTokenLen, unsigned int retryTokMax,
+ void *arg);
+
+#define SSL_HelloRetryRequestCallback(fd, cb, arg) \
+ SSL_EXPERIMENTAL_API("SSL_HelloRetryRequestCallback", \
+ (PRFileDesc * _fd, \
+ SSLHelloRetryRequestCallback _cb, void *_arg), \
+ (fd, cb, arg))
+
+/* Update traffic keys (TLS 1.3 only).
+ *
+ * The |requestUpdate| flag determines whether to request an update from the
+ * remote peer.
+ */
+#define SSL_KeyUpdate(fd, requestUpdate) \
+ SSL_EXPERIMENTAL_API("SSL_KeyUpdate", \
+ (PRFileDesc * _fd, PRBool _requestUpdate), \
+ (fd, requestUpdate))
+
+#define SSL_UseAltServerHelloType(fd, enable) \
+ SSL_DEPRECATED_EXPERIMENTAL_API
+
+SEC_END_PROTOS
+
+#endif /* __sslexp_h_ */