Next: , Up: Associating the credentials   [Contents][Index]


6.4.1 Certificates

Server certificate authentication

When using certificates the server is required to have at least one certificate and private key pair. Clients may not hold such a pair, but a server could require it. In this section we discuss general issues applying to both client and server certificates. The next section will elaborate on issues arising from client authentication only.

In order to use certificate credentials one must first initialize a credentials structure of type gnutls_certificate_credentials_t. After use this structure must be freed. This can be done with the following functions.

int gnutls_certificate_allocate_credentials (gnutls_certificate_credentials_t * res)
void gnutls_certificate_free_credentials (gnutls_certificate_credentials_t sc)

After the credentials structures are initialized, the certificate and key pair must be loaded. This occurs before any TLS session is initialized, and the same structures are reused for multiple sessions. Depending on the certificate type different loading functions are available, as shown below. For X.509 certificates, the functions will accept and use a certificate chain that leads to a trusted authority. The certificate chain must be ordered in such way that every certificate certifies the one before it. The trusted authority’s certificate need not to be included since the peer should possess it already.

int gnutls_certificate_set_x509_key_file2 (gnutls_certificate_credentials_t res, const char * certfile, const char * keyfile, gnutls_x509_crt_fmt_t type, const char * pass, unsigned int flags)
int gnutls_certificate_set_x509_key_mem2 (gnutls_certificate_credentials_t res, const gnutls_datum_t * cert, const gnutls_datum_t * key, gnutls_x509_crt_fmt_t type, const char * pass, unsigned int flags)
int gnutls_certificate_set_x509_key (gnutls_certificate_credentials_t res, gnutls_x509_crt_t * cert_list, int cert_list_size, gnutls_x509_privkey_t key)

It is recommended to use the higher level functions such as gnutls_certificate_set_x509_key_file2 which accept not only file names but URLs that specify objects stored in token, or system certificates and keys (see Application-specific keys). For these cases, another important function is gnutls_certificate_set_pin_function, that allows setting a callback function to retrieve a PIN if the input keys are protected by PIN.

Function: void gnutls_certificate_set_pin_function (gnutls_certificate_credentials_t cred, gnutls_pin_callback_t fn, void * userdata)

cred: is a gnutls_certificate_credentials_t type.

fn: A PIN callback

userdata: Data to be passed in the callback

This function will set a callback function to be used when required to access a protected object. This function overrides any other global PIN functions.

Note that this function must be called right after initialization to have effect.

Since: 3.1.0

If the imported keys and certificates need to be accessed before any TLS session is established, it is convenient to use gnutls_certificate_set_key in combination with gnutls_pcert_import_x509_raw and gnutls_privkey_import_x509_raw.

Function: int gnutls_certificate_set_key (gnutls_certificate_credentials_t res, const char ** names, int names_size, gnutls_pcert_st * pcert_list, int pcert_list_size, gnutls_privkey_t key)

res: is a gnutls_certificate_credentials_t type.

names: is an array of DNS names belonging to the public-key (NULL if none)

names_size: holds the size of the names list

pcert_list: contains a certificate list (chain) or raw public-key

pcert_list_size: holds the size of the certificate list

key: is a gnutls_privkey_t key corresponding to the first public-key in pcert_list

This function sets a public/private key pair in the gnutls_certificate_credentials_t type. The given public key may be encapsulated in a certificate or can be given as a raw key. This function may be called more than once, in case multiple key pairs exist for the server. For clients that want to send more than their own end- entity certificate (e.g., also an intermediate CA cert), the full certificate chain must be provided in pcert_list .

Note that the key will become part of the credentials structure and must not be deallocated. It will be automatically deallocated when the res structure is deinitialized.

If this function fails, the res structure is at an undefined state and it must not be reused to load other keys or certificates.

Note that, this function by default returns zero on success and a negative value on error. Since 3.5.6, when the flag GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags() it returns an index (greater or equal to zero). That index can be used for other functions to refer to the added key-pair.

Since GnuTLS 3.6.6 this function also handles raw public keys.

Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior).

Since: 3.0

