SSL_SET1_SERVER_CERT_TYPE(3ossl)
π SSL_SET1_SERVER_CERT_TYPE(3ossl) β the certificate type (RFC7250) glow-up π
okay bestie, sit down, hydrate, because we're talking about the SSL_set1_client_cert_type(3ossl) family β a whole little squad of functions that handle certificate type (RFC7250) support β¨ and yes they are lowkey iconic. this is from the OpenSSL manual, and we're gonna get through every single one of them together, no skipping, no cap π«Ά
πΈ NAME πΈ
SSL_set1_client_cert_type, SSL_set1_server_cert_type, SSL_CTX_set1_client_cert_type, SSL_CTX_set1_server_cert_type, SSL_get0_client_cert_type, SSL_get0_server_cert_type, SSL_CTX_get0_client_cert_type, SSL_CTX_get0_server_cert_type β certificate type (RFC7250) support π
it's giving "eight functions, one very specific job, and they ate."
β¨ SYNOPSIS β¨
#include <openssl/ssl.h>
int SSL_set1_client_cert_type(SSL *s, const unsigned char *val, size_t len);
int SSL_set1_server_cert_type(SSL *s, const unsigned char *val, size_t len);
int SSL_CTX_set1_client_cert_type(SSL_CTX *ctx, const unsigned char *val, size_t len);
int SSL_CTX_set1_server_cert_type(SSL_CTX *ctx, const unsigned char *val, size_t len);
int SSL_get0_client_cert_type(const SSL *s, unsigned char **val, size_t *len);
int SSL_get0_server_cert_type(const SSL *s, unsigned char **val, size_t *len);
int SSL_CTX_get0_client_cert_type(const SSL_CTX *ctx, unsigned char **val, size_t *len);
int SSL_CTX_get0_server_cert_type(const SSL_CTX *s, unsigned char **val, size_t *len);
look at them all lined up like a little friend group photo πΈ
π DESCRIPTION π
so. two separate stories happening here, one for the client cert type and one for the server cert type. buckle up.
SSL_set1_client_cert_type() and SSL_CTX_set1_client_cert_type() set the values for the client certificate type extension. and SSL_get0_client_cert_type() and SSL_CTX_get0_client_cert_type() retrieve the local values that are gonna be used in the client certificate type extension. retrieve, bestie. not invent, not negotiate, just hand you back what's already there π
SSL_set1_server_cert_type() and SSL_CTX_set1_server_cert_type() set the values for the server certificate type extension. and SSL_get0_server_cert_type() and SSL_CTX_get0_server_cert_type() retrieve the local values to be used in the server certificate type extension. same energy, different side of the handshake π¦
π NOTES π
okay this is the part where it gets interesting, pay attention π
the certificate type extensions are what negotiate the certificate type used in the handshake. they literally exist so each side can let the other know what it's able to accept. it's giving "hi, here's my vibe, do you match" π
π§ the client certificate type π§
the client certificate type is sent from the client to the server to indicate what certificate types the client is able to present. values are configured in preference order β order matters, queen. on the server, this setting determines which certificate types the server is willing to accept. the server ultimately chooses what type to request (if any) from the values that are mutually supported. and by default β as in, if no explicit settings are specified β only X.509 certificates are supported. that's the baseline, that's the default, that's the lore.
π§ the server certificate type π§
the server certificate type is sent from the client to the server to indicate what certificate types the client accepts. values are configured in preference order. on the server, this setting determines which certificate types the server is willing to present. the server ultimately chooses what type to use from the values that are mutually supported. and again, by default (if no explicit settings are specified), only X.509 certificates are supported. same rule, other direction, periodt.
π‘ having RPK specified first means that side will attempt to send (or request) RPKs if its peer also supports RPKs, otherwise an X.509 certificate will be used if both have specified that (or have not configured these options).
π the two supported values in the val array π
TLSEXT_cert_type_x509β which corresponds to an X.509 certificate normally used in TLS.TLSEXT_cert_type_rpkβ which corresponds to a raw public key.
now, the on/off situation: if val is set to a non-NULL value, then the extension is sent in the handshake. if val is set to a NULL value (and len is 0), then the extension is disabled. the default value is NULL, meaning the extension is not sent, and X.509 certificates are used in the handshake. no cap.
raw public keys may be used in place of certificates when specified in the certificate type and negotiated. and listen β raw public keys have no subject, no issuer, no validity dates, and no digital signature. they're the minimalist, no-baggage, main-character-cert of the TLS world π
use the SSL_get_negotiated_client_cert_type(3) and SSL_get_negotiated_server_cert_type(3) functions to get the negotiated cert type values β at the conclusion of the handshake, or in callbacks that happen after the TLS ServerHello has been processed. iykyk π«Ά
π₯ RETURN VALUES π₯
all functions return 1 on success and 0 on failure. classic binary, love that for them.
β οΈ the memory returned from the get0 functions must not be freed. do not free it. do not touch it with free(). hands off, bestie π
π EXAMPLES π
π server side: raw public keys π
to use raw public keys on the server, set up the SSL_CTX and SSL as follows:
SSL_CTX *ctx;
SSL *ssl;
unsigned char cert_type[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 };
EVP_PKEY *rpk;
/* Assign rpk to an EVP_PKEY from a file or other means */
if ((ctx = SSL_CTX_new(TLS_server_method())) == NULL)
/* error */
if ((ssl = SSL_new(ctx)) == NULL)
/* error */
if (!SSL_set1_server_cert_type(ssl, cert_type, sizeof(cert_type)))
/* error */
/* A certificate does not need to be specified when using raw public keys */
if (!SSL_use_PrivateKey(ssl, rpk))
/* error */
/* Perform SSL_accept() operations */
π¦ client side: connecting to that server π¦
to connect to this server, set the client SSL_CTX and SSL as follows:
/* Connect function */
SSL_CTX *ctx;
SSL *ssl;
const char *dane_tlsa_domain = "smtp.example.com";
unsigned char cert_type[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 };
EVP_PKEY *rpk;
int verify_result;
/* Assign rpk to an EVP_PKEY from a file or other means */
if ((ctx = SSL_CTX_new(TLS_client_method())) == NULL)
/* error */
if (SSL_CTX_dane_enable(ctx) <= 0)
/* error */
if ((ssl = SSL_new(ctx)) == NULL)
/* error */
/*
* The `dane_tlsa_domain` arguments sets the default SNI hostname.
* It may be set to NULL when enabling DANE on the server side.
*/
if (SSL_dane_enable(ssl, dane_tlsa_domain) <= 0)
/* error */
if (!SSL_set1_server_cert_type(ssl, cert_type, sizeof(cert_type)))
/* error */
if (!SSL_add_expected_rpk(ssl, rpk))
/* error */
/* Do SSL_connect() handshake and handle errors here */
/* Optional: verify the peer RPK */
verify_result = SSL_get_verify_result(ssl);
if (verify_result == X509_V_OK) {
/* The server's raw public key matched the TLSA record */
} else if (verify_result == X509_V_ERR_DANE_NO_MATCH) {
/*
* The server's raw public key, or public key in certificate, did not
* match the TLSA record
*/
} else if (verify_result == X509_V_ERR_RPK_UNTRUSTED) {
/*
* No TLSA records of the correct type are available to verify the
* server's raw public key. This would not happen in this example,
* as a TLSA record is configured.
*/
} else {
/* Some other verify error */
}
and one more lil note, bestie: to validate client raw public keys, code from the client example may need to be incorporated into the server side. steal the fit, it's fine π
π SEE ALSO π
SSL_get0_peer_rpk(3)SSL_get_negotiated_client_cert_type(3)SSL_get_negotiated_server_cert_type(3)SSL_use_certificate(3)
β HISTORY β
these functions were added in OpenSSL 3.2. new-ish era, fresh-faced, still serving π
π COPYRIGHT π
Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
and that's the whole page, bestie β every flag, every function, every value, every warning, all of it, intact π«Ά this was the SSL_SET1_SERVER_CERT_TYPE(3ossl) page from OpenSSL, version 3.5.9, dated 2026-09-29. go forth and negotiate responsibly β¨ππ
π¦ where this page comes from
- fedora 43: openssl-devel 1:3.5.9-1.fc43 Β· Apache-2.0
- fedora 43: openssl-devel 1:3.5.9-1.fc43 Β· Apache-2.0
- fedora 44: openssl-devel 1:3.5.9-1.fc44 Β· Apache-2.0
- fedora 44: openssl-devel 1:3.5.9-1.fc44 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms