TLS 1.2
TLS 1.2 is a legacy protocol version. New deployments should use TLS 1.3 where possible, and existing TLS 1.2 deployments should plan an upgrade path to TLS 1.3.
TLS 1.0, 1.1, and 1.2 implementation. Header: noxtls_tls12.h. Context extends dtls_context_t (which contains tls_context_t).
Types
tls12_context_t
TLS 1.2 context: base DTLS/TLS context plus handshake state (client/server random, cipher suite, keys, IVs, MAC keys, sequence numbers), server certificate, optional server RSA private key or crypto provider handle, key exchange (premaster secret, master secret, ECDHE/DHE context), handshake message buffer, client/server extensions, SNI, renegotiation and RFC 6066 max fragment length, RPK (RFC 7250) options, and workspace buffers. Initialized with noxtls_tls12_context_init or noxtls_tls12_context_init_with_version, freed with noxtls_tls12_context_free.
API
Context
noxtls_tls12_context_init
noxtls_return_t noxtls_tls12_context_init(tls12_context_t *ctx, tls_role_t role);
Initialize TLS 1.2 context (default TLS 1.2). Set I/O callbacks on ctx->base.base before connect/accept.
Returns: noxtls_return_t.
noxtls_tls12_context_init_with_version
noxtls_return_t noxtls_tls12_context_init_with_version(tls12_context_t *ctx, tls_role_t role, uint16_t version);
Initialize for a specific version: TLS_VERSION_1_0, TLS_VERSION_1_1, or TLS_VERSION_1_2.
Returns: noxtls_return_t.
noxtls_dtls12_context_init
noxtls_return_t noxtls_dtls12_context_init(tls12_context_t *ctx, tls_role_t role);
Initialize for DTLS 1.2. Use noxtls_dtls_set_mtu and related DTLS options as needed.
Returns: noxtls_return_t.
noxtls_tls12_context_free
noxtls_return_t noxtls_tls12_context_free(tls12_context_t *ctx);
Free TLS 1.2 context and owned resources. Since 0.3.0 this also erases, with noxtls_secure_zero(), the secrets held in the caller-owned context: premaster and master secret, traffic keys, IVs, MAC keys, Finished data, and buffered application plaintext.
Returns: noxtls_return_t.
noxtls_tls12_context_size
uint32_t noxtls_tls12_context_size(void);
New in 0.3.0. Returns sizeof(tls12_context_t) as compiled into the library. Compare it with sizeof(tls12_context_t) in your own translation units to detect a noxtls_config.h mismatch, such as a different NOXTLS_TLS_MAX_RECORD_SIZE. Such a mismatch otherwise corrupts memory silently.
if (noxtls_tls12_context_size() != (uint32_t)sizeof(tls12_context_t)) {
/* library and application were built with different configurations */
}
Handshake and data
noxtls_tls12_connect
noxtls_return_t noxtls_tls12_connect(tls12_context_t *ctx);
Run full client handshake (Client Hello through Finished). Set server certificate verification expectations and optional SNI before calling.
Returns: noxtls_return_t.
noxtls_tls12_connect_poll
noxtls_return_t noxtls_tls12_connect_poll(tls12_context_t *ctx);
Advance an initial client handshake when the base context uses
TLS_IO_MODE_NON_BLOCKING. Repeatedly call it until it returns success or a
terminal error. NOXTLS_RETURN_WANT_READ and NOXTLS_RETURN_WANT_WRITE are
resumable outcomes; flush pending output when the transport is writable.
noxtls_tls12_accept
noxtls_return_t noxtls_tls12_accept(tls12_context_t *ctx);
Run full server handshake. Set server certificate and, for ECDHE-RSA/DHE-RSA, the server private key (or crypto provider) before calling.
Returns: noxtls_return_t.
noxtls_tls12_accept_poll
noxtls_return_t noxtls_tls12_accept_poll(tls12_context_t *ctx);
Server equivalent of noxtls_tls12_connect_poll(). Configure I/O and server
credentials before the first call.
noxtls_tls12_send
noxtls_return_t noxtls_tls12_send(tls12_context_t *ctx, const uint8_t *data, uint32_t len);
Send application data (encrypted records). Call after handshake completes.
Returns: noxtls_return_t.
noxtls_tls12_recv
noxtls_return_t noxtls_tls12_recv(tls12_context_t *ctx, uint8_t *data, uint32_t *len);
Receive application data. len is in/out: maximum buffer size in, actual bytes read out.
Returns: noxtls_return_t.
noxtls_tls12_close
noxtls_return_t noxtls_tls12_close(tls12_context_t *ctx);
Send close_notify and transition to closing/closed state.
Returns: noxtls_return_t.
Server renegotiation
noxtls_tls12_send_hello_request
noxtls_return_t noxtls_tls12_send_hello_request(tls12_context_t *ctx);
Send HelloRequest to ask the client to renegotiate (RFC 5746).
Returns: noxtls_return_t.
Server key and certificate
noxtls_tls12_set_server_private_rsa
void noxtls_tls12_set_server_private_rsa(tls12_context_t *ctx, void *rsa_key);
Set server RSA private key (rsa_key_t*) for Server Key Exchange signature. Call before handshake when using ECDHE_RSA or DHE_RSA.
noxtls_tls12_set_crypto_provider_server
void noxtls_tls12_set_crypto_provider_server(tls12_context_t *ctx, const noxtls_crypto_provider_t *provider, noxtls_crypto_key_handle_t server_key_handle);
Use a crypto provider (e.g. HSM/TPM) for server signing and decrypting Client Key Exchange instead of server_private_rsa. Call before handshake.
Raw Public Key (RFC 7250)
noxtls_tls12_set_server_use_rpk
void noxtls_tls12_set_server_use_rpk(tls12_context_t *ctx, int use_rpk);
Server: send Raw Public Key. Set server_cert/server_cert_len to SubjectPublicKeyInfo (DER). Call before handshake.
noxtls_tls12_set_client_accept_server_rpk
void noxtls_tls12_set_client_accept_server_rpk(tls12_context_t *ctx, int accept);
Client: advertise acceptance of server RPK (server_certificate_type extension). Call before connect.
noxtls_tls12_set_client_offer_client_rpk
void noxtls_tls12_set_client_offer_client_rpk(tls12_context_t *ctx, int offer);
Client: offer to send RPK for client auth (client_certificate_type extension). Call before connect.
Max fragment length (RFC 6066)
noxtls_tls12_set_max_fragment_length
void noxtls_tls12_set_max_fragment_length(tls12_context_t *ctx, uint8_t code);
Set max fragment length: 0 = disabled; 1 = 512, 2 = 1024, 3 = 2048, 4 = 4096 bytes. Call before handshake.
noxtls_tls12_require_client_auth
void noxtls_tls12_require_client_auth(tls12_context_t *ctx, int require);
Server: require a non-empty client certificate. A nonzero value implies
noxtls_tls12_request_client_auth() and fails the handshake if the client
responds with an empty Certificate message.
noxtls_tls12_set_client_verify_policy
void noxtls_tls12_set_client_verify_policy(tls12_context_t *ctx,
const struct noxtls_x509_verify_policy *policy);
New in 0.3.0. Server: verify client certificates against an explicit X.509 verification policy (trust anchors, key usage, EKU, time source) instead of the global trust store. Pass NULL to restore the global behavior. The policy is not copied and must stay valid for the lifetime of the handshake.
While a policy is set:
- The client chain is verified only against
policy->trust_anchors. A policy with no anchors fails closed. - Session-ID and session-ticket resumption are declined, so every connection re-authenticates the client. The caches keep no peer identity.
- A rejected client certificate is not left in the context.
Combine it with noxtls_tls12_require_client_auth() to reject clients that send no certificate.
noxtls_tls12_get_client_certificate
noxtls_return_t noxtls_tls12_get_client_certificate(const tls12_context_t *ctx,
const uint8_t **der,
uint32_t *der_len,
const void **parsed);
New in 0.3.0. Server: after the handshake, returns the accepted client leaf as DER. If parsed is non-NULL, it also returns the parsed x509_certificate_t, as an opaque pointer. The pointers stay valid until the context is freed. Returns NOXTLS_RETURN_FAILED when no client certificate was accepted.
static noxtls_x509_verify_policy_t policy; /* must outlive the handshake */
policy.trust_anchors = &commissioning_ca_chain;
policy.required_key_usage = X509_KEY_USAGE_DIGITAL_SIGNATURE;
policy.time_mode = NOXTLS_X509_TIME_SYSTEM;
noxtls_tls12_require_client_auth(&server, 1);
noxtls_tls12_set_client_verify_policy(&server, &policy);
/* ... noxtls_tls12_accept() or noxtls_tls12_accept_poll() ... */
const uint8_t *leaf; uint32_t leaf_len; const void *parsed;
if (noxtls_tls12_get_client_certificate(&server, &leaf, &leaf_len, &parsed) == NOXTLS_RETURN_SUCCESS) {
noxtls_x509_extension_t ext; int found;
(void)noxtls_x509_certificate_find_extension((const x509_certificate_t *)parsed,
oid, oid_len, &ext, &found);
}
See also docs/CLIENT_CERTIFICATE_AUTHENTICATION.md in the repository.
Key derivation (internal use)
tls12_compute_master_secret
noxtls_return_t tls12_compute_master_secret(tls12_context_t *ctx, const uint8_t *premaster_secret, uint32_t premaster_secret_len);
Compute master secret from premaster secret. Used internally during handshake.
Returns: noxtls_return_t.
tls12_derive_keys
noxtls_return_t tls12_derive_keys(tls12_context_t *ctx);
Derive record protection keys from master secret. Used internally.
Returns: noxtls_return_t.
Client handshake steps (optional fine-grained control)
- noxtls_tls12_send_client_hello, noxtls_tls12_recv_server_hello, noxtls_tls12_recv_certificate, noxtls_tls12_recv_server_key_exchange, noxtls_tls12_recv_server_hello_done
- noxtls_tls12_send_client_key_exchange, noxtls_tls12_send_change_cipher_spec, noxtls_tls12_send_finished
- noxtls_tls12_recv_change_cipher_spec, noxtls_tls12_recv_finished
Server handshake steps (optional fine-grained control)
- noxtls_tls12_recv_client_hello, noxtls_tls12_send_server_hello, noxtls_tls12_send_certificate, noxtls_tls12_send_server_key_exchange, noxtls_tls12_send_server_hello_done
- noxtls_tls12_recv_client_key_exchange, noxtls_tls12_recv_change_cipher_spec_client, noxtls_tls12_recv_finished_client
- noxtls_tls12_send_change_cipher_spec_server, noxtls_tls12_send_finished_server
Record encryption/decryption is available via noxtls_tls12_encrypt_record and noxtls_tls12_decrypt_record from the common TLS API.