More on certificate authentication
==================================

Certificates are not the only structures involved in a public key infrastructure. Several other structures that are used for certificate requests, encrypted private keys, revocation lists, GnuTLS abstract key structures, etc., are discussed in this chapter.

PKCS #10 certificate requests
-----------------------------

A certificate request is a structure, which contain information about an applicant of a certificate service.  It typically contains a public key, a distinguished name and secondary data such as a challenge password. GnuTLS supports the requests defined in PKCS #10 RFC2986. Other formats of certificate requests are not currently supported by GnuTLS.

A certificate request can be generated by associating it with a private key, setting the subject's information and finally self signing it. The last step ensures that the requester is in possession of the private key.

gnutls_x509_crq_set_version,gnutls_x509_crq_set_dn,gnutls_x509_crq_set_dn_by_oid,gnutls_x509_crq_set_key_usage,gnutls_x509_crq_set_key_purpose_oid,gnutls_x509_crq_set_basic_constraints

The gnutls_x509_crq_set_key and gnutls_x509_crq_sign2 functions associate the request with a private key and sign it. If a request is to be signed with a key residing in a PKCS #11 token it is recommended to use the signing functions shown in Abstract key types.

gnutls_x509_crq_set_key gnutls_x509_crq_sign2

The following example is about generating a certificate request, and a private key. A certificate request can be later be processed by a CA which should return a signed certificate.

     [file ex-crq.c not included]

PKIX certificate revocation lists
---------------------------------

A certificate revocation list (CRL) is a structure issued by an authority periodically containing a list of revoked certificates serial numbers. The CRL structure is signed with the issuing authorities' keys. A typical CRL contains the fields as shown in tab:crl. Certificate revocation lists are used to complement the expiration date of a certificate, in order to account for other reasons of revocation, such as compromised keys, etc.

Each CRL is valid for limited amount of time and is required to provide, except for the current issuing time, also the issuing time of the next update.

Field   Description

version
The field that indicates the version of the CRL structure.

signature
A signature by the issuing authority.

issuer
Holds the issuer's distinguished name.

thisUpdate
The issuing time of the revocation list.

nextUpdate
The issuing time of the revocation list that will update that one.

revokedCertificates
List of revoked certificates serial numbers.

extensions
Optional CRL structure extensions.

Table: Certificate revocation list fields.

The basic CRL structure functions follow.

gnutls_x509_crl_init,gnutls_x509_crl_import,gnutls_x509_crl_export,gnutls_x509_crl_export

Reading a CRL
.............

The most important function that extracts the certificate revocation information from a CRL is gnutls_x509_crl_get_crt_serial. Other functions that return other fields of the CRL structure are also provided.

gnutls_x509_crl_get_crt_serial

gnutls_x509_crl_get_version,gnutls_x509_crl_get_issuer_dn,gnutls_x509_crl_get_issuer_dn2,gnutls_x509_crl_get_this_update,gnutls_x509_crl_get_next_update,gnutls_x509_crl_get_crt_count

Generation of a CRL
...................

The following functions can be used to generate a CRL.

gnutls_x509_crl_set_version,gnutls_x509_crl_set_crt_serial gnutls_x509_crl_set_crt,gnutls_x509_crl_set_next_update,gnutls_x509_crl_set_this_update

The gnutls_x509_crl_sign2 and gnutls_x509_crl_privkey_sign functions sign the revocation list with a private key. The latter function can be used to sign with a key residing in a PKCS #11 token.

gnutls_x509_crl_sign2 gnutls_x509_crl_privkey_sign

Few extensions on the CRL structure are supported, including the CRL number extension and the authority key identifier.

gnutls_x509_crl_set_number,gnutls_x509_crl_set_authority_key_id

OCSP certificate status checking
--------------------------------

Certificates may be revoked before their expiration time has been reached.  There are several reasons for revoking certificates, but a typical situation is when the private key associated with a certificate has been compromised.  Traditionally, Certificate Revocation Lists (CRLs) have been used by application to implement revocation checking, however, several problems with CRLs have been identified RIVESTCRL.

The Online Certificate Status Protocol, or OCSP RFC2560, is a widely implemented protocol which performs certificate revocation status checking.  An application that wish to verify the identity of a peer will verify the certificate against a set of trusted certificates and then check whether the certificate is listed in a CRL and/or perform an OCSP check for the certificate.

Applications are typically expected to contact the OCSP server in order to request the certificate validity status. The OCSP server replies with an OCSP response. This section describes this online communication (which can be avoided when using OCSP stapled responses, for that, see OCSP stapling).

Before performing the OCSP query, the application will need to figure out the address of the OCSP server.  The OCSP server address can be provided by the local user in manual configuration or may be stored in the certificate that is being checked.  When stored in a certificate the OCSP server is in the extension field called the Authority Information Access (AIA). The following function extracts this information from a certificate.

gnutls_x509_crt_get_authority_info_access

There are several functions in GnuTLS for creating and manipulating OCSP requests and responses.  The general idea is that a client application creates an OCSP request object, stores some information about the certificate to check in the request, and then exports the request in DER format.  The request will then need to be sent to the OCSP responder, which needs to be done by the application (GnuTLS does not send and receive OCSP packets).  Normally an OCSP response is received that the application will need to import into an OCSP response object.  The digital signature in the OCSP response needs to be verified against a set of trust anchors before the information in the response can be trusted.

The ASN.1 structure of OCSP requests are briefly as follows.  It is useful to review the structures to get an understanding of which fields are modified by GnuTLS functions.

     OCSPRequest     ::=     SEQUENCE {
         tbsRequest                  TBSRequest,
         optionalSignature   [0]     EXPLICIT Signature OPTIONAL }

     TBSRequest      ::=     SEQUENCE {
         version             [0]     EXPLICIT Version DEFAULT v1,
         requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
         requestList                 SEQUENCE OF Request,
         requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }

     Request         ::=     SEQUENCE {
         reqCert                     CertID,
         singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }

     CertID          ::=     SEQUENCE {
         hashAlgorithm       AlgorithmIdentifier,
         issuerNameHash      OCTET STRING, -- Hash of Issuer's DN
         issuerKeyHash       OCTET STRING, -- Hash of Issuers public key
         serialNumber        CertificateSerialNumber }

The basic functions to initialize, import, export and deallocate OCSP requests are the following.

gnutls_ocsp_req_init,gnutls_ocsp_req_deinit,gnutls_ocsp_req_import,gnutls_ocsp_req_export,gnutls_ocsp_req_print

To generate an OCSP request the issuer name hash, issuer key hash, and the checked certificate's serial number are required. There are two interfaces available for setting those in an OCSP request. The is a low-level function when you have the issuer name hash, issuer key hash, and certificate serial number in binary form.  The second is more useful if you have the certificate (and its issuer) in a gnutls_x509_crt_t type. There is also a function to extract this information from existing an OCSP request.

gnutls_ocsp_req_add_cert_id,gnutls_ocsp_req_add_cert,gnutls_ocsp_req_get_cert_id

Each OCSP request may contain a number of extensions.  Extensions are identified by an Object Identifier (OID) and an opaque data buffer whose syntax and semantics is implied by the OID. You can extract or set those extensions using the following functions.

gnutls_ocsp_req_get_extension,gnutls_ocsp_req_set_extension

A common OCSP Request extension is the nonce extension (OID 1.3.6.1.5.5.7.48.1.2), which is used to avoid replay attacks of earlier recorded OCSP responses.  The nonce extension carries a value that is intended to be sufficiently random and unique so that an attacker will not be able to give a stale response for the same nonce.

gnutls_ocsp_req_get_nonce,gnutls_ocsp_req_set_nonce,gnutls_ocsp_req_randomize_nonce

The OCSP response structures is a complex structure. A simplified overview of it is in tab:ocsp-response. Note that a response may contain information on multiple certificates.

Field   Description

version
The OCSP response version number (typically 1).

responder ID
An identifier of the responder (DN name or a hash of its key).

issue time
The time the response was generated.

thisUpdate
The issuing time of the revocation information.

nextUpdate
The issuing time of the revocation information that will update that one.

  Revoked certificates

certificate status
The status of the certificate.

certificate serial
The certificate's serial number.

revocationTime
The time the certificate was revoked.

revocationReason
The reason the certificate was revoked.

Table: The most important OCSP response fields.

We provide basic functions for initialization, importing, exporting and deallocating OCSP responses.

gnutls_ocsp_resp_init,gnutls_ocsp_resp_deinit,gnutls_ocsp_resp_import,gnutls_ocsp_resp_export,gnutls_ocsp_resp_print

The utility function that extracts the revocation as well as other information from a response is shown below.

gnutls_ocsp_resp_get_single

The possible revocation reasons available in an OCSP response are shown below.

gnutls_x509_crl_reason_t,The revocation reasons

Note, that the OCSP response needs to be verified against some set of trust anchors before it can be relied upon. It is also important to check whether the received OCSP response corresponds to the certificate being checked.

gnutls_ocsp_resp_verify,gnutls_ocsp_resp_verify_direct,gnutls_ocsp_resp_check_crt

OCSP stapling
-------------

To avoid applications contacting the OCSP server directly, TLS servers can provide a "stapled" OCSP response in the TLS handshake. That way the client application needs to do nothing more. GnuTLS will automatically consider the stapled OCSP response during the TLS certificate verification (see gnutls_certificate_verify_peers2). To disable the automatic OCSP verification the flag GNUTLS_VERIFY_DISABLE_CRL_CHECKS should be specified to gnutls_certificate_set_verify_flags.

Since GnuTLS 3.5.1 the client certificate verification will consider the RFC7633 OCSP-Must-staple certificate extension, and will consider it while checking for stapled OCSP responses. If the extension is present and no OCSP staple is found, the certificate verification will fail and the status code GNUTLS_CERT_MISSING_OCSP_STATUS will returned from the verification function.

Under TLS 1.2 only one stapled response can be sent by a server, the OCSP response associated with the end-certificate. Under TLS 1.3 a server can send multiple OCSP responses, typically one for each certificate in the certificate chain. The following functions can be used by a client application to retrieve the OCSP responses as sent by the server.

gnutls_ocsp_status_request_get,gnutls_ocsp_status_request_get2

GnuTLS servers can provide OCSP responses to their clients using the following functions.

gnutls_certificate_set_retrieve_function3,gnutls_certificate_set_ocsp_status_request_file2,gnutls_ocsp_status_request_is_checked

A server is expected to provide the relevant certificate's OCSP responses using gnutls_certificate_set_ocsp_status_request_file2, and ensure a periodic reload/renew of the credentials. An estimation of the OCSP responses expiration can be obtained using the gnutls_certificate_get_ocsp_expiration function.

gnutls_certificate_get_ocsp_expiration

Prior to GnuTLS 3.6.4, the functions gnutls_certificate_set_ocsp_status_request_function2 gnutls_certificate_set_ocsp_status_request_file were provided to set OCSP responses. These functions are still functional, but cannot be used to set multiple OCSP responses as allowed by TLS1.3.

The responses can be updated periodically using the 'ocsptool' command (see also ocsptool Invocation).

     ocsptool --ask --load-cert server_cert.pem --load-issuer the_issuer.pem
              --load-signer the_issuer.pem --outfile ocsp.resp

In order to allow multiple OCSP responses to be concatenated, GnuTLS supports PEM-encoded OCSP responses. These can be generated using 'ocsptool' with the '--no-outder' parameter.

Managing encrypted keys
-----------------------

Transferring or storing private keys in plain may not be a good idea, since any compromise is irreparable. Storing the keys in hardware security modules (see Smart cards and HSMs) could solve the storage problem but it is not always practical or efficient enough. This section describes ways to store and transfer encrypted private keys.

There are methods for key encryption, namely the PKCS #8, PKCS #12 and OpenSSL's custom encrypted private key formats. The PKCS #8 and the OpenSSL's method allow encryption of the private key, while the PKCS #12 method allows, in addition, the bundling of accompanying data into the structure. That is typically the corresponding certificate, as well as a trusted CA certificate.

High level functionality
........................

Generic and higher level private key import functions are available, that import plain or encrypted keys and will auto-detect the encrypted key format.

gnutls_privkey_import_x509_raw

gnutls_x509_privkey_import2

Any keys imported using those functions can be imported to a certificate credentials structure using gnutls_certificate_set_key, or alternatively they can be directly imported using gnutls_certificate_set_x509_key_file2.

PKCS #8 structures
..................

PKCS #8 keys can be imported and exported as normal private keys using the functions below. An addition to the normal import functions, are a password and a flags argument. The flags can be any element of the gnutls_pkcs_encrypt_flags_t enumeration. Note however, that GnuTLS only supports the PKCS #5 PBES2 encryption scheme. Keys encrypted with the obsolete PBES1 scheme cannot be decrypted.

gnutls_x509_privkey_import_pkcs8,gnutls_x509_privkey_export_pkcs8,gnutls_x509_privkey_export2_pkcs8

gnutls_pkcs_encrypt_flags_t,Encryption flags

PKCS #12 structures
...................

A PKCS #12 structure PKCS12 usually contains a user's private keys and certificates. It is commonly used in browsers to export and import the user's identities. A file containing such a key can be directly imported to a certificate credentials structure by using gnutls_certificate_set_x509_simple_pkcs12_file.

In GnuTLS the PKCS #12 structures are handled using the gnutls_pkcs12_t type. This is an abstract type that may hold several gnutls_pkcs12_bag_t types.  The bag types are the holders of the actual data, which may be certificates, private keys or encrypted data.  A bag of type encrypted should be decrypted in order for its data to be accessed.

To reduce the complexity in parsing the structures the simple helper function gnutls_pkcs12_simple_parse is provided. For more advanced uses, manual parsing of the structure is required using the functions below.

gnutls_pkcs12_get_bag,gnutls_pkcs12_verify_mac,gnutls_pkcs12_bag_decrypt,gnutls_pkcs12_bag_get_count

gnutls_pkcs12_simple_parse gnutls_pkcs12_bag_get_data,gnutls_pkcs12_bag_get_key_id,gnutls_pkcs12_bag_get_friendly_name

The functions below are used to generate a PKCS #12 structure. An example of their usage is shown at PKCS12 structure generation example.

gnutls_pkcs12_set_bag,gnutls_pkcs12_bag_encrypt,gnutls_pkcs12_generate_mac gnutls_pkcs12_bag_set_data,gnutls_pkcs12_bag_set_crl,gnutls_pkcs12_bag_set_crt,gnutls_pkcs12_bag_set_key_id,gnutls_pkcs12_bag_set_friendly_name

OpenSSL encrypted keys
......................

Unfortunately the structures discussed in the previous sections are not the only structures that may hold an encrypted private key. For example the OpenSSL library offers a custom key encryption method. Those structures are also supported in GnuTLS with gnutls_x509_privkey_import_openssl.

gnutls_x509_privkey_import_openssl

     [file invoke-certtool.texi not included]

     [file invoke-ocsptool.texi not included]

     [file invoke-danetool.texi not included]