If multiple certificates are used with the functions above each client’s request will be served with the certificate that matches the requested name (see Server name indication).

As an alternative to loading from files or buffers, a callback may be used for the server or the client to specify the certificate and the key at the handshake time. In that case a certificate should be selected according the peer’s signature algorithm preferences. To get those preferences use gnutls_sign_algorithm_get_requested. Both functions are shown below.

void gnutls_certificate_set_retrieve_function (gnutls_certificate_credentials_t cred, gnutls_certificate_retrieve_function * func)
void gnutls_certificate_set_retrieve_function2 (gnutls_certificate_credentials_t cred, gnutls_certificate_retrieve_function2 * func)
void gnutls_certificate_set_retrieve_function3 (gnutls_certificate_credentials_t cred, gnutls_certificate_retrieve_function3 * func)
int gnutls_sign_algorithm_get_requested (gnutls_session_t session, size_t indx, gnutls_sign_algorithm_t * algo)

The functions above do not handle the requested server name automatically. A server would need to check the name requested by the client using gnutls_server_name_get, and serve the appropriate certificate. Note that some of these functions require the gnutls_pcert_st structure to be filled in. Helper functions to fill in the structure are listed below.

typedef struct gnutls_pcert_st
{
  gnutls_pubkey_t pubkey;
  gnutls_datum_t cert;
  gnutls_certificate_type_t type;
} gnutls_pcert_st;
int gnutls_pcert_import_x509 (gnutls_pcert_st * pcert, gnutls_x509_crt_t crt, unsigned int flags)
int gnutls_pcert_import_x509_raw (gnutls_pcert_st * pcert, const gnutls_datum_t * cert, gnutls_x509_crt_fmt_t format, unsigned int flags)
void gnutls_pcert_deinit (gnutls_pcert_st * pcert)

In a handshake, the negotiated cipher suite depends on the certificate’s parameters, so some key exchange methods might not be available with all certificates. GnuTLS will disable ciphersuites that are not compatible with the key, or the enabled authentication methods. For example keys marked as sign-only, will not be able to access the plain RSA ciphersuites, that require decryption. It is not recommended to use RSA keys for both signing and encryption. If possible use a different key for the DHE-RSA which uses signing and RSA that requires decryption. All the key exchange methods shown in Table 4.1 are available in certificate authentication.

Client certificate authentication

If a certificate is to be requested from the client during the handshake, the server will send a certificate request message. This behavior is controlled by gnutls_certificate_server_set_request. The request contains a list of the by the server accepted certificate signers. This list is constructed using the trusted certificate authorities of the server. In cases where the server supports a large number of certificate authorities it makes sense not to advertise all of the names to save bandwidth. That can be controlled using the function gnutls_certificate_send_x509_rdn_sequence. This however will have the side-effect of not restricting the client to certificates signed by server’s acceptable signers.

Function: void gnutls_certificate_server_set_request (gnutls_session_t session, gnutls_certificate_request_t req)

session: is a gnutls_session_t type.

req: is one of GNUTLS_CERT_REQUEST, GNUTLS_CERT_REQUIRE, GNUTLS_CERT_IGNORE

This function specifies if we (in case of a server) are going to send a certificate request message to the client. If req is GNUTLS_CERT_REQUIRE then the server will return the GNUTLS_E_NO_CERTIFICATE_FOUND error if the peer does not provide a certificate. If you do not call this function then the client will not be asked to send a certificate. Invoking the function with req GNUTLS_CERT_IGNORE has the same effect.

Function: void gnutls_certificate_send_x509_rdn_sequence (gnutls_session_t session, int status)

session: a gnutls_session_t type.

status: is 0 or 1

If status is non zero, this function will order gnutls not to send the rdnSequence in the certificate request message. That is the server will not advertise its trusted CAs to the peer. If status is zero then the default behaviour will take effect, which is to advertise the server’s trusted CAs.

This function has no effect in clients, and in authentication methods other than certificate with X.509 certificates.

On the client side, it needs to set its certificates on the credentials structure, similarly to server side from a file, or via a callback. Once the certificates are available in the credentials structure, the client will send them if during the handshake the server requests a certificate signed by the issuer of its CA.

In the case a single certificate is available and the server does not specify a signer’s list, then that certificate is always sent. It is, however possible, to send a certificate even when the advertised CA list by the server contains CAs other than its signer. That can be achieved using the GNUTLS_FORCE_CLIENT_CERT flag in gnutls_init.

int gnutls_certificate_set_x509_key_file (gnutls_certificate_credentials_t res, const char * certfile, const char * keyfile, gnutls_x509_crt_fmt_t type)
int gnutls_certificate_set_x509_simple_pkcs12_file (gnutls_certificate_credentials_t res, const char * pkcs12file, gnutls_x509_crt_fmt_t type, const char * password)
void gnutls_certificate_set_retrieve_function2 (gnutls_certificate_credentials_t cred, gnutls_certificate_retrieve_function2 * func)

Client or server certificate verification

Certificate verification is possible by loading the trusted authorities into the credentials structure by using the following functions, applicable to X.509 certificates. In modern systems it is recommended to utilize gnutls_certificate_set_x509_system_trust which will load the trusted authorities from the system store.

Function: int gnutls_certificate_set_x509_system_trust (gnutls_certificate_credentials_t cred)

cred: is a gnutls_certificate_credentials_t type.

This function adds the system’s default trusted CAs in order to verify client or server certificates.

In the case the system is currently unsupported GNUTLS_E_UNIMPLEMENTED_FEATURE is returned.

Returns: the number of certificates processed or a negative error code on error.

Since: 3.0.20

int gnutls_certificate_set_x509_trust_file (gnutls_certificate_credentials_t cred, const char * cafile, gnutls_x509_crt_fmt_t type)
int gnutls_certificate_set_x509_trust_dir (gnutls_certificate_credentials_t cred, const char * ca_dir, gnutls_x509_crt_fmt_t type)

The peer’s certificate will be automatically verified if gnutls_session_set_verify_cert is called prior to handshake.

Alternatively, one must set a callback function during the handshake using gnutls_certificate_set_verify_function, which will verify the peer’s certificate once received. The verification should happen using gnutls_certificate_verify_peers3 within the callback. It will verify the certificate’s signature and the owner of the certificate. That will provide a brief verification output. If a detailed output is required one should call gnutls_certificate_get_peers to obtain the raw certificate of the peer and verify it using the functions discussed in X.509 certificates.

In both the automatic and the manual cases, the verification status returned can be printed using gnutls_certificate_verification_status_print.

Function: void gnutls_session_set_verify_cert (gnutls_session_t session, const char * hostname, unsigned flags)

session: is a gnutls session

hostname: is the expected name of the peer; may be NULL

flags: flags for certificate verification – gnutls_certificate_verify_flags

This function instructs GnuTLS to verify the peer’s certificate using the provided hostname. If the verification fails the handshake will also fail with GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR . In that case the verification result can be obtained using gnutls_session_get_verify_cert_status() .

The hostname pointer provided must remain valid for the lifetime of the session. More precisely it should be available during any subsequent handshakes. If no hostname is provided, no hostname verification will be performed. For a more advanced verification function check gnutls_session_set_verify_cert2() .

If flags is provided which contain a profile, this function should be called after any session priority setting functions.

The gnutls_session_set_verify_cert() function is intended to be used by TLS clients to verify the server’s certificate.

Since: 3.4.6

int gnutls_certificate_verify_peers3 (gnutls_session_t session, const char * hostname, unsigned int * status)
void gnutls_certificate_set_verify_function (gnutls_certificate_credentials_t cred, gnutls_certificate_verify_function * func)

Note that when using raw public-keys verification will not work because there is no corresponding certificate body belonging to the raw key that can be verified. In that case the gnutls_certificate_verify_peers family of functions will return a GNUTLS_E_INVALID_REQUEST error code. For authenticating raw public-keys one must use an out-of-band mechanism, e.g. by comparing hashes or using trust on first use (see Verifying a certificate using trust on first use authentication).


Next: , Up: Associating the credentials   [Contents][Index]