This is gnutls.info, produced by makeinfo version 4.13.90 from gnutls.texi. This manual is last updated 2 September 2012 for version 3.0.30 of GnuTLS. Copyright (C) 2001-2012 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". INFO-DIR-SECTION Software libraries START-INFO-DIR-ENTRY * GnuTLS: (gnutls). GNU Transport Layer Security Library. END-INFO-DIR-ENTRY INFO-DIR-SECTION System Administration START-INFO-DIR-ENTRY * certtool: (gnutls)Invoking certtool. Manipulate certificates and keys. * gnutls-serv: (gnutls)Invoking gnutls-serv. GnuTLS test server. * gnutls-cli: (gnutls)Invoking gnutls-cli. GnuTLS test client. * gnutls-cli-debug: (gnutls)Invoking gnutls-cli-debug. GnuTLS debug client. * psktool: (gnutls)Invoking psktool. Simple TLS-Pre-Shared-Keys manager. * srptool: (gnutls)Invoking srptool. Simple SRP password tool. END-INFO-DIR-ENTRY  File: gnutls.info, Node: Top, Next: Preface, Up: (dir) GnuTLS ****** This manual is last updated 2 September 2012 for version 3.0.30 of GnuTLS. Copyright (C) 2001-2012 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". * Menu: * Preface:: * Introduction to GnuTLS:: * Introduction to TLS:: * Certificate authentication:: * Shared-key and anonymous authentication:: * More on certificate authentication:: * How to use GnuTLS in applications:: * GnuTLS application examples:: * Other included programs:: * Internal architecture of GnuTLS:: * Upgrading from previous versions:: * Support:: * Error codes:: * Supported ciphersuites:: * API reference:: * Copying Information:: * Bibliography:: * Function and Data Index:: * Concept Index::  File: gnutls.info, Node: Preface, Next: Introduction to GnuTLS, Prev: Top, Up: Top 1 Preface ********* This document demonstrates and explains the GnuTLS library API. A brief introduction to the protocols and the technology involved is also included so that an application programmer can better understand the GnuTLS purpose and actual offerings. Even if GnuTLS is a typical library software, it operates over several security and cryptographic protocols which require the programmer to make careful and correct usage of them. Otherwise it is likely to only obtain a false sense of security. The term of security is very broad even if restricted to computer software, and cannot be confined to a single cryptographic library. For that reason, do not consider any program secure just because it uses GnuTLS; there are several ways to compromise a program or a communication line and GnuTLS only helps with some of them. Although this document tries to be self contained, basic network programming and public key infrastructure (PKI) knowledge is assumed in most of it. A good introduction to networking can be found in [_STEVENS_], to public key infrastructure in [_GUTPKI_] and to security engineering in [_ANDERSON_]. Updated versions of the GnuTLS software and this document will be available from and .  File: gnutls.info, Node: Introduction to GnuTLS, Next: Introduction to TLS, Prev: Preface, Up: Top 2 Introduction to GnuTLS ************************ In brief GnuTLS can be described as a library which offers an API to access secure communication protocols. These protocols provide privacy over insecure lines, and were designed to prevent eavesdropping, tampering, or message forgery. Technically GnuTLS is a portable ANSI C based library which implements the protocols ranging from SSL 3.0 to TLS 1.2 (see *note Introduction to TLS::, for a detailed description of the protocols), accompanied with the required framework for authentication and public key infrastructure. Important features of the GnuTLS library include: * Support for TLS 1.2, TLS 1.1, TLS 1.0 and SSL 3.0 protocols. * Support for Datagram TLS 1.0. * Support for handling and verification of X.509 and OpenPGP certificates. * Support for password authentication using TLS-SRP. * Support for keyed authentication using TLS-PSK. * Support for PKCS #11 tokens and smart-cards. The GnuTLS library consists of three independent parts, namely the "TLS protocol part", the "Certificate part", and the "Cryptographic back-end" part. The "TLS protocol part" is the actual protocol implementation, and is entirely implemented within the GnuTLS library. The "Certificate part" consists of the certificate parsing, and verification functions and it uses functionality from the libtasn1(1) library. The "Cryptographic back-end" is provided by the nettle(2) library. * Menu: * Downloading and installing:: * Document overview:: ---------- Footnotes ---------- (1) (2)  File: gnutls.info, Node: Downloading and installing, Next: Document overview, Up: Introduction to GnuTLS 2.1 Downloading and installing ============================== GnuTLS is available for download at: GnuTLS uses a development cycle where even minor version numbers indicate a stable release and a odd minor version number indicate a development release. For example, GnuTLS 1.6.3 denote a stable release since 6 is even, and GnuTLS 1.7.11 denote a development release since 7 is odd. GnuTLS depends on Libnettle, and you will need to install it before installing GnuTLS. Libnettle is available from . Don't forget to verify the cryptographic signature after downloading source code packages. The package is then extracted, configured and built like many other packages that use Autoconf. For detailed information on configuring and building it, refer to the 'INSTALL' file that is part of the distribution archive. Typically you invoke './configure' and then 'make check install'. There are a number of compile-time parameters, as discussed below. The compression library, libz, as well as p11-kit are a optional dependencies. You can get libz from and p11-kit from . The X.509 part of GnuTLS needs ASN.1 functionality, from a library called libtasn1. A copy of libtasn1 is included in GnuTLS. If you want to install it separately (e.g., to make it possibly to use libtasn1 in other programs), you can get it from . A few 'configure' options may be relevant, summarized below. They disable or enable particular features, to create a smaller library with only the required features. Note however, that although a smaller library is generated, the included programs are not guarranteed to compile if some of these options are given. --disable-srp-authentication --disable-psk-authentication --disable-anon-authentication --disable-extra-pki --disable-openpgp-authentication --disable-openssl-compatibility --without-p11-kit For the complete list, refer to the output from 'configure --help'.  File: gnutls.info, Node: Document overview, Prev: Downloading and installing, Up: Introduction to GnuTLS 2.2 Overview ============ In this document we present an overview of the supported security protocols in *note Introduction to TLS::, and continue by providing more information on the certificate authentication in *note Certificate authentication::, and shared-key as well anonymous authentication in *note Shared-key and anonymous authentication::. We elaborate on certificate authentication by demonstrating advanced usage of the API in *note More on certificate authentication::. The core of the TLS library is presented in *note How to use GnuTLS in applications:: and example applications are listed in *note GnuTLS application examples::. In *note Other included programs:: the usage of few included programs that may assist debugging is presented. The last chapter is *note Internal architecture of GnuTLS:: that provides a short introduction to GnuTLS' internal architecture.  File: gnutls.info, Node: Introduction to TLS, Next: Certificate authentication, Prev: Introduction to GnuTLS, Up: Top 3 Introduction to TLS and DTLS ****************************** TLS stands for "Transport Layer Security" and is the successor of SSL, the Secure Sockets Layer protocol [_SSL3_] designed by Netscape. TLS is an Internet protocol, defined by IETF(1), described in [_RFC5246_]. The protocol provides confidentiality, and authentication layers over any reliable transport layer. The description, above, refers to TLS 1.0 but applies to all other TLS versions as the differences between the protocols are not major. The DTLS protocol, or "Datagram TLS" [_RFC4347_] is a protocol with identical goals as TLS, but can operate under unreliable transport layers such as UDP. The discussions below apply to this protocol as well, except when noted otherwise. * Menu: * TLS layers:: * The transport layer:: * The TLS record protocol:: * The TLS Alert Protocol:: * The TLS Handshake Protocol:: * TLS Extensions:: * How to use TLS in application protocols:: * On SSL 2 and older protocols:: ---------- Footnotes ---------- (1) IETF, or Internet Engineering Task Force, is a large open international community of network designers, operators, vendors, and researchers concerned with the evolution of the Internet architecture and the smooth operation of the Internet. It is open to any interested individual.  File: gnutls.info, Node: TLS layers, Next: The transport layer, Up: Introduction to TLS 3.1 TLS layers ============== TLS is a layered protocol, and consists of the record protocol, the handshake protocol and the alert protocol. The record protocol is to serve all other protocols and is above the transport layer. The record protocol offers symmetric encryption, data authenticity, and optionally compression. The alert protocol offers some signaling to the other protocols. It can help informing the peer for the cause of failures and other error conditions. *Note The Alert Protocol::, for more information. The alert protocol is above the record protocol. The handshake protocol is responsible for the security parameters' negotiation, the initial key exchange and authentication. *Note The Handshake Protocol::, for more information about the handshake protocol. The protocol layering in TLS is shown in *note Figure 3.1: fig:tls-layers. [image src="gnutls-layers.png"] Figure 3.1: The TLS protocol layers.  File: gnutls.info, Node: The transport layer, Next: The TLS record protocol, Prev: TLS layers, Up: Introduction to TLS 3.2 The transport layer ======================= TLS is not limited to any transport layer and can be used above any transport layer, as long as it is a reliable one. DTLS can be used over reliable and unreliable transport layers. GnuTLS supports TCP and UDP layers transparently using the Berkeley sockets API. However, any transport layer can be used by providing callbacks for GnuTLS to access the transport layer (for details see *note Setting up the transport layer::).  File: gnutls.info, Node: The TLS record protocol, Next: The TLS Alert Protocol, Prev: The transport layer, Up: Introduction to TLS 3.3 The TLS record protocol =========================== The record protocol is the secure communications provider. Its purpose is to encrypt, authenticate and --optionally-- compress packets. The record layer functions can be called at any time after the handshake process is finished, when there is need to receive or send data. In DTLS however, due to re-transmission timers used in the handshake out-of-order handshake data might be received for some time (maximum 60 seconds) after the handshake process is finished. The functions to access the record protocol are limited to send and receive functions, which might, given the importance of this protocol in TLS, seem awkward. This is because the record protocol's parameters are all set by the handshake protocol. The record protocol initially starts with NULL parameters, which means no encryption, and no MAC is used. Encryption and authentication begin just after the handshake protocol has finished. * Menu: * Encryption algorithms used in the record layer:: * Compression algorithms used in the record layer:: * Weaknesses and countermeasures:: * On Record Padding::  File: gnutls.info, Node: Encryption algorithms used in the record layer, Next: Compression algorithms used in the record layer, Up: The TLS record protocol 3.3.1 Encryption algorithms used in the record layer ---------------------------------------------------- Confidentiality in the record layer is achieved by using symmetric block encryption algorithms like '3DES', 'AES' or stream algorithms like 'ARCFOUR_128'. Ciphers are encryption algorithms that use a single, secret, key to encrypt and decrypt data. Block algorithms in CBC mode also provide protection against statistical analysis of the data. Thus, if you're using the TLS protocol, a random number of blocks will be appended to data, to prevent eavesdroppers from guessing the actual data size. The supported in GnuTLS ciphers and MAC algorithms are shown in *note Table 3.1: tab:ciphers. and *note Table 3.2: tab:macs. Algorithm Description ------------------------------------------------------------------ 3DES_CBC This is the DES block cipher algorithm used with triple encryption (EDE). Has 64 bits block size and is used in CBC mode. ARCFOUR_128 ARCFOUR_128 is a compatible algorithm with RSA's RC4 algorithm, which is considered to be a trade secret. It is a fast cipher but considered weak today. ARCFOUR_40 This is the ARCFOUR cipher fed with a 40 bit key, which is considered weak. AES_CBC AES or RIJNDAEL is the block cipher algorithm that replaces the old DES algorithm. Has 128 bits block size and is used in CBC mode. AES_GCM This is the AES algorithm in the authenticated encryption GCM mode. This mode combines message authentication and encryption and can be extremely fast on CPUs that support hardware acceleration. CAMELLIA_CBC This is an 128-bit block cipher developed by Mitsubishi and NTT. It is one of the approved ciphers of the European NESSIE and Japanese CRYPTREC projects. Table 3.1: Supported ciphers. Algorithm Description ------------------------------------------------------------------ MAC_MD5 This is an HMAC based on MD5 a cryptographic hash algorithm designed by Ron Rivest. Outputs 128 bits of data. MAC_SHA1 An HMAC based on the SHA1 cryptographic hash algorithm designed by NSA. Outputs 160 bits of data. MAC_SHA256 An HMAC based on SHA256. Outputs 256 bits of data. MAC_AEAD This indicates that an authenticated encryption algorithm, such as GCM, is in use. Table 3.2: Supported MAC algorithms.  File: gnutls.info, Node: Compression algorithms used in the record layer, Next: Weaknesses and countermeasures, Prev: Encryption algorithms used in the record layer, Up: The TLS record protocol 3.3.2 Compression algorithms used in the record layer ----------------------------------------------------- The TLS record layer also supports compression. The algorithms implemented in GnuTLS can be found in the table below. The included algorithms perform really good when text, or other compressible data are to be transferred, but offer nothing on already compressed data, such as compressed images, zipped archives etc. These compression algorithms, may be useful in high bandwidth TLS tunnels, and in cases where network usage has to be minimized. It should be noted however that compression increases latency. The record layer compression in GnuTLS is implemented based on [_RFC3749_]. The supported algorithms are shown below. 'GNUTLS_COMP_UNKNOWN' Unknown compression method. 'GNUTLS_COMP_NULL' The NULL compression method (no compression). 'GNUTLS_COMP_DEFLATE' The DEFLATE compression method from zlib. 'GNUTLS_COMP_ZLIB' Same as 'GNUTLS_COMP_DEFLATE' . Figure 3.2: Supported compression algorithms Note that compression enables attacks such as traffic analysis, or even plaintext recovery under certain circumstances. To avoid some of these attacks GnuTLS allows each record to be compressed independently (i.e., stateless compression), by using the "%STATELESS_COMPRESSION" priority string.  File: gnutls.info, Node: Weaknesses and countermeasures, Next: On Record Padding, Prev: Compression algorithms used in the record layer, Up: The TLS record protocol 3.3.3 Weaknesses and countermeasures ------------------------------------ Some weaknesses that may affect the security of the record layer have been found in TLS 1.0 protocol. These weaknesses can be exploited by active attackers, and exploit the facts that 1. TLS has separate alerts for "decryption_failed" and "bad_record_mac" 2. The decryption failure reason can be detected by timing the response time. 3. The IV for CBC encrypted packets is the last block of the previous encrypted packet. Those weaknesses were solved in TLS 1.1 [_RFC4346_] which is implemented in GnuTLS. For this reason we suggest to always negotiate the highest supported TLS version with the peer(1). For a detailed discussion of the issues see the archives of the TLS Working Group mailing list and [_CBCATT_]. ---------- Footnotes ---------- (1) If this is not possible then please consult *note Interoperability::.  File: gnutls.info, Node: On Record Padding, Prev: Weaknesses and countermeasures, Up: The TLS record protocol 3.3.4 On record padding ----------------------- The TLS protocol allows for random padding of records in CBC ciphers, to prevent statistical analysis based on the length of exchanged messages (see [_RFC5246_] section 6.2.3.2). GnuTLS appears to be one of few implementation that take advantage of this text, and pad records by a random length. The TLS implementation in the Symbian operating system, frequently used by Nokia and Sony-Ericsson mobile phones, cannot handle non-minimal record padding. What happens when one of these clients handshake with a GnuTLS server is that the client will fail to compute the correct MAC for the record. The client sends a TLS alert ('bad_record_mac') and disconnects. Typically this will result in error messages such as 'A TLS fatal alert has been received', 'Bad record MAC', or both, on the GnuTLS server side. GnuTLS implements a work around for this problem. However, it has to be enabled specifically. It can be enabled by using *note gnutls_record_disable_padding::, or *note gnutls_priority_set:: with the '%COMPAT' priority string (see *note Priority Strings::). If you implement an application that have a configuration file, we recommend that you make it possible for users or administrators to specify a GnuTLS protocol priority string, which is used by your application via *note gnutls_priority_set::. To allow the best flexibility, make it possible to have a different priority string for different incoming IP addresses.  File: gnutls.info, Node: The TLS Alert Protocol, Next: The TLS Handshake Protocol, Prev: The TLS record protocol, Up: Introduction to TLS 3.4 The TLS alert protocol ========================== The alert protocol is there to allow signals to be sent between peers. These signals are mostly used to inform the peer about the cause of a protocol failure. Some of these signals are used internally by the protocol and the application protocol does not have to cope with them (e.g. 'GNUTLS_A_CLOSE_NOTIFY'), and others refer to the application protocol solely (e.g. 'GNUTLS_A_USER_CANCELLED'). An alert signal includes a level indication which may be either fatal or warning. Fatal alerts always terminate the current connection, and prevent future re-negotiations using the current session ID. All alert messages are summarized in the table below. The alert messages are protected by the record protocol, thus the information that is included does not leak. You must take extreme care for the alert information not to leak to a possible attacker, via public log files etc. Alert ID Description ------------------------------------------------------------------------ GNUTLS_A_CLOSE_NOTIFY 0 Close notify GNUTLS_A_UNEXPECTED_MESSAGE 10 Unexpected message GNUTLS_A_BAD_RECORD_MAC 20 Bad record MAC GNUTLS_A_DECRYPTION_FAILED 21 Decryption failed GNUTLS_A_RECORD_OVERFLOW 22 Record overflow GNUTLS_A_DECOMPRESSION_FAILURE 30 Decompression failed GNUTLS_A_HANDSHAKE_FAILURE 40 Handshake failed GNUTLS_A_SSL3_NO_CERTIFICATE 41 No certificate (SSL 3.0) GNUTLS_A_BAD_CERTIFICATE 42 Certificate is bad GNUTLS_A_UNSUPPORTED_CERTIFICATE 43 Certificate is not supported GNUTLS_A_CERTIFICATE_REVOKED 44 Certificate was revoked GNUTLS_A_CERTIFICATE_EXPIRED 45 Certificate is expired GNUTLS_A_CERTIFICATE_UNKNOWN 46 Unknown certificate GNUTLS_A_ILLEGAL_PARAMETER 47 Illegal parameter GNUTLS_A_UNKNOWN_CA 48 CA is unknown GNUTLS_A_ACCESS_DENIED 49 Access was denied GNUTLS_A_DECODE_ERROR 50 Decode error GNUTLS_A_DECRYPT_ERROR 51 Decrypt error GNUTLS_A_EXPORT_RESTRICTION 60 Export restriction GNUTLS_A_PROTOCOL_VERSION 70 Error in protocol version GNUTLS_A_INSUFFICIENT_SECURITY 71 Insufficient security GNUTLS_A_INTERNAL_ERROR 80 Internal error GNUTLS_A_USER_CANCELED 90 User canceled GNUTLS_A_NO_RENEGOTIATION 100 No renegotiation is allowed GNUTLS_A_UNSUPPORTED_EXTENSION 110 An unsupported extension was sent GNUTLS_A_CERTIFICATE_UNOBTAINABLE 111 Could not retrieve the specified certificate GNUTLS_A_UNRECOGNIZED_NAME 112 The server name sent was not recognized GNUTLS_A_UNKNOWN_PSK_IDENTITY 115 The SRP/PSK username is missing or not known  File: gnutls.info, Node: The TLS Handshake Protocol, Next: TLS Extensions, Prev: The TLS Alert Protocol, Up: Introduction to TLS 3.5 The TLS handshake protocol ============================== The handshake protocol is responsible for the ciphersuite negotiation, the initial key exchange, and the authentication of the two peers. This is fully controlled by the application layer, thus your program has to set up the required parameters. The main handshake function is *note gnutls_handshake::. In the next paragraphs we elaborate on the handshake protocol, i.e., the ciphersuite negotiation. * Menu: * TLS Cipher Suites:: TLS session parameters. * Authentication:: TLS authentication. * Client Authentication:: Requesting a certificate from the client. * Resuming Sessions:: Reusing previously established keys.  File: gnutls.info, Node: TLS Cipher Suites, Next: Authentication, Up: The TLS Handshake Protocol 3.5.1 TLS ciphersuites ---------------------- The handshake protocol of TLS negotiates cipher suites of a special form illustrated by the 'TLS_DHE_RSA_WITH_3DES_CBC_SHA' cipher suite name. A typical cipher suite contains these parameters: * The key exchange algorithm. 'DHE_RSA' in the example. * The Symmetric encryption algorithm and mode '3DES_CBC' in this example. * The MAC(1) algorithm used for authentication. 'MAC_SHA' is used in the above example. The cipher suite negotiated in the handshake protocol will affect the record protocol, by enabling encryption and data authentication. Note that you should not over rely on TLS to negotiate the strongest available cipher suite. Do not enable ciphers and algorithms that you consider weak. All the supported ciphersuites are listed in *note ciphersuites::. ---------- Footnotes ---------- (1) MAC stands for Message Authentication Code. It can be described as a keyed hash algorithm. See RFC2104.  File: gnutls.info, Node: Authentication, Next: Client Authentication, Prev: TLS Cipher Suites, Up: The TLS Handshake Protocol 3.5.2 Authentication -------------------- The key exchange algorithms of the TLS protocol offer authentication, which is a prerequisite for a secure connection. The available authentication methods in GnuTLS follow. * Certificate authentication: Authenticated key exchange using public key infrastructure and certificates (X.509 or OpenPGP). * SRP authentication: Authenticated key exchange using a password. * PSK authentication: Authenticated key exchange using a pre-shared key. * Anonymous authentication: Key exchange without peer authentication.  File: gnutls.info, Node: Client Authentication, Next: Resuming Sessions, Prev: Authentication, Up: The TLS Handshake Protocol 3.5.3 Client authentication --------------------------- In the case of ciphersuites that use certificate authentication, the authentication of the client is optional in TLS. A server may request a certificate from the client using the *note gnutls_certificate_server_set_request:: function. We elaborate in *note Certificate credentials::.  File: gnutls.info, Node: Resuming Sessions, Prev: Client Authentication, Up: The TLS Handshake Protocol 3.5.4 Resuming sessions ----------------------- The TLS handshake process performs expensive calculations and a busy server might easily be put under load. To reduce the load, session resumption may be used. This is a feature of the TLS protocol which allows a client to connect to a server after a successful handshake, without the expensive calculations. This is achieved by re-using the previously established keys, meaning the server needs to store the state of established connections (unless session tickets are used - *note Session tickets::). Session resumption is an integral part of GnuTLS, and *note Session resumption:: and *note ex:resume-client:: illustrate typical uses of it.  File: gnutls.info, Node: TLS Extensions, Next: How to use TLS in application protocols, Prev: The TLS Handshake Protocol, Up: Introduction to TLS 3.6 TLS extensions ================== A number of extensions to the TLS protocol have been proposed mainly in [_TLSEXT_]. The extensions supported in GnuTLS are: * Maximum fragment length negotiation * Server name indication * Session tickets * Safe Renegotiation and they will be discussed in the subsections that follow. * Menu: * Maximum fragment length negotiation:: * Server name indication:: * Session tickets:: * Safe renegotiation::  File: gnutls.info, Node: Maximum fragment length negotiation, Next: Server name indication, Up: TLS Extensions 3.6.1 Maximum fragment length negotiation ----------------------------------------- This extension allows a TLS implementation to negotiate a smaller value for record packet maximum length. This extension may be useful to clients with constrained capabilities. The functions shown below can be used to control this extension. 'SIZE_T *note gnutls_record_get_max_size:: (gnutls_session_t SESSION)' 'SSIZE_T *note gnutls_record_set_max_size:: (gnutls_session_t SESSION, size_t SIZE)'  File: gnutls.info, Node: Server name indication, Next: Session tickets, Prev: Maximum fragment length negotiation, Up: TLS Extensions 3.6.2 Server name indication ---------------------------- A common problem in HTTPS servers is the fact that the TLS protocol is not aware of the hostname that a client connects to, when the handshake procedure begins. For that reason the TLS server has no way to know which certificate to send. This extension solves that problem within the TLS protocol, and allows a client to send the HTTP hostname before the handshake begins within the first handshake packet. The functions *note gnutls_server_name_set:: and *note gnutls_server_name_get:: can be used to enable this extension, or to retrieve the name sent by a client. 'INT *note gnutls_server_name_set:: (gnutls_session_t SESSION, gnutls_server_name_type_t TYPE, const void * NAME, size_t NAME_LENGTH)' 'INT *note gnutls_server_name_get:: (gnutls_session_t SESSION, void * DATA, size_t * DATA_LENGTH, unsigned int * TYPE, unsigned int INDX)'  File: gnutls.info, Node: Session tickets, Next: Safe renegotiation, Prev: Server name indication, Up: TLS Extensions 3.6.3 Session tickets --------------------- To resume a TLS session the server normally store session parameters. This complicates deployment, and could be avoiding by delegating the storage to the client. Because session parameters are sensitive they are encrypted and authenticated with a key only known to the server and then sent to the client. The Session Tickets in RFC 5077 [_TLSTKT_], describe this idea, which is implemented in GnuTLS.  File: gnutls.info, Node: Safe renegotiation, Prev: Session tickets, Up: TLS Extensions 3.6.4 Safe renegotiation ------------------------ TLS gives the option to two communicating parties to renegotiate and update their security parameters. One useful example of this feature was for a client to initially connect using anonymous negotiation to a server, and the renegotiate using some authenticated ciphersuite. This occurred to avoid having the client sending its credentials in the clear. However this renegotiation, as initially designed would not ensure that the party one is renegotiating is the same as the one in the initial negotiation. For example one server could forward all renegotiation traffic to an other server who will see this traffic as an initial negotiation attempt. This might be seen as a valid design decision, but it seems it was not widely known or understood, thus today some application protocols the TLS renegotiation feature in a manner that enables a malicious server to insert content of his choice in the beginning of a TLS session. The most prominent vulnerability was with HTTPS. There servers request a renegotiation to enforce an anonymous user to use a certificate in order to access certain parts of a web site. The attack works by having the attacker simulate a client and connect to a server, with server-only authentication, and send some data intended to cause harm. The server will then require renegotiation from him in order to perform the request. When the proper client attempts to contact the server, the attacker hijacks that connection and forwards traffic to the initial server that requested renegotiation. The attacker will not be able to read the data exchanged between the client and the server. However, the server will (incorrectly) assume that the initial request sent by the attacker was sent by the now authenticated client. The result is a prefix plain-text injection attack. The above is just one example. Other vulnerabilities exists that do not rely on the TLS renegotiation to change the client's authenticated status (either TLS or application layer). While fixing these application protocols and implementations would be one natural reaction, an extension to TLS has been designed that cryptographically binds together any renegotiated handshakes with the initial negotiation. When the extension is used, the attack is detected and the session can be terminated. The extension is specified in [_RFC5746_]. GnuTLS supports the safe renegotiation extension. The default behavior is as follows. Clients will attempt to negotiate the safe renegotiation extension when talking to servers. Servers will accept the extension when presented by clients. Clients and servers will permit an initial handshake to complete even when the other side does not support the safe renegotiation extension. Clients and servers will refuse renegotiation attempts when the extension has not been negotiated. Note that permitting clients to connect to servers when the safe renegotiation extension is not enabled, is open up for attacks. Changing this default behavior would prevent interoperability against the majority of deployed servers out there. We will reconsider this default behavior in the future when more servers have been upgraded. Note that it is easy to configure clients to always require the safe renegotiation extension from servers. To modify the default behavior, we have introduced some new priority strings (see *note Priority Strings::). The '%UNSAFE_RENEGOTIATION' priority string permits (re-)handshakes even when the safe renegotiation extension was not negotiated. The default behavior is '%PARTIAL_RENEGOTIATION' that will prevent renegotiation with clients and servers not supporting the extension. This is secure for servers but leaves clients vulnerable to some attacks, but this is a trade-off between security and compatibility with old servers. The '%SAFE_RENEGOTIATION' priority string makes clients and servers require the extension for every handshake. The latter is the most secure option for clients, at the cost of not being able to connect to legacy servers. Servers will also deny clients that do not support the extension from connecting. It is possible to disable use of the extension completely, in both clients and servers, by using the '%DISABLE_SAFE_RENEGOTIATION' priority string however we strongly recommend you to only do this for debugging and test purposes. The default values if the flags above are not specified are: 'Server:' %PARTIAL_RENEGOTIATION 'Client:' %PARTIAL_RENEGOTIATION For applications we have introduced a new API related to safe renegotiation. The *note gnutls_safe_renegotiation_status:: function is used to check if the extension has been negotiated on a session, and can be used both by clients and servers.  File: gnutls.info, Node: How to use TLS in application protocols, Next: On SSL 2 and older protocols, Prev: TLS Extensions, Up: Introduction to TLS 3.7 How to use TLS in application protocols =========================================== This chapter is intended to provide some hints on how to use the TLS over simple custom made application protocols. The discussion below mainly refers to the TCP/IP transport layer but may be extended to other ones too. * Menu: * Separate ports:: * Upward negotiation::  File: gnutls.info, Node: Separate ports, Next: Upward negotiation, Up: How to use TLS in application protocols 3.7.1 Separate ports -------------------- Traditionally SSL was used in application protocols by assigning a new port number for the secure services. That way two separate ports were assigned, one for the non secure sessions, and one for the secured ones. This has the benefit that if a user requests a secure session then the client will try to connect to the secure port and fail otherwise. The only possible attack with this method is a denial of service one. The most famous example of this method is the famous "HTTP over TLS" or HTTPS protocol [_RFC2818_]. Despite its wide use, this method is not as good as it seems. This approach starts the TLS Handshake procedure just after the client connects on the --so called-- secure port. That way the TLS protocol does not know anything about the client, and popular methods like the host advertising in HTTP do not work(1). There is no way for the client to say "I connected to YYY server" before the Handshake starts, so the server cannot possibly know which certificate to use. Other than that it requires two separate ports to run a single service, which is unnecessary complication. Due to the fact that there is a limitation on the available privileged ports, this approach was soon obsoleted. ---------- Footnotes ---------- (1) See also the Server Name Indication extension on *note serverind::.  File: gnutls.info, Node: Upward negotiation, Prev: Separate ports, Up: How to use TLS in application protocols 3.7.2 Upward negotiation ------------------------ Other application protocols(1) use a different approach to enable the secure layer. They use something often called as the "TLS upgrade" method. This method is quite tricky but it is more flexible. The idea is to extend the application protocol to have a "STARTTLS" request, whose purpose it to start the TLS protocols just after the client requests it. This approach does not require any extra port to be reserved. There is even an extension to HTTP protocol to support that method [_RFC2817_]. The tricky part, in this method, is that the "STARTTLS" request is sent in the clear, thus is vulnerable to modifications. A typical attack is to modify the messages in a way that the client is fooled and thinks that the server does not have the "STARTTLS" capability. See a typical conversation of a hypothetical protocol: (client connects to the server) CLIENT: HELLO I'M MR. XXX SERVER: NICE TO MEET YOU XXX CLIENT: PLEASE START TLS SERVER: OK *** TLS STARTS CLIENT: HERE ARE SOME CONFIDENTIAL DATA And see an example of a conversation where someone is acting in between: (client connects to the server) CLIENT: HELLO I'M MR. XXX SERVER: NICE TO MEET YOU XXX CLIENT: PLEASE START TLS (here someone inserts this message) SERVER: SORRY I DON'T HAVE THIS CAPABILITY CLIENT: HERE ARE SOME CONFIDENTIAL DATA As you can see above the client was fooled, and was dummy enough to send the confidential data in the clear. How to avoid the above attack? As you may have already noticed this one is easy to avoid. The client has to ask the user before it connects whether the user requests TLS or not. If the user answered that he certainly wants the secure layer the last conversation should be: (client connects to the server) CLIENT: HELLO I'M MR. XXX SERVER: NICE TO MEET YOU XXX CLIENT: PLEASE START TLS (here someone inserts this message) SERVER: SORRY I DON'T HAVE THIS CAPABILITY CLIENT: BYE (the client notifies the user that the secure connection was not possible) This method, if implemented properly, is far better than the traditional method, and the security properties remain the same, since only denial of service is possible. The benefit is that the server may request additional data before the TLS Handshake protocol starts, in order to send the correct certificate, use the correct password file, or anything else! ---------- Footnotes ---------- (1) See LDAP, IMAP etc.  File: gnutls.info, Node: On SSL 2 and older protocols, Prev: How to use TLS in application protocols, Up: Introduction to TLS 3.8 On SSL 2 and older protocols ================================ One of the initial decisions in the GnuTLS development was to implement the known security protocols for the transport layer. Initially TLS 1.0 was implemented since it was the latest at that time, and was considered to be the most advanced in security properties. Later the SSL 3.0 protocol was implemented since it is still the only protocol supported by several servers and there are no serious security vulnerabilities known. One question that may arise is why we didn't implement SSL 2.0 in the library. There are several reasons, most important being that it has serious security flaws, unacceptable for a modern security library. Other than that, this protocol is barely used by anyone these days since it has been deprecated since 1996. The security problems in SSL 2.0 include: * Message integrity compromised. The SSLv2 message authentication uses the MD5 function, and is insecure. * Man-in-the-middle attack. There is no protection of the handshake in SSLv2, which permits a man-in-the-middle attack. * Truncation attack. SSLv2 relies on TCP FIN to close the session, so the attacker can forge a TCP FIN, and the peer cannot tell if it was a legitimate end of data or not. * Weak message integrity for export ciphers. The cryptographic keys in SSLv2 are used for both message authentication and encryption, so if weak encryption schemes are negotiated (say 40-bit keys) the message authentication code uses the same weak key, which isn't necessary. Other protocols such as Microsoft's PCT 1 and PCT 2 were not implemented because they were also abandoned and deprecated by SSL 3.0 and later TLS 1.0.  File: gnutls.info, Node: Certificate authentication, Next: Shared-key and anonymous authentication, Prev: Introduction to TLS, Up: Top 4 Certificate authentication **************************** The most known authentication method of TLS are certificates. The PKIX [_PKIX_] public key infrastructure is daily used by anyone using a browser today. GnuTLS supports both X.509 certificates [_PKIX_] and OpenPGP certificates using a common API. The key exchange algorithms supported by certificate authentication are shown in *note Table 4.1: tab:key-exchange. Key exchange Description ------------------------------------------------------------------ RSA The RSA algorithm is used to encrypt a key and send it to the peer. The certificate must allow the key to be used for encryption. RSA_EXPORT The RSA algorithm is used to encrypt a key and send it to the peer. In the EXPORT algorithm, the server signs temporary RSA parameters of 512 bits -- which are considered weak -- and sends them to the client. DHE_RSA The RSA algorithm is used to sign ephemeral Diffie-Hellman parameters which are sent to the peer. The key in the certificate must allow the key to be used for signing. Note that key exchange algorithms which use ephemeral Diffie-Hellman parameters, offer perfect forward secrecy. That means that even if the private key used for signing is compromised, it cannot be used to reveal past session data. ECDHE_RSA The RSA algorithm is used to sign ephemeral elliptic curve Diffie-Hellman parameters which are sent to the peer. The key in the certificate must allow the key to be used for signing. It also offers perfect forward secrecy. That means that even if the private key used for signing is compromised, it cannot be used to reveal past session data. DHE_DSS The DSA algorithm is used to sign ephemeral Diffie-Hellman parameters which are sent to the peer. The certificate must contain DSA parameters to use this key exchange algorithm. DSA is the algorithm of the Digital Signature Standard (DSS). ECDHE_ECDSA The Elliptic curve DSA algorithm is used to sign ephemeral elliptic curve Diffie-Hellman parameters which are sent to the peer. The certificate must contain ECDSA parameters to use this key exchange algorithm. Table 4.1: Supported key exchange algorithms. * Menu: * X.509 certificates:: * OpenPGP certificates:: * Digital signatures::  File: gnutls.info, Node: X.509 certificates, Next: OpenPGP certificates, Up: Certificate authentication 4.1 X.509 certificates ====================== The X.509 protocols rely on a hierarchical trust model. In this trust model Certification Authorities (CAs) are used to certify entities. Usually more than one certification authorities exist, and certification authorities may certify other authorities to issue certificates as well, following a hierarchical model. [image src="gnutls-x509.png"] Figure 4.1: An example of the X.509 hierarchical trust model. One needs to trust one or more CAs for his secure communications. In that case only the certificates issued by the trusted authorities are acceptable. The framework is illustrated on *note Figure 4.1: fig:x509. * Menu: * X.509 certificate structure:: * Importing an X.509 certificate:: * X.509 distinguished names:: * Verifying X.509 certificate paths:: * Verifying a certificate in the context of TLS session:: * Verifying a certificate using trust on first use authentication::  File: gnutls.info, Node: X.509 certificate structure, Next: Importing an X.509 certificate, Up: X.509 certificates 4.1.1 X.509 certificate structure --------------------------------- An X.509 certificate usually contains information about the certificate holder, the signer, a unique serial number, expiration dates and some other fields [_PKIX_] as shown in *note Table 4.2: tab:x509. Field Description ------------------------------------------------------------------ version The field that indicates the version of the certificate. serialNumber This field holds a unique serial number per certificate. signature The issuing authority's signature. issuer Holds the issuer's distinguished name. validity The activation and expiration dates. subject The subject's distinguished name of the certificate. extensions The extensions are fields only present in version 3 certificates. Table 4.2: X.509 certificate fields. The certificate's _subject or issuer name_ is not just a single string. It is a Distinguished name and in the ASN.1 notation is a sequence of several object identifiers with their corresponding values. Some of available OIDs to be used in an X.509 distinguished name are defined in 'gnutls/x509.h'. The _Version_ field in a certificate has values either 1 or 3 for version 3 certificates. Version 1 certificates do not support the extensions field so it is not possible to distinguish a CA from a person, thus their usage should be avoided. The _validity_ dates are there to indicate the date that the specific certificate was activated and the date the certificate's key would be considered invalid. Certificate _extensions_ are there to include information about the certificate's subject that did not fit in the typical certificate fields. Those may be e-mail addresses, flags that indicate whether the belongs to a CA etc. All the supported X.509 version 3 extensions are shown in *note Table 4.3: tab:x509-ext. Extension OID Description -------------------------------------------------------------------- Subject key id 2.5.29.14 An identifier of the key of the subject. Authority key id 2.5.29.35 An identifier of the authority's key used to sign the certificate. Subject alternative 2.5.29.17 Alternative names to name subject's distinguished name. Key usage 2.5.29.15 Constraints the key's usage of the certificate. Extended key usage 2.5.29.37 Constraints the purpose of the certificate. Basic constraints 2.5.29.19 Indicates whether this is a CA certificate or not, and specify the maximum path lengths of certificate chains. CRL distribution 2.5.29.31 This extension is set by points the CA, in order to inform about the issued CRLs. Proxy Certification 1.3.6.1.5.5.7.1.14Proxy Certificates includes Information this extension that contains the OID of the proxy policy language used, and can specify limits on the maximum lengths of proxy chains. Proxy Certificates are specified in [_RFC3820_]. Table 4.3: X.509 certificate extensions. In GnuTLS the X.509 certificate structures are handled using the 'gnutls_x509_crt_t' type and the corresponding private keys with the 'gnutls_x509_privkey_t' type. All the available functions for X.509 certificate handling have their prototypes in 'gnutls/x509.h'. An example program to demonstrate the X.509 parsing capabilities can be found at *note ex:x509-info::.  File: gnutls.info, Node: Importing an X.509 certificate, Next: X.509 distinguished names, Prev: X.509 certificate structure, Up: X.509 certificates 4.1.2 Importing an X.509 certificate ------------------------------------ The certificate structure should be initialized using *note gnutls_x509_crt_init::, and a certificate structure can be imported using *note gnutls_x509_crt_import::. 'INT *note gnutls_x509_crt_init:: (gnutls_x509_crt_t * CERT)' 'INT *note gnutls_x509_crt_import:: (gnutls_x509_crt_t CERT, const gnutls_datum_t * DATA, gnutls_x509_crt_fmt_t FORMAT)' 'VOID *note gnutls_x509_crt_deinit:: (gnutls_x509_crt_t CERT)' In several functions an array of certificates is required. To assist in initialization and import the following two functions are provided. 'INT *note gnutls_x509_crt_list_import:: (gnutls_x509_crt_t * CERTS, unsigned int * CERT_MAX, const gnutls_datum_t * DATA, gnutls_x509_crt_fmt_t FORMAT, unsigned int FLAGS)' 'INT *note gnutls_x509_crt_list_import2:: (gnutls_x509_crt_t ** CERTS, unsigned int * SIZE, const gnutls_datum_t * DATA, gnutls_x509_crt_fmt_t FORMAT, unsigned int FLAGS)' In all cases after use a certificate must be deinitialized using *note gnutls_x509_crt_deinit::. Note that although the functions above apply to 'gnutls_x509_crt_t' structure, similar functions exist for the CRL structure 'gnutls_x509_crl_t'.  File: gnutls.info, Node: X.509 distinguished names, Next: Verifying X.509 certificate paths, Prev: Importing an X.509 certificate, Up: X.509 certificates 4.1.3 X.509 distinguished names ------------------------------- The "subject" of an X.509 certificate is not described by a single name, but rather with a distinguished name. This in X.509 terminology is a list of strings each associated an object identifier. To make things simple GnuTLS provides *note gnutls_x509_crt_get_dn:: which follows the rules in [_RFC4514_] and returns a single string. Access to each string by individual object identifiers can be accessed using *note gnutls_x509_crt_get_dn_by_oid::. -- Function: int gnutls_x509_crt_get_dn (gnutls_x509_crt_t CERT, char * BUF, size_t * BUF_SIZE) CERT: should contain a 'gnutls_x509_crt_t' structure BUF: a pointer to a structure to hold the name (may be null) BUF_SIZE: initially holds the size of 'buf' This function will copy the name of the Certificate in the provided buffer. The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC4514. The output string will be ASCII or UTF-8 encoded, depending on the certificate data. If 'buf' is null then only the size will be filled. *Returns:* 'GNUTLS_E_SHORT_MEMORY_BUFFER' if the provided buffer is not long enough, and in that case the 'buf_size' will be updated with the required size. On success 0 is returned. -- Function: int gnutls_x509_crt_get_dn_by_oid (gnutls_x509_crt_t CERT, const char * OID, int INDX, unsigned int RAW_FLAG, void * BUF, size_t * BUF_SIZE) CERT: should contain a 'gnutls_x509_crt_t' structure OID: holds an Object Identified in null terminated string INDX: In case multiple same OIDs exist in the RDN, this specifies which to send. Use (0) to get the first one. RAW_FLAG: If non (0) returns the raw DER data of the DN part. BUF: a pointer where the DN part will be copied (may be null). BUF_SIZE: initially holds the size of 'buf' This function will extract the part of the name of the Certificate subject specified by the given OID. The output, if the raw flag is not used, will be encoded as described in RFC4514. Thus a string that is ASCII or UTF-8 encoded, depending on the certificate data. Some helper macros with popular OIDs can be found in gnutls/x509.h If raw flag is (0), this function will only return known OIDs as text. Other OIDs will be DER encoded, as described in RFC4514 - in hex format with a '#' prefix. You can check about known OIDs using 'gnutls_x509_dn_oid_known()' . If 'buf' is null then only the size will be filled. If the 'raw_flag' is not specified the output is always null terminated, although the 'buf_size' will not include the null character. *Returns:* 'GNUTLS_E_SHORT_MEMORY_BUFFER' if the provided buffer is not long enough, and in that case the *buf_size will be updated with the required size. On success 0 is returned. -- Function: int gnutls_x509_crt_get_dn_oid (gnutls_x509_crt_t CERT, int INDX, void * OID, size_t * OID_SIZE) CERT: should contain a 'gnutls_x509_crt_t' structure INDX: This specifies which OID to return. Use (0) to get the first one. OID: a pointer to a buffer to hold the OID (may be null) OID_SIZE: initially holds the size of 'oid' This function will extract the OIDs of the name of the Certificate subject specified by the given index. If 'oid' is null then only the size will be filled. The 'oid' returned will be null terminated, although 'oid_size' will not account for the trailing null. *Returns:* 'GNUTLS_E_SHORT_MEMORY_BUFFER' if the provided buffer is not long enough, and in that case the 'oid_size' will be updated with the required size. On success 0 is returned. The more powerful *note gnutls_x509_crt_get_subject:: and *note gnutls_x509_dn_get_rdn_ava:: provide efficient access to the contents of the distinguished name structure. -- Function: int gnutls_x509_crt_get_subject (gnutls_x509_crt_t CERT, gnutls_x509_dn_t * DN) CERT: should contain a 'gnutls_x509_crt_t' structure DN: output variable with pointer to uint8_t DN. Return the Certificate's Subject DN as an uint8_t data type. You may use 'gnutls_x509_dn_get_rdn_ava()' to decode the DN. Note that 'dn' should be treated as constant. Because points into the 'cert' object, you may not deallocate 'cert' and continue to access 'dn' . *Returns:* Returns 0 on success, or an error code. -- Function: int gnutls_x509_dn_get_rdn_ava (gnutls_x509_dn_t DN, int IRDN, int IAVA, gnutls_x509_ava_st * AVA) DN: input variable with uint8_t DN pointer IRDN: index of RDN IAVA: index of AVA. AVA: Pointer to structure which will hold output information. Get pointers to data within the DN. Note that 'ava' will contain pointers into the 'dn' structure, so you should not modify any data or deallocate it. Note also that the DN in turn points into the original certificate structure, and thus you may not deallocate the certificate and continue to access 'dn' . *Returns:* Returns 0 on success, or an error code. Similar functions exist to access the distinguished name of the issuer of the certificate. 'INT *note gnutls_x509_crt_get_issuer_dn:: (gnutls_x509_crt_t CERT, char * BUF, size_t * BUF_SIZE)' 'INT *note gnutls_x509_crt_get_issuer_dn_by_oid:: (gnutls_x509_crt_t CERT, const char * OID, int INDX, unsigned int RAW_FLAG, void * BUF, size_t * BUF_SIZE)' 'INT *note gnutls_x509_crt_get_issuer_dn_oid:: (gnutls_x509_crt_t CERT, int INDX, void * OID, size_t * OID_SIZE)' 'INT *note gnutls_x509_crt_get_issuer:: (gnutls_x509_crt_t CERT, gnutls_x509_dn_t * DN)'  File: gnutls.info, Node: Verifying X.509 certificate paths, Next: Verifying a certificate in the context of TLS session, Prev: X.509 distinguished names, Up: X.509 certificates 4.1.4 Verifying X.509 certificate paths --------------------------------------- Verifying certificate paths is important in X.509 authentication. For this purpose the following functions are provided. -- Function: int gnutls_x509_trust_list_add_cas (gnutls_x509_trust_list_t LIST, const gnutls_x509_crt_t * CLIST, int CLIST_SIZE, unsigned int FLAGS) LIST: The structure of the list CLIST: A list of CAs CLIST_SIZE: The length of the CA list FLAGS: should be 0. This function will add the given certificate authorities to the trusted list. The list of CAs must not be deinitialized during this structure's lifetime. *Returns:* The number of added elements is returned. *Since:* 3.0 -- Function: int gnutls_x509_trust_list_add_named_crt (gnutls_x509_trust_list_t LIST, gnutls_x509_crt_t CERT, const void * NAME, size_t NAME_SIZE, unsigned int FLAGS) LIST: The structure of the list CERT: A certificate NAME: An identifier for the certificate NAME_SIZE: The size of the identifier FLAGS: should be 0. This function will add the given certificate to the trusted list and associate it with a name. The certificate will not be be used for verification with 'gnutls_x509_trust_list_verify_crt()' but only with 'gnutls_x509_trust_list_verify_named_crt()' . In principle this function can be used to set individual "server" certificates that are trusted by the user for that specific server but for no other purposes. The certificate must not be deinitialized during the lifetime of the trusted list. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 3.0 -- Function: int gnutls_x509_trust_list_add_crls (gnutls_x509_trust_list_t LIST, const gnutls_x509_crl_t * CRL_LIST, int CRL_SIZE, unsigned int FLAGS, unsigned int VERIFICATION_FLAGS) LIST: The structure of the list CRL_LIST: A list of CRLs CRL_SIZE: The length of the CRL list FLAGS: if GNUTLS_TL_VERIFY_CRL is given the CRLs will be verified before being added. VERIFICATION_FLAGS: gnutls_certificate_verify_flags if flags specifies GNUTLS_TL_VERIFY_CRL This function will add the given certificate revocation lists to the trusted list. The list of CRLs must not be deinitialized during this structure's lifetime. This function must be called after 'gnutls_x509_trust_list_add_cas()' to allow verifying the CRLs for validity. *Returns:* The number of added elements is returned. *Since:* 3.0 -- Function: int gnutls_x509_trust_list_verify_crt (gnutls_x509_trust_list_t LIST, gnutls_x509_crt_t * CERT_LIST, unsigned int CERT_LIST_SIZE, unsigned int FLAGS, unsigned int * VERIFY, gnutls_verify_output_function FUNC) LIST: The structure of the list CERT_LIST: is the certificate list to be verified CERT_LIST_SIZE: is the certificate list size FLAGS: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations. VERIFY: will hold the certificate verification output. FUNC: If non-null will be called on each chain element verification with the output. This function will try to verify the given certificate and return its status. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 3.0 -- Function: int gnutls_x509_trust_list_verify_named_crt (gnutls_x509_trust_list_t LIST, gnutls_x509_crt_t CERT, const void * NAME, size_t NAME_SIZE, unsigned int FLAGS, unsigned int * VERIFY, gnutls_verify_output_function FUNC) LIST: The structure of the list CERT: is the certificate to be verified NAME: is the certificate's name NAME_SIZE: is the certificate's name size FLAGS: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations. VERIFY: will hold the certificate verification output. FUNC: If non-null will be called on each chain element verification with the output. This function will try to find a matching named certificate. If a match is found the certificate is considered valid. In addition to that this function will also check CRLs. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 3.0 The verification function will verify a given certificate chain against a list of certificate authorities and certificate revocation lists, and output a bit-wise OR of elements of the 'gnutls_certificate_status_t' enumeration shown in *note Figure 4.2: gnutls_certificate_status_t. The 'GNUTLS_CERT_INVALID' flag is always set on a verification error and more detailed flags will also be set when appropriate. 'GNUTLS_CERT_INVALID' The certificate is not signed by one of the known authorities or the signature is invalid. 'GNUTLS_CERT_REVOKED' Certificate is revoked by its authority. In X.509 this will be set only if CRLs are checked. 'GNUTLS_CERT_SIGNER_NOT_FOUND' The certificate's issuer is not known. This is the case if the issuer is not included in the trusted certificate list. 'GNUTLS_CERT_SIGNER_NOT_CA' The certificate's signer was not a CA. This may happen if this was a version 1 certificate, which is common with some CAs, or a version 3 certificate without the basic constrains extension. 'GNUTLS_CERT_INSECURE_ALGORITHM' The certificate was signed using an insecure algorithm such as MD2 or MD5. These algorithms have been broken and should not be trusted. 'GNUTLS_CERT_NOT_ACTIVATED' The certificate is not yet activated. 'GNUTLS_CERT_EXPIRED' The certificate has expired. 'GNUTLS_CERT_SIGNATURE_FAILURE' - undescribed - 'GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED' The revocation data are old and have been superseded. 'GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE' The revocation data have a future issue date. Figure 4.2: The 'gnutls_certificate_status_t' enumeration. An example of certificate verification is shown in *note ex:verify2::. It is also possible to have a set of certificates that are trusted for a particular server but not to authorize other certificates. This purpose is served by the functions *note gnutls_x509_trust_list_add_named_crt:: and *note gnutls_x509_trust_list_verify_named_crt::.  File: gnutls.info, Node: Verifying a certificate in the context of TLS session, Next: Verifying a certificate using trust on first use authentication, Prev: Verifying X.509 certificate paths, Up: X.509 certificates 4.1.5 Verifying a certificate in the context of TLS session ----------------------------------------------------------- When operating in the context of a TLS session, the trusted certificate authority list may also be set using: 'INT *note gnutls_certificate_set_x509_trust_file:: (gnutls_certificate_credentials_t CRED, const char * CAFILE, gnutls_x509_crt_fmt_t TYPE)' 'INT *note gnutls_certificate_set_x509_crl_file:: (gnutls_certificate_credentials_t RES, const char * CRLFILE, gnutls_x509_crt_fmt_t TYPE)' 'INT *note gnutls_certificate_set_x509_system_trust:: (gnutls_certificate_credentials_t CRED)' Then it is not required to setup a trusted list as above. The function *note gnutls_certificate_verify_peers2:: may then be used to verify the peer's certificate chain. The flags are set similarly to the verification functions in the previous section. There is also the possibility to pass some input to the verification functions in the form of flags. For *note gnutls_x509_trust_list_verify_crt:: the flags are passed straightforward, but *note gnutls_certificate_verify_peers2:: depends on the flags set by calling *note gnutls_certificate_set_verify_flags::. All the available flags are part of the enumeration 'gnutls_certificate_verify_flags' shown in *note Figure 4.3: gnutls_certificate_verify_flags. 'GNUTLS_VERIFY_DISABLE_CA_SIGN' If set a signer does not have to be a certificate authority. This flag should normaly be disabled, unless you know what this means. 'GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT' Allow trusted CA certificates with version 1. This is safer than 'GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT' , and should be used instead. That way only signers in your trusted list will be allowed to have certificates of version 1. This is the default. 'GNUTLS_VERIFY_DO_NOT_ALLOW_SAME' If a certificate is not signed by anyone trusted but exists in the trusted CA list do not treat it as trusted. 'GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT' Allow CA certificates that have version 1 (both root and intermediate). This might be dangerous since those haven't the basicConstraints extension. Must be used in combination with 'GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT' . 'GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2' Allow certificates to be signed using the broken MD2 algorithm. 'GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5' Allow certificates to be signed using the broken MD5 algorithm. 'GNUTLS_VERIFY_DISABLE_TIME_CHECKS' Disable checking of activation and expiration validity periods of certificate chains. Don't set this unless you understand the security implications. 'GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS' If set a signer in the trusted list is never checked for expiration or activation. 'GNUTLS_VERIFY_DO_NOT_ALLOW_X509_V1_CA_CRT' Do not allow trusted CA certificates that have version 1. This option is to be used to deprecate all certificates of version 1. 'GNUTLS_VERIFY_DISABLE_CRL_CHECKS' Disable checking for validity using certificate revocation lists. 'GNUTLS_VERIFY_ALLOW_UNSORTED_CHAIN' A certificate chain is tolerated if unsorted (the case with many TLS servers out there). Figure 4.3: The 'gnutls_certificate_verify_flags' enumeration. Although the verification of a certificate path indicates that the certificate is signed by trusted authority, does not reveal anything about the peer's identity. It is required to verify if the certificate's owner is the one you expect. For more information consult [_RFC2818_] and section *note ex:verify:: for an example.  File: gnutls.info, Node: Verifying a certificate using trust on first use authentication, Prev: Verifying a certificate in the context of TLS session, Up: X.509 certificates 4.1.6 Verifying a certificate using trust on first use authentication --------------------------------------------------------------------- It is possible to use a trust on first use (similar to SSH) authentication method in GnuTLS. That is the concept used by the SSH programs, where the public key of the peer is not verified, or verified in an out-of-bound way, but subsequent connections to the same peer require the public key to remain the same. Such a system in combination with the typical CA verification of a certificate, and OCSP revocation checks, can help to provide multiple factor verification, where a single point of failure is not enough to compromise the system. For example a server compromise may be detected using OCSP, and a CA compromise can be detected using the trust on first use method. Such a hybrid system with X.509 and trust on first use authentication is shown in *note Simple client example with SSH-style certificate verification::. -- Function: int gnutls_verify_stored_pubkey (const char* DB_NAME, gnutls_tdb_t TDB, const char* HOST, const char* SERVICE, gnutls_certificate_type_t CERT_TYPE, const gnutls_datum_t * CERT, unsigned int FLAGS) DB_NAME: A file specifying the stored keys (use NULL for the default) TDB: A storage structure or NULL to use the default HOST: The peer's name SERVICE: non-NULL if this key is specific to a service (e.g. http) CERT_TYPE: The type of the certificate CERT: The raw (der) data of the certificate FLAGS: should be 0. This function will try to verify the provided certificate using a list of stored public keys. The 'service' field if non-NULL should be a port number. The 'retrieve' variable if non-null specifies a custom backend for the retrieval of entries. If it is NULL then the default file backend will be used. In POSIX-like systems the file backend uses the $HOME/.gnutls/known_hosts file. Note that if the custom storage backend is provided the retrieval function should return 'GNUTLS_E_CERTIFICATE_KEY_MISMATCH' if the host/service pair is found but key doesn't match, 'GNUTLS_E_NO_CERTIFICATE_FOUND' if no such host/service with the given key is found, and 0 if it was found. The storage function should return 0 on success. *Returns:* If no associated public key is found then 'GNUTLS_E_NO_CERTIFICATE_FOUND' will be returned. If a key is found but does not match 'GNUTLS_E_CERTIFICATE_KEY_MISMATCH' is returned. On success, 'GNUTLS_E_SUCCESS' (0) is returned, or a negative error value on other errors. *Since:* 3.0 -- Function: int gnutls_store_pubkey (const char* DB_NAME, gnutls_tdb_t TDB, const char* HOST, const char* SERVICE, gnutls_certificate_type_t CERT_TYPE, const gnutls_datum_t * CERT, time_t EXPIRATION, unsigned int FLAGS) DB_NAME: A file specifying the stored keys (use NULL for the default) TDB: A storage structure or NULL to use the default HOST: The peer's name SERVICE: non-NULL if this key is specific to a service (e.g. http) CERT_TYPE: The type of the certificate CERT: The data of the certificate EXPIRATION: The expiration time (use 0 to disable expiration) FLAGS: should be 0. This function will store the provided certificate to the list of stored public keys. The key will be considered valid until the provided expiration time. The 'store' variable if non-null specifies a custom backend for the storage of entries. If it is NULL then the default file backend will be used. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 3.0 In addition to the above the *note gnutls_store_commitment:: can be used to implement a key-pinning architecture as in [_KEYPIN_]. This provides a way for web server to commit on a public key that is not yet active. -- Function: int gnutls_store_commitment (const char* DB_NAME, gnutls_tdb_t TDB, const char* HOST, const char* SERVICE, gnutls_digest_algorithm_t HASH_ALGO, const gnutls_datum_t* HASH, time_t EXPIRATION, unsigned int FLAGS) DB_NAME: A file specifying the stored keys (use NULL for the default) TDB: A storage structure or NULL to use the default HOST: The peer's name SERVICE: non-NULL if this key is specific to a service (e.g. http) HASH_ALGO: The hash algorithm type HASH: The raw hash EXPIRATION: The expiration time (use 0 to disable expiration) FLAGS: should be 0. This function will store the provided hash commitment to the list of stored public keys. The key with the given hash will be considered valid until the provided expiration time. The 'store' variable if non-null specifies a custom backend for the storage of entries. If it is NULL then the default file backend will be used. Note that this function is not thread safe with the default backend. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 3.0 The storage and verification functions may be used with the default text file based back-end, or another back-end may be specified. That should contain storage and retrieval functions and specified as below. 'INT *note gnutls_tdb_init:: (gnutls_tdb_t* TDB)' 'VOID *note gnutls_tdb_deinit:: (gnutls_tdb_t TDB)' 'VOID *note gnutls_tdb_set_verify_func:: (gnutls_tdb_t TDB, gnutls_tdb_verify_func VERIFY)' 'VOID *note gnutls_tdb_set_store_func:: (gnutls_tdb_t TDB, gnutls_tdb_store_func STORE)' 'VOID *note gnutls_tdb_set_store_commitment_func:: (gnutls_tdb_t TDB, gnutls_tdb_store_commitment_func CSTORE)'  File: gnutls.info, Node: OpenPGP certificates, Next: Digital signatures, Prev: X.509 certificates, Up: Certificate authentication 4.2 OpenPGP certificates ======================== The OpenPGP key authentication relies on a distributed trust model, called the "web of trust". The "web of trust" uses a decentralized system of trusted introducers, which are the same as a CA. OpenPGP allows anyone to sign anyone else's public key. When Alice signs Bob's key, she is introducing Bob's key to anyone who trusts Alice. If someone trusts Alice to introduce keys, then Alice is a trusted introducer in the mind of that observer. For example in *note Figure 4.4: fig:openpgp, David trusts Alice to be an introducer and Alice signed Bob's key thus Dave trusts Bob's key to be the real one. [image src="gnutls-pgp.png"] Figure 4.4: An example of the OpenPGP trust model. There are some key points that are important in that model. In the example Alice has to sign Bob's key, only if she is sure that the key belongs to Bob. Otherwise she may also make Dave falsely believe that this is Bob's key. Dave has also the responsibility to know who to trust. This model is similar to real life relations. Just see how Charlie behaves in the previous example. Although he has signed Bob's key - because he knows, somehow, that it belongs to Bob - he does not trust Bob to be an introducer. Charlie decided to trust only Kevin, for some reason. A reason could be that Bob is lazy enough, and signs other people's keys without being sure that they belong to the actual owner. 4.2.1 OpenPGP certificate structure ----------------------------------- In GnuTLS the OpenPGP key structures [_RFC2440_] are handled using the 'gnutls_openpgp_crt_t' type and the corresponding private keys with the 'gnutls_openpgp_privkey_t' type. All the prototypes for the key handling functions can be found at 'gnutls/openpgp.h'. 4.2.2 Verifying an OpenPGP certificate -------------------------------------- The verification functions of OpenPGP keys, included in GnuTLS, are simple ones, and do not use the features of the "web of trust". For that reason, if the verification needs are complex, the assistance of external tools like GnuPG and GPGME(1) is recommended. In GnuTLS there is a verification function for OpenPGP certificates, the *note gnutls_openpgp_crt_verify_ring::. This checks an OpenPGP key against a given set of public keys (keyring) and returns the key status. The key verification status is the same as in X.509 certificates, although the meaning and interpretation are different. For example an OpenPGP key may be valid, if the self signature is ok, even if no signers were found. The meaning of verification status flags is the same as in the X.509 certificates (see *note Figure 4.3: gnutls_certificate_verify_flags.). -- Function: int gnutls_openpgp_crt_verify_ring (gnutls_openpgp_crt_t KEY, gnutls_openpgp_keyring_t KEYRING, unsigned int FLAGS, unsigned int * VERIFY) KEY: the structure that holds the key. KEYRING: holds the keyring to check against FLAGS: unused (should be 0) VERIFY: will hold the certificate verification output. Verify all signatures in the key, using the given set of keys (keyring). The key verification output will be put in 'verify' and will be one or more of the 'gnutls_certificate_status_t' enumerated elements bitwise or'd. *Returns:* 'GNUTLS_E_SUCCESS' on success, or an error code. -- Function: int gnutls_openpgp_crt_verify_self (gnutls_openpgp_crt_t KEY, unsigned int FLAGS, unsigned int * VERIFY) KEY: the structure that holds the key. FLAGS: unused (should be 0) VERIFY: will hold the key verification output. Verifies the self signature in the key. The key verification output will be put in 'verify' and will be one or more of the gnutls_certificate_status_t enumerated elements bitwise or'd. *Returns:* 'GNUTLS_E_SUCCESS' on success, or an error code. 4.2.3 Verifying a certificate in the context of a TLS session ------------------------------------------------------------- Similarly with X.509 certificates, one needs to specify the OpenPGP keyring file in the credentials structure. The certificates in this file will be used by *note gnutls_certificate_verify_peers2:: to verify the signatures in the certificate sent by the peer. -- Function: int gnutls_certificate_set_openpgp_keyring_file (gnutls_certificate_credentials_t C, const char * FILE, gnutls_openpgp_crt_fmt_t FORMAT) C: A certificate credentials structure FILE: filename of the keyring. FORMAT: format of keyring. The function is used to set keyrings that will be used internally by various OpenPGP functions. For example to find a key when it is needed for an operations. The keyring will also be used at the verification functions. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. ---------- Footnotes ---------- (1)  File: gnutls.info, Node: Digital signatures, Prev: OpenPGP certificates, Up: Certificate authentication 4.3 Digital signatures ====================== In this section we will provide some information about digital signatures, how they work, and give the rationale for disabling some of the algorithms used. Digital signatures work by using somebody's secret key to sign some arbitrary data. Then anybody else could use the public key of that person to verify the signature. Since the data may be arbitrary it is not suitable input to a cryptographic digital signature algorithm. For this reason and also for performance cryptographic hash algorithms are used to preprocess the input to the signature algorithm. This works as long as it is difficult enough to generate two different messages with the same hash algorithm output. In that case the same signature could be used as a proof for both messages. Nobody wants to sign an innocent message of donating 1 euro to Greenpeace and find out that he donated 1.000.000 euros to Bad Inc. For a hash algorithm to be called cryptographic the following three requirements must hold: 1. Preimage resistance. That means the algorithm must be one way and given the output of the hash function H(x), it is impossible to calculate x. 2. 2nd preimage resistance. That means that given a pair x,y with y=H(x) it is impossible to calculate an x' such that y=H(x'). 3. Collision resistance. That means that it is impossible to calculate random x and x' such H(x')=H(x). The last two requirements in the list are the most important in digital signatures. These protect against somebody who would like to generate two messages with the same hash output. When an algorithm is considered broken usually it means that the Collision resistance of the algorithm is less than brute force. Using the birthday paradox the brute force attack takes 2^{((hash size) / 2)} operations. Today colliding certificates using the MD5 hash algorithm have been generated as shown in [_WEGER_]. There has been cryptographic results for the SHA-1 hash algorithms as well, although they are not yet critical. Before 2004, MD5 had a presumed collision strength of 2^{64}, but it has been showed to have a collision strength well under 2^{50}. As of November 2005, it is believed that SHA-1's collision strength is around 2^{63}. We consider this sufficiently hard so that we still support SHA-1. We anticipate that SHA-256/386/512 will be used in publicly-distributed certificates in the future. When 2^{63} can be considered too weak compared to the computer power available sometime in the future, SHA-1 will be disabled as well. The collision attacks on SHA-1 may also get better, given the new interest in tools for creating them. 4.3.1 Trading security for interoperability ------------------------------------------- If you connect to a server and use GnuTLS' functions to verify the certificate chain, and get a 'GNUTLS_CERT_INSECURE_ALGORITHM' validation error (see *note Verifying X.509 certificate paths::), it means that somewhere in the certificate chain there is a certificate signed using 'RSA-MD2' or 'RSA-MD5'. These two digital signature algorithms are considered broken, so GnuTLS fails verifying the certificate. In some situations, it may be useful to be able to verify the certificate chain anyway, assuming an attacker did not utilize the fact that these signatures algorithms are broken. This section will give help on how to achieve that. It is important to know that you do not have to enable any of the flags discussed here to be able to use trusted root CA certificates self-signed using 'RSA-MD2' or 'RSA-MD5'. The certificates in the trusted list are considered trusted irrespective of the signature. If you are using *note gnutls_certificate_verify_peers2:: to verify the certificate chain, you can call *note gnutls_certificate_set_verify_flags:: with the flags: * 'GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2' * 'GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5' as in the following example: gnutls_certificate_set_verify_flags (x509cred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); This will tell the verifier algorithm to enable 'RSA-MD5' when verifying the certificates. If you are using *note gnutls_x509_crt_verify:: or *note gnutls_x509_crt_list_verify::, you can pass the 'GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5' parameter directly in the 'flags' parameter. If you are using these flags, it may also be a good idea to warn the user when verification failure occur for this reason. The simplest is to not use the flags by default, and only fall back to using them after warning the user. If you wish to inspect the certificate chain yourself, you can use *note gnutls_certificate_get_peers:: to extract the raw server's certificate chain, *note gnutls_x509_crt_list_import:: to parse each of the certificates, and then *note gnutls_x509_crt_get_signature_algorithm:: to find out the signing algorithm used for each certificate. If any of the intermediary certificates are using 'GNUTLS_SIGN_RSA_MD2' or 'GNUTLS_SIGN_RSA_MD5', you could present a warning.  File: gnutls.info, Node: Shared-key and anonymous authentication, Next: More on certificate authentication, Prev: Certificate authentication, Up: Top 5 Shared-key and anonymous authentication ***************************************** In addition to certificate authentication, the TLS protocol may be used with password, shared-key and anonymous authentication methods. The rest of this chapter discusses details of these methods. * Menu: * SRP authentication:: * PSK authentication:: * Anonymous authentication::  File: gnutls.info, Node: SRP authentication, Next: PSK authentication, Up: Shared-key and anonymous authentication 5.1 SRP authentication ====================== * Menu: * Authentication using SRP:: * srptool Invocation:: Invoking srptool  File: gnutls.info, Node: Authentication using SRP, Next: srptool Invocation, Up: SRP authentication 5.1.1 Authentication using SRP ------------------------------ GnuTLS supports authentication via the Secure Remote Password or SRP protocol (see [_RFC2945,TOMSRP_] for a description). The SRP key exchange is an extension to the TLS protocol, and it provides an authenticated with a password key exchange. The peers can be identified using a single password, or there can be combinations where the client is authenticated using SRP and the server using a certificate. The advantage of SRP authentication, over other proposed secure password authentication schemes, is that SRP is not susceptible to off-line dictionary attacks. Moreover, SRP does not require the server to hold the user's password. This kind of protection is similar to the one used traditionally in the UNIX '/etc/passwd' file, where the contents of this file did not cause harm to the system security if they were revealed. The SRP needs instead of the plain password something called a verifier, which is calculated using the user's password, and if stolen cannot be used to impersonate the user. Typical conventions in SRP are a password file, called 'tpasswd' that holds the SRP verifiers (encoded passwords) and another file, 'tpasswd.conf', which holds the allowed SRP parameters. The included in GnuTLS helper follow those conventions. The srptool program, discussed in the next section is a tool to manipulate the SRP parameters. The implementation in GnuTLS is based on [_TLSSRP_]. The supported key exchange methods are shown below. 'SRP:' Authentication using the SRP protocol. 'SRP_DSS:' Client authentication using the SRP protocol. Server is authenticated using a certificate with DSA parameters. 'SRP_RSA:' Client authentication using the SRP protocol. Server is authenticated using a certificate with RSA parameters. -- Function: int gnutls_srp_verifier (const char * USERNAME, const char * PASSWORD, const gnutls_datum_t * SALT, const gnutls_datum_t * GENERATOR, const gnutls_datum_t * PRIME, gnutls_datum_t * RES) USERNAME: is the user's name PASSWORD: is the user's password SALT: should be some randomly generated bytes GENERATOR: is the generator of the group PRIME: is the group's prime RES: where the verifier will be stored. This function will create an SRP verifier, as specified in RFC2945. The 'prime' and 'generator' should be one of the static parameters defined in gnutls/gnutls.h or may be generated. The verifier will be allocated with 'gnutls_malloc' () and will be stored in 'res' using binary format. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, or an error code. 'INT *note gnutls_srp_base64_encode:: (const gnutls_datum_t * DATA, char * RESULT, size_t * RESULT_SIZE)' 'INT *note gnutls_srp_base64_decode:: (const gnutls_datum_t * B64_DATA, char * RESULT, size_t * RESULT_SIZE)'  File: gnutls.info, Node: srptool Invocation, Prev: Authentication using SRP, Up: SRP authentication 5.1.2 Invoking srptool ---------------------- Simple program that emulates the programs in the Stanford SRP (Secure Remote Password) libraries using GnuTLS. It is intended for use in places where you don't expect SRP authentication to be the used for system users. In brief, to use SRP you need to create two files. These are the password file that holds the users and the verifiers associated with them and the configuration file to hold the group parameters (called tpasswd.conf). This section was generated by *AutoGen*, using the 'agtexi-cmd' template and the option descriptions for the 'srptool' program. This software is released under the GNU General Public License, version 3 or later. srptool help/usage ('--help') ............................. This is the automatically generated usage text for srptool. The text printed is the same whether selected with the 'help' option ('--help') or the 'more-help' option ('--more-help'). 'more-help' will print the usage text by passing it through a pager program. 'more-help' is disabled on platforms without a working 'fork(2)' function. The 'PAGER' environment variable is used to select the program, defaulting to 'more'. Both will exit with a status code of 0. srptool - GnuTLS SRP tool - Ver. @VERSION@ USAGE: lt-srptool [ - [] | --[{=| }] ]... -d, --debug=num Enable debugging. - It must be in the range: 0 to 9999 -i, --index specify the index of the group parameters in tpasswd.conf to use. -u, --username=str specify a username -p, --passwd=str specify a password file. -s, --salt=num specify salt size. --verify just verify the password. -v, --passwd-conf=str specify a password conf file. --create-conf=str Generate a password configuration file. -v, --version[=arg] Output version information and exit -h, --help Display extended usage information and exit -!, --more-help Extended usage information passed thru pager Options are specified by doubled hyphens and their name or by a single hyphen and the flag character. Simple program that emulates the programs in the Stanford SRP (Secure Remote Password) libraries using GnuTLS. It is intended for use in places where you don't expect SRP authentication to be the used for system users. In brief, to use SRP you need to create two files. These are the password file that holds the users and the verifiers associated with them and the configuration file to hold the group parameters (called tpasswd.conf). please send bug reports to: bug-gnutls@gnu.org debug option (-d) ................. This is the "enable debugging." option. This option takes an argument number. Specifies the debug level. verify option ............. This is the "just verify the password." option. Verifies the password provided against the password file. passwd-conf option (-v) ....................... This is the "specify a password conf file." option. This option takes an argument string. Specify a filename or a PKCS #11 URL to read the CAs from. create-conf option .................. This is the "generate a password configuration file." option. This option takes an argument string. This generates a password configuration file (tpasswd.conf) containing the required for TLS parameters. srptool exit status ................... One of the following exit values will be returned: '0 (EXIT_SUCCESS)' Successful program execution. '1 (EXIT_FAILURE)' The operation failed or the command syntax was not valid. srptool See Also ................ gnutls-cli-debug (1), gnutls-serv (1), srptool (1), psktool (1), certtool (1) srptool Examples ................ To create 'tpasswd.conf' which holds the g and n values for SRP protocol (generator and a large prime), run: $ srptool --create-conf /etc/tpasswd.conf This command will create '/etc/tpasswd' and will add user 'test' (you will also be prompted for a password). Verifiers are stored by default in the way libsrp expects. $ srptool --passwd /etc/tpasswd --passwd-conf /etc/tpasswd.conf -u test This command will check against a password. If the password matches the one in '/etc/tpasswd' you will get an ok. $ srptool --passwd /etc/tpasswd --passwd\-conf /etc/tpasswd.conf --verify -u test  File: gnutls.info, Node: PSK authentication, Next: Anonymous authentication, Prev: SRP authentication, Up: Shared-key and anonymous authentication 5.2 PSK authentication ====================== * Menu: * Authentication using PSK:: * psktool Invocation:: Invoking psktool  File: gnutls.info, Node: Authentication using PSK, Next: psktool Invocation, Up: PSK authentication 5.2.1 Authentication using PSK ------------------------------ Authentication using Pre-shared keys is a method to authenticate using usernames and binary keys. This protocol avoids making use of public key infrastructure and expensive calculations, thus it is suitable for constraint clients. The implementation in GnuTLS is based on [_TLSPSK_]. The supported PSK key exchange methods are: 'PSK:' Authentication using the PSK protocol. 'DHE-PSK:' Authentication using the PSK protocol and Diffie-Hellman key exchange. This method offers perfect forward secrecy. 'ECDHE-PSK:' Authentication using the PSK protocol and Elliptic curve Diffie-Hellman key exchange. This method offers perfect forward secrecy. Helper functions to generate and maintain PSK keys are also included in GnuTLS. 'INT *note gnutls_key_generate:: (gnutls_datum_t * KEY, unsigned int KEY_SIZE)' 'INT *note gnutls_hex_encode:: (const gnutls_datum_t * DATA, char * RESULT, size_t * RESULT_SIZE)' 'INT *note gnutls_hex_decode:: (const gnutls_datum_t * HEX_DATA, void * RESULT, size_t * RESULT_SIZE)'  File: gnutls.info, Node: psktool Invocation, Prev: Authentication using PSK, Up: PSK authentication 5.2.2 Invoking psktool ---------------------- Program that generates random keys for use with TLS-PSK. The keys are stored in hexadecimal format in a key file. This section was generated by *AutoGen*, using the 'agtexi-cmd' template and the option descriptions for the 'psktool' program. This software is released under the GNU General Public License, version 3 or later. psktool help/usage ('--help') ............................. This is the automatically generated usage text for psktool. The text printed is the same whether selected with the 'help' option ('--help') or the 'more-help' option ('--more-help'). 'more-help' will print the usage text by passing it through a pager program. 'more-help' is disabled on platforms without a working 'fork(2)' function. The 'PAGER' environment variable is used to select the program, defaulting to 'more'. Both will exit with a status code of 0. psktool - GnuTLS PSK tool - Ver. @VERSION@ USAGE: lt-psktool [ - [] | --[{=| }] ]... -d, --debug=num Enable debugging. - It must be in the range: 0 to 9999 -s, --keysize=num specify the key size in bytes - It must be in the range: 0 to 512 -u, --username=str specify a username -p, --passwd=str specify a password file. -v, --version[=arg] Output version information and exit -h, --help Display extended usage information and exit -!, --more-help Extended usage information passed thru pager Options are specified by doubled hyphens and their name or by a single hyphen and the flag character. Program that generates random keys for use with TLS-PSK. The keys are stored in hexadecimal format in a key file. please send bug reports to: bug-gnutls@gnu.org debug option (-d) ................. This is the "enable debugging." option. This option takes an argument number. Specifies the debug level. psktool exit status ................... One of the following exit values will be returned: '0 (EXIT_SUCCESS)' Successful program execution. '1 (EXIT_FAILURE)' The operation failed or the command syntax was not valid. psktool See Also ................ gnutls-cli-debug (1), gnutls-serv (1), srptool (1), certtool (1) psktool Examples ................ To add a user 'psk_identity' in 'passwd.psk' for use with GnuTLS run: $ ./psktool -u psk_identity -p passwd.psk Generating a random key for user 'psk_identity' Key stored to passwd.psk $ cat psks.txt psk_identity:88f3824b3e5659f52d00e959bacab954b6540344 $ This command will create 'passwd.psk' if it does not exist and will add user 'psk_identity' (you will also be prompted for a password).  File: gnutls.info, Node: Anonymous authentication, Prev: PSK authentication, Up: Shared-key and anonymous authentication 5.3 Anonymous authentication ============================ The anonymous key exchange offers encryption without any indication of the peer's identity. This kind of authentication is vulnerable to a man in the middle attack, but can be used even if there is no prior communication or shared trusted parties with the peer. Moreover it is useful when complete anonymity is required. Unless in one of the above cases, do not use anonymous authentication. The available key exchange algorithms for anonymous authentication are shown below, but note that few public servers support them. They typically have to be explicitly enabled. 'ANON_DH:' This algorithm exchanges Diffie-Hellman parameters. 'ANON_ECDH:' This algorithm exchanges elliptic curve Diffie-Hellman parameters. It is more efficient than ANON_DH on equivalent security levels.  File: gnutls.info, Node: More on certificate authentication, Next: How to use GnuTLS in applications, Prev: Shared-key and anonymous authentication, Up: Top 6 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. * Menu: * PKCS 10 certificate requests:: * PKIX certificate revocation lists:: * OCSP certificate status checking:: * Managing encrypted keys:: * certtool Invocation:: Invoking certtool * ocsptool Invocation:: Invoking ocsptool * Smart cards and HSMs:: * Abstract key types::  File: gnutls.info, Node: PKCS 10 certificate requests, Next: PKIX certificate revocation lists, Up: More on certificate authentication 6.1 PKCS #10 certificate requests ================================= A certificate request is a structure, which contain information about an applicant of a certificate service. It usually contains a private 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. 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. 'INT *note gnutls_x509_crq_set_version:: (gnutls_x509_crq_t CRQ, unsigned int VERSION)' 'INT *note gnutls_x509_crq_set_dn_by_oid:: (gnutls_x509_crq_t CRQ, const char * OID, unsigned int RAW_FLAG, const void * DATA, unsigned int SIZEOF_DATA)' 'INT *note gnutls_x509_crq_set_key_usage:: (gnutls_x509_crq_t CRQ, unsigned int USAGE)' 'INT *note gnutls_x509_crq_set_key_purpose_oid:: (gnutls_x509_crq_t CRQ, const void * OID, unsigned int CRITICAL)' 'INT *note gnutls_x509_crq_set_basic_constraints:: (gnutls_x509_crq_t CRQ, unsigned int CA, int PATHLENCONSTRAINT)' The *note gnutls_x509_crq_set_key:: and *note 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 *note Abstract key types::. -- Function: int gnutls_x509_crq_set_key (gnutls_x509_crq_t CRQ, gnutls_x509_privkey_t KEY) CRQ: should contain a 'gnutls_x509_crq_t' structure KEY: holds a private key This function will set the public parameters from the given private key to the request. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. -- Function: int gnutls_x509_crq_sign2 (gnutls_x509_crq_t CRQ, gnutls_x509_privkey_t KEY, gnutls_digest_algorithm_t DIG, unsigned int FLAGS) CRQ: should contain a 'gnutls_x509_crq_t' structure KEY: holds a private key DIG: The message digest to use, i.e., 'GNUTLS_DIG_SHA1' FLAGS: must be 0 This function will sign the certificate request with a private key. This must be the same key as the one used in 'gnutls_x509_crt_set_key()' since a certificate request is self signed. This must be the last step in a certificate request generation since all the previously set parameters are now signed. *Returns:* 'GNUTLS_E_SUCCESS' on success, otherwise a negative error code. 'GNUTLS_E_ASN1_VALUE_NOT_FOUND' is returned if you didn't set all information in the certificate request (e.g., the version using 'gnutls_x509_crq_set_version()' ). 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. /* This example code is placed in the public domain. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include /* This example will generate a private key and a certificate * request. */ int main (void) { gnutls_x509_crq_t crq; gnutls_x509_privkey_t key; unsigned char buffer[10 * 1024]; size_t buffer_size = sizeof (buffer); unsigned int bits; gnutls_global_init (); /* Initialize an empty certificate request, and * an empty private key. */ gnutls_x509_crq_init (&crq); gnutls_x509_privkey_init (&key); /* Generate an RSA key of moderate security. */ bits = gnutls_sec_param_to_pk_bits (GNUTLS_PK_RSA, GNUTLS_SEC_PARAM_NORMAL); gnutls_x509_privkey_generate (key, GNUTLS_PK_RSA, bits, 0); /* Add stuff to the distinguished name */ gnutls_x509_crq_set_dn_by_oid (crq, GNUTLS_OID_X520_COUNTRY_NAME, 0, "GR", 2); gnutls_x509_crq_set_dn_by_oid (crq, GNUTLS_OID_X520_COMMON_NAME, 0, "Nikos", strlen ("Nikos")); /* Set the request version. */ gnutls_x509_crq_set_version (crq, 1); /* Set a challenge password. */ gnutls_x509_crq_set_challenge_password (crq, "something to remember here"); /* Associate the request with the private key */ gnutls_x509_crq_set_key (crq, key); /* Self sign the certificate request. */ gnutls_x509_crq_sign2 (crq, key, GNUTLS_DIG_SHA1, 0); /* Export the PEM encoded certificate request, and * display it. */ gnutls_x509_crq_export (crq, GNUTLS_X509_FMT_PEM, buffer, &buffer_size); printf ("Certificate Request: \n%s", buffer); /* Export the PEM encoded private key, and * display it. */ buffer_size = sizeof (buffer); gnutls_x509_privkey_export (key, GNUTLS_X509_FMT_PEM, buffer, &buffer_size); printf ("\n\nPrivate key: \n%s", buffer); gnutls_x509_crq_deinit (crq); gnutls_x509_privkey_deinit (key); return 0; }  File: gnutls.info, Node: PKIX certificate revocation lists, Next: OCSP certificate status checking, Prev: PKCS 10 certificate requests, Up: More on certificate authentication 6.2 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 *note Table 6.1: 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. 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. 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. revokedCertificatesList of revoked certificates serial numbers. extensions Optional CRL structure extensions. Table 6.1: Certificate revocation list fields. 'INT *note gnutls_x509_crl_set_version:: (gnutls_x509_crl_t CRL, unsigned int VERSION)' 'INT *note gnutls_x509_crl_set_crt_serial:: (gnutls_x509_crl_t CRL, const void * SERIAL, size_t SERIAL_SIZE, time_t REVOCATION_TIME)' 'INT *note gnutls_x509_crl_set_crt:: (gnutls_x509_crl_t CRL, gnutls_x509_crt_t CRT, time_t REVOCATION_TIME)' 'INT *note gnutls_x509_crl_set_next_update:: (gnutls_x509_crl_t CRL, time_t EXP_TIME)' 'INT *note gnutls_x509_crl_set_this_update:: (gnutls_x509_crl_t CRL, time_t ACT_TIME)' The *note gnutls_x509_crl_sign2:: and *note 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. -- Function: int gnutls_x509_crl_sign2 (gnutls_x509_crl_t CRL, gnutls_x509_crt_t ISSUER, gnutls_x509_privkey_t ISSUER_KEY, gnutls_digest_algorithm_t DIG, unsigned int FLAGS) CRL: should contain a gnutls_x509_crl_t structure ISSUER: is the certificate of the certificate issuer ISSUER_KEY: holds the issuer's private key DIG: The message digest to use. GNUTLS_DIG_SHA1 is the safe choice unless you know what you're doing. FLAGS: must be 0 This function will sign the CRL with the issuer's private key, and will copy the issuer's information into the CRL. This must be the last step in a certificate CRL since all the previously set parameters are now signed. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. -- Function: int gnutls_x509_crl_privkey_sign (gnutls_x509_crl_t CRL, gnutls_x509_crt_t ISSUER, gnutls_privkey_t ISSUER_KEY, gnutls_digest_algorithm_t DIG, unsigned int FLAGS) CRL: should contain a gnutls_x509_crl_t structure ISSUER: is the certificate of the certificate issuer ISSUER_KEY: holds the issuer's private key DIG: The message digest to use. GNUTLS_DIG_SHA1 is the safe choice unless you know what you're doing. FLAGS: must be 0 This function will sign the CRL with the issuer's private key, and will copy the issuer's information into the CRL. This must be the last step in a certificate CRL since all the previously set parameters are now signed. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. Since 2.12.0 Few extensions on the CRL structure are supported, including the CRL number extension and the authority key identifier. 'INT *note gnutls_x509_crl_set_number:: (gnutls_x509_crl_t CRL, const void * NR, size_t NR_SIZE)' 'INT *note gnutls_x509_crl_set_authority_key_id:: (gnutls_x509_crl_t CRL, const void * ID, size_t ID_SIZE)'  File: gnutls.info, Node: OCSP certificate status checking, Next: Managing encrypted keys, Prev: PKIX certificate revocation lists, Up: More on certificate authentication 6.3 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 to perform 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. 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. The latter is due to an extension field called the Authority Information Access (AIA) which may hold the location of the OCSP responder in the access method called 'id-ad-ocsp'. The following function extracts this information from a certificate. 'INT *note gnutls_x509_crt_get_authority_info_access:: (gnutls_x509_crt_t CRT, unsigned int SEQ, int WHAT, gnutls_datum_t * DATA, unsigned int * CRITICAL)' There are several functions in GnuTLS for creating and manipulating OCSP requests and responses. The general idea is that a client application create an OCSP request object, store some information about the certificate to check in the request, and then export 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. 'INT *note gnutls_ocsp_req_init:: (gnutls_ocsp_req_t * REQ)' 'VOID *note gnutls_ocsp_req_deinit:: (gnutls_ocsp_req_t REQ)' 'INT *note gnutls_ocsp_req_import:: (gnutls_ocsp_req_t REQ, const gnutls_datum_t * DATA)' 'INT *note gnutls_ocsp_req_export:: (gnutls_ocsp_req_t REQ, gnutls_datum_t * DATA)' 'INT *note gnutls_ocsp_req_print:: (gnutls_ocsp_req_t REQ, gnutls_ocsp_print_formats_t FORMAT, gnutls_datum_t * OUT)' There are two interfaces for setting the identity of a certificate in a OCSP request, the first being a low-level function when you have the issuer name hash, issuer key hash, and certificate serial number in binary form. The second is usually 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 an OCSP request. 'INT *note gnutls_ocsp_req_add_cert_id:: (gnutls_ocsp_req_t REQ, gnutls_digest_algorithm_t DIGEST, const gnutls_datum_t * ISSUER_NAME_HASH, const gnutls_datum_t * ISSUER_KEY_HASH, const gnutls_datum_t * SERIAL_NUMBER)' 'INT *note gnutls_ocsp_req_add_cert:: (gnutls_ocsp_req_t REQ, gnutls_digest_algorithm_t DIGEST, gnutls_x509_crt_t ISSUER, gnutls_x509_crt_t CERT)' 'INT *note gnutls_ocsp_req_get_cert_id:: (gnutls_ocsp_req_t REQ, unsigned INDX, gnutls_digest_algorithm_t * DIGEST, gnutls_datum_t * ISSUER_NAME_HASH, gnutls_datum_t * ISSUER_KEY_HASH, gnutls_datum_t * SERIAL_NUMBER)' 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. 'INT *note gnutls_ocsp_req_get_extension:: (gnutls_ocsp_req_t REQ, unsigned INDX, gnutls_datum_t * OID, unsigned int * CRITICAL, gnutls_datum_t * DATA)' 'INT *note gnutls_ocsp_req_set_extension:: (gnutls_ocsp_req_t REQ, const char * OID, unsigned int CRITICAL, const gnutls_datum_t * DATA)' 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. 'INT *note gnutls_ocsp_req_get_nonce:: (gnutls_ocsp_req_t REQ, unsigned int * CRITICAL, gnutls_datum_t * NONCE)' 'INT *note gnutls_ocsp_req_set_nonce:: (gnutls_ocsp_req_t REQ, unsigned int CRITICAL, const gnutls_datum_t * NONCE)' 'INT *note gnutls_ocsp_req_randomize_nonce:: (gnutls_ocsp_req_t REQ)' The OCSP response structures is a bit more complex than the request. The important ASN.1 structure is as follows. In practice, all OCSP responses contain a Basic OCSP response sub-structure. OCSPResponse ::= SEQUENCE { responseStatus OCSPResponseStatus, responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } OCSPResponseStatus ::= ENUMERATED { successful (0), --Response has valid confirmations malformedRequest (1), --Illegal confirmation request internalError (2), --Internal error in issuer tryLater (3), --Try again later --(4) is not used sigRequired (5), --Must sign the request unauthorized (6) --Request unauthorized } ResponseBytes ::= SEQUENCE { responseType OBJECT IDENTIFIER, response OCTET STRING } id-pkix-ocsp-basic OBJECT IDENTIFIER ::= { id-pkix-ocsp 1 } BasicOCSPResponse ::= SEQUENCE { tbsResponseData ResponseData, signatureAlgorithm AlgorithmIdentifier, signature BIT STRING, certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } ResponseData ::= SEQUENCE { version [0] EXPLICIT Version DEFAULT v1, responderID ResponderID, producedAt GeneralizedTime, responses SEQUENCE OF SingleResponse, responseExtensions [1] EXPLICIT Extensions OPTIONAL } ResponderID ::= CHOICE { byName [1] Name, byKey [2] KeyHash } KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key (excluding the tag and length fields) SingleResponse ::= SEQUENCE { certID CertID, certStatus CertStatus, thisUpdate GeneralizedTime, nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, singleExtensions [1] EXPLICIT Extensions OPTIONAL } CertStatus ::= CHOICE { good [0] IMPLICIT NULL, revoked [1] IMPLICIT RevokedInfo, unknown [2] IMPLICIT UnknownInfo } RevokedInfo ::= SEQUENCE { revocationTime GeneralizedTime, revocationReason [0] EXPLICIT CRLReason OPTIONAL } We provide basic functions for initialization, importing, exporting and deallocating OCSP responses. The Basic OCSP Response structure is automatically parsed when an OCSP Response is imported. 'INT *note gnutls_ocsp_resp_init:: (gnutls_ocsp_resp_t * RESP)' 'VOID *note gnutls_ocsp_resp_deinit:: (gnutls_ocsp_resp_t RESP)' 'INT *note gnutls_ocsp_resp_import:: (gnutls_ocsp_resp_t RESP, const gnutls_datum_t * DATA)' 'INT *note gnutls_ocsp_resp_export:: (gnutls_ocsp_resp_t RESP, gnutls_datum_t * DATA)' 'INT *note gnutls_ocsp_resp_print:: (gnutls_ocsp_resp_t RESP, gnutls_ocsp_print_formats_t FORMAT, gnutls_datum_t * OUT)' The OCSP response needs to be verified against some set of trust anchors before it can be relied upon. 'INT *note gnutls_ocsp_resp_verify:: (gnutls_ocsp_resp_t RESP, gnutls_x509_trust_list_t TRUSTLIST, unsigned int * VERIFY, unsigned int FLAGS)' 'INT *note gnutls_ocsp_resp_verify_direct:: (gnutls_ocsp_resp_t RESP, gnutls_x509_crt_t ISSUER, unsigned int * VERIFY, unsigned int FLAGS)'  File: gnutls.info, Node: Managing encrypted keys, Next: certtool Invocation, Prev: OCSP certificate status checking, Up: More on certificate authentication 6.4 Managing encrypted keys =========================== Transferring or storing private keys in plain might not be a good idea. Any access on the keys becomes a fatal compromise. Storing the keys in hardware security modules (see *note Smart cards and HSMs::) could solve the storage problem but it is not always practical or efficient enough. This section describes alternative ways that involve encryption of the private keys to store and transfer. There are two alternatives to use for key encryption, PKCS #8 and #12 methods of private key encryption. The PKCS #8 method only allows encryption of the private key, whilst the PKCS #12 method allows in addition the bundling of other data into the structure. That could be bundling together the certificate as well as the trusted CA certificate. 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. 'INT *note gnutls_x509_privkey_import_pkcs8:: (gnutls_x509_privkey_t KEY, const gnutls_datum_t * DATA, gnutls_x509_crt_fmt_t FORMAT, const char * PASSWORD, unsigned int FLAGS)' 'INT *note gnutls_x509_privkey_export_pkcs8:: (gnutls_x509_privkey_t KEY, gnutls_x509_crt_fmt_t FORMAT, const char * PASSWORD, unsigned int FLAGS, void * OUTPUT_DATA, size_t * OUTPUT_DATA_SIZE)' 'GNUTLS_PKCS_PLAIN' Unencrypted private key. 'GNUTLS_PKCS8_PLAIN' Same as 'GNUTLS_PKCS_PLAIN' . 'GNUTLS_PKCS_USE_PKCS12_3DES' PKCS-12 3DES. 'GNUTLS_PKCS8_USE_PKCS12_3DES' Same as 'GNUTLS_PKCS_USE_PKCS12_3DES' . 'GNUTLS_PKCS_USE_PKCS12_ARCFOUR' PKCS-12 ARCFOUR. 'GNUTLS_PKCS8_USE_PKCS12_ARCFOUR' Same as 'GNUTLS_PKCS_USE_PKCS12_ARCFOUR' . 'GNUTLS_PKCS_USE_PKCS12_RC2_40' PKCS-12 RC2-40. 'GNUTLS_PKCS8_USE_PKCS12_RC2_40' Same as 'GNUTLS_PKCS_USE_PKCS12_RC2_40' . 'GNUTLS_PKCS_USE_PBES2_3DES' PBES2 3DES. 'GNUTLS_PKCS_USE_PBES2_AES_128' PBES2 AES-128. 'GNUTLS_PKCS_USE_PBES2_AES_192' PBES2 AES-192. 'GNUTLS_PKCS_USE_PBES2_AES_256' PBES2 AES-256. Figure 6.1: 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. 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. 'INT *note gnutls_pkcs12_get_bag:: (gnutls_pkcs12_t PKCS12, int INDX, gnutls_pkcs12_bag_t BAG)' 'INT *note gnutls_pkcs12_verify_mac:: (gnutls_pkcs12_t PKCS12, const char * PASS)' 'INT *note gnutls_pkcs12_bag_decrypt:: (gnutls_pkcs12_bag_t BAG, const char * PASS)' 'INT *note gnutls_pkcs12_bag_get_count:: (gnutls_pkcs12_bag_t BAG)' 'INT *note gnutls_pkcs12_bag_get_data:: (gnutls_pkcs12_bag_t BAG, int INDX, gnutls_datum_t * DATA)' 'INT *note gnutls_pkcs12_bag_get_key_id:: (gnutls_pkcs12_bag_t BAG, int INDX, gnutls_datum_t * ID)' 'INT *note gnutls_pkcs12_bag_get_friendly_name:: (gnutls_pkcs12_bag_t BAG, int INDX, char ** NAME)' The functions below are used to generate a PKCS #12 structure. An example of their usage is also shown. 'INT *note gnutls_pkcs12_set_bag:: (gnutls_pkcs12_t PKCS12, gnutls_pkcs12_bag_t BAG)' 'INT *note gnutls_pkcs12_bag_encrypt:: (gnutls_pkcs12_bag_t BAG, const char * PASS, unsigned int FLAGS)' 'INT *note gnutls_pkcs12_generate_mac:: (gnutls_pkcs12_t PKCS12, const char * PASS)' 'INT *note gnutls_pkcs12_bag_set_data:: (gnutls_pkcs12_bag_t BAG, gnutls_pkcs12_bag_type_t TYPE, const gnutls_datum_t * DATA)' 'INT *note gnutls_pkcs12_bag_set_crl:: (gnutls_pkcs12_bag_t BAG, gnutls_x509_crl_t CRL)' 'INT *note gnutls_pkcs12_bag_set_crt:: (gnutls_pkcs12_bag_t BAG, gnutls_x509_crt_t CRT)' 'INT *note gnutls_pkcs12_bag_set_key_id:: (gnutls_pkcs12_bag_t BAG, int INDX, const gnutls_datum_t * ID)' 'INT *note gnutls_pkcs12_bag_set_friendly_name:: (gnutls_pkcs12_bag_t BAG, int INDX, const char * NAME)' /* This example code is placed in the public domain. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "examples.h" #define OUTFILE "out.p12" /* This function will write a pkcs12 structure into a file. * cert: is a DER encoded certificate * pkcs8_key: is a PKCS #8 encrypted key (note that this must be * encrypted using a PKCS #12 cipher, or some browsers will crash) * password: is the password used to encrypt the PKCS #12 packet. */ int write_pkcs12 (const gnutls_datum_t * cert, const gnutls_datum_t * pkcs8_key, const char *password) { gnutls_pkcs12_t pkcs12; int ret, bag_index; gnutls_pkcs12_bag_t bag, key_bag; char pkcs12_struct[10 * 1024]; size_t pkcs12_struct_size; FILE *fd; /* A good idea might be to use gnutls_x509_privkey_get_key_id() * to obtain a unique ID. */ gnutls_datum_t key_id = { (void *) "\x00\x00\x07", 3 }; gnutls_global_init (); /* Firstly we create two helper bags, which hold the certificate, * and the (encrypted) key. */ gnutls_pkcs12_bag_init (&bag); gnutls_pkcs12_bag_init (&key_bag); ret = gnutls_pkcs12_bag_set_data (bag, GNUTLS_BAG_CERTIFICATE, cert); if (ret < 0) { fprintf (stderr, "ret: %s\n", gnutls_strerror (ret)); return 1; } /* ret now holds the bag's index. */ bag_index = ret; /* Associate a friendly name with the given certificate. Used * by browsers. */ gnutls_pkcs12_bag_set_friendly_name (bag, bag_index, "My name"); /* Associate the certificate with the key using a unique key * ID. */ gnutls_pkcs12_bag_set_key_id (bag, bag_index, &key_id); /* use weak encryption for the certificate. */ gnutls_pkcs12_bag_encrypt (bag, password, GNUTLS_PKCS_USE_PKCS12_RC2_40); /* Now the key. */ ret = gnutls_pkcs12_bag_set_data (key_bag, GNUTLS_BAG_PKCS8_ENCRYPTED_KEY, pkcs8_key); if (ret < 0) { fprintf (stderr, "ret: %s\n", gnutls_strerror (ret)); return 1; } /* Note that since the PKCS #8 key is already encrypted we don't * bother encrypting that bag. */ bag_index = ret; gnutls_pkcs12_bag_set_friendly_name (key_bag, bag_index, "My name"); gnutls_pkcs12_bag_set_key_id (key_bag, bag_index, &key_id); /* The bags were filled. Now create the PKCS #12 structure. */ gnutls_pkcs12_init (&pkcs12); /* Insert the two bags in the PKCS #12 structure. */ gnutls_pkcs12_set_bag (pkcs12, bag); gnutls_pkcs12_set_bag (pkcs12, key_bag); /* Generate a message authentication code for the PKCS #12 * structure. */ gnutls_pkcs12_generate_mac (pkcs12, password); pkcs12_struct_size = sizeof (pkcs12_struct); ret = gnutls_pkcs12_export (pkcs12, GNUTLS_X509_FMT_DER, pkcs12_struct, &pkcs12_struct_size); if (ret < 0) { fprintf (stderr, "ret: %s\n", gnutls_strerror (ret)); return 1; } fd = fopen (OUTFILE, "w"); if (fd == NULL) { fprintf (stderr, "cannot open file\n"); return 1; } fwrite (pkcs12_struct, 1, pkcs12_struct_size, fd); fclose (fd); gnutls_pkcs12_bag_deinit (bag); gnutls_pkcs12_bag_deinit (key_bag); gnutls_pkcs12_deinit (pkcs12); return 0; }  File: gnutls.info, Node: certtool Invocation, Next: ocsptool Invocation, Prev: Managing encrypted keys, Up: More on certificate authentication 6.5 Invoking certtool ===================== Tool to parse and generate X.509 certificates, requests and private keys. It can be used interactively or non interactively by specifying the template command line option. This section was generated by *AutoGen*, using the 'agtexi-cmd' template and the option descriptions for the 'certtool' program. This software is released under the GNU General Public License, version 3 or later. certtool help/usage ('--help') ------------------------------ This is the automatically generated usage text for certtool. The text printed is the same whether selected with the 'help' option ('--help') or the 'more-help' option ('--more-help'). 'more-help' will print the usage text by passing it through a pager program. 'more-help' is disabled on platforms without a working 'fork(2)' function. The 'PAGER' environment variable is used to select the program, defaulting to 'more'. Both will exit with a status code of 0. certtool - GnuTLS PKCS #11 tool - Ver. @VERSION@ USAGE: lt-certtool [ - [] | --[{=| }] ]... -d, --debug=num Enable debugging. - It must be in the range: 0 to 9999 --infile=file Input file - file must pre-exist --outfile=str Output file -s, --generate-self-signed Generate a self-signed certificate -c, --generate-certificate Generate a signed certificate --generate-proxy Generates a proxy certificate --generate-crl Generate a CRL -u, --update-certificate Update a signed certificate -p, --generate-privkey Generate a private key -q, --generate-request Generate a PKCS #10 certificate request -e, --verify-chain Verify a PEM encoded certificate chain. --verify Verify a PEM encoded certificate chain using a trusted list. - requires these options: load-ca-certificate --verify-crl Verify a CRL using a trusted list. - requires these options: load-ca-certificate --generate-dh-params Generate PKCS #3 encoded Diffie-Hellman parameters. --get-dh-params Get the included PKCS #3 encoded Diffie-Hellman parameters. --dh-info Print information PKCS #3 encoded Diffie-Hellman parameters --load-privkey=str Loads a private key file --load-pubkey=str Loads a public key file --load-request=file Loads a certificate request file - file must pre-exist --load-certificate=str Loads a certificate file --load-ca-privkey=str Loads the certificate authority's private key file --load-ca-certificate=str Loads the certificate authority's certificate file --password=str Password to use -i, --certificate-info Print information on the given certificate --certificate-pubkey Print certificate's public key --pgp-certificate-info Print information on the given OpenPGP certificate --pgp-ring-info Print information on the given OpenPGP keyring structure -l, --crl-info Print information on the given CRL structure --crq-info Print information on the given certificate request --no-crq-extensions Do not use extensions in certificate requests --p12-info Print information on a PKCS #12 structure --p7-info Print information on a PKCS #7 structure --smime-to-p7 Convert S/MIME to PKCS #7 structure -k, --key-info Print information on a private key --pgp-key-info Print information on an OpenPGP private key --pubkey-info Print information on a public key --v1 Generate an X.509 version 1 certificate (with no extensions) --to-p12 Generate a PKCS #12 structure - requires these options: load-certificate --to-p8 Generate a PKCS #8 structure -8, --pkcs8 Use PKCS #8 format for private keys --rsa Generate RSA key --dsa Generate DSA key --ecc Generate ECC (ECDSA) key --hash=str Hash algorithm to use for signing. --inder Use DER format for input certificates and private keys. - disabled as --no-inder --inraw This is an alias for 'inder' --outder Use DER format for output certificates and private keys - disabled as --no-outder --outraw This is an alias for 'outder' --bits=num Specify the number of bits for key generate --sec-param=str Specify the security level [low, legacy, normal, high, ultra]. --disable-quick-random No effect --template=file Template file to use for non-interactive operation - file must pre-exist --pkcs-cipher=str Cipher to use for PKCS #8 and #12 operations -v, --version[=arg] Output version information and exit -h, --help Display extended usage information and exit -!, --more-help Extended usage information passed thru pager Options are specified by doubled hyphens and their name or by a single hyphen and the flag character. Tool to parse and generate X.509 certificates, requests and private keys. It can be used interactively or non interactively by specifying the template command line option. please send bug reports to: bug-gnutls@gnu.org debug option (-d) ----------------- This is the "enable debugging." option. This option takes an argument number. Specifies the debug level. verify-chain option (-e) ------------------------ This is the "verify a pem encoded certificate chain." option. The last certificate in the chain must be a self signed one. verify option ------------- This is the "verify a pem encoded certificate chain using a trusted list." option. This option has some usage constraints. It: * must appear in combination with the following options: load-ca-certificate. The trusted certificate list must be loaded with -load-ca-certificate. verify-crl option ----------------- This is the "verify a crl using a trusted list." option. This option has some usage constraints. It: * must appear in combination with the following options: load-ca-certificate. The trusted certificate list must be loaded with -load-ca-certificate. get-dh-params option -------------------- This is the "get the included pkcs #3 encoded diffie-hellman parameters." option. Returns stored DH parameters in GnuTLS. Those parameters are used in the SRP protocol. The parameters returned by fresh generation are more efficient since GnuTLS 3.0.9. load-privkey option ------------------- This is the "loads a private key file" option. This option takes an argument string. This can be either a file or a PKCS #11 URL load-pubkey option ------------------ This is the "loads a public key file" option. This option takes an argument string. This can be either a file or a PKCS #11 URL load-certificate option ----------------------- This is the "loads a certificate file" option. This option takes an argument string. This can be either a file or a PKCS #11 URL load-ca-privkey option ---------------------- This is the "loads the certificate authority's private key file" option. This option takes an argument string. This can be either a file or a PKCS #11 URL load-ca-certificate option -------------------------- This is the "loads the certificate authority's certificate file" option. This option takes an argument string. This can be either a file or a PKCS #11 URL to-p12 option ------------- This is the "generate a pkcs #12 structure" option. This option has some usage constraints. It: * must appear in combination with the following options: load-certificate. It requires a certificate, a private key and possibly a CA certificate to be specified. hash option ----------- This is the "hash algorithm to use for signing." option. This option takes an argument string. Available hash functions are SHA1, RMD160, SHA256, SHA384, SHA512. inder option ------------ This is the "use der format for input certificates and private keys." option. The input files will be assumed to be in DER or RAW format. Unlike options that in PEM input would allow multiple input data (e.g. multiple certificates), when reading in DER format a single data structure is read. inraw option ------------ This is an alias for the 'inder' option, *note the inder option documentation: certtool inder. outder option ------------- This is the "use der format for output certificates and private keys" option. The output will be in DER or RAW format. outraw option ------------- This is an alias for the 'outder' option, *note the outder option documentation: certtool outder. sec-param option ---------------- This is the "specify the security level [low, legacy, normal, high, ultra]." option. This option takes an argument string 'Security parameter'. This is alternative to the bits option. pkcs-cipher option ------------------ This is the "cipher to use for pkcs #8 and #12 operations" option. This option takes an argument string 'Cipher'. Cipher may be one of 3des, 3des-pkcs12, aes-128, aes-192, aes-256, rc2-40, arcfour. certtool exit status -------------------- One of the following exit values will be returned: '0 (EXIT_SUCCESS)' Successful program execution. '1 (EXIT_FAILURE)' The operation failed or the command syntax was not valid. certtool See Also ----------------- p11tool (1) certtool Examples ----------------- Generating private keys ----------------------- To create an RSA private key, run: $ certtool --generate-privkey --outfile key.pem --rsa To create a DSA or elliptic curves (ECDSA) private key use the above command combined with 'dsa' or 'ecc' options. Generating certificate requests ------------------------------- To create a certificate request (needed when the certificate is issued by another party), run: certtool --generate-request --load-privkey key.pem \ --outfile request.pem If the private key is stored in a smart card you can generate a request by specifying the private key object URL. $ ./certtool --generate-request --load-privkey "pkcs11:..." \ --load-pubkey "pkcs11:..." --outfile request.pem Generating a self-signed certificate ------------------------------------ To create a self signed certificate, use the command: $ certtool --generate-privkey --outfile ca-key.pem $ certtool --generate-self-signed --load-privkey ca-key.pem \ --outfile ca-cert.pem Note that a self-signed certificate usually belongs to a certificate authority, that signs other certificates. Generating a certificate ------------------------ To generate a certificate using the previous request, use the command: $ certtool --generate-certificate --load-request request.pem \ --outfile cert.pem --load-ca-certificate ca-cert.pem \ --load-ca-privkey ca-key.pem To generate a certificate using the private key only, use the command: $ certtool --generate-certificate --load-privkey key.pem \ --outfile cert.pem --load-ca-certificate ca-cert.pem \ --load-ca-privkey ca-key.pem Certificate information ----------------------- To view the certificate information, use: $ certtool --certificate-info --infile cert.pem PKCS #12 structure generation ----------------------------- To generate a PKCS #12 structure using the previous key and certificate, use the command: $ certtool --load-certificate cert.pem --load-privkey key.pem \ --to-p12 --outder --outfile key.p12 Some tools (reportedly web browsers) have problems with that file because it does not contain the CA certificate for the certificate. To work around that problem in the tool, you can use the -load-ca-certificate parameter as follows: $ certtool --load-ca-certificate ca.pem \ --load-certificate cert.pem --load-privkey key.pem \ --to-p12 --outder --outfile key.p12 Diffie-Hellman parameter generation ----------------------------------- To generate parameters for Diffie-Hellman key exchange, use the command: $ certtool --generate-dh-params --outfile dh.pem --sec-param normal Proxy certificate generation ---------------------------- Proxy certificate can be used to delegate your credential to a temporary, typically short-lived, certificate. To create one from the previously created certificate, first create a temporary key and then generate a proxy certificate for it, using the commands: $ certtool --generate-privkey > proxy-key.pem $ certtool --generate-proxy --load-ca-privkey key.pem \ --load-privkey proxy-key.pem --load-certificate cert.pem \ --outfile proxy-cert.pem Certificate revocation list generation -------------------------------------- To create an empty Certificate Revocation List (CRL) do: $ certtool --generate-crl --load-ca-privkey x509-ca-key.pem \ --load-ca-certificate x509-ca.pem To create a CRL that contains some revoked certificates, place the certificates in a file and use '--load-certificate' as follows: $ certtool --generate-crl --load-ca-privkey x509-ca-key.pem \ --load-ca-certificate x509-ca.pem --load-certificate revoked-certs.pem To verify a Certificate Revocation List (CRL) do: $ certtool --verify-crl --load-ca-certificate x509-ca.pem < crl.pem certtool Files -------------- Certtool's template file format ------------------------------- A template file can be used to avoid the interactive questions of certtool. Initially create a file named 'cert.cfg' that contains the information about the certificate. The template can be used as below: $ certtool --generate-certificate cert.pem --load-privkey key.pem \ --template cert.cfg \ --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem An example certtool template file that can be used to generate a certificate request or a self signed certificate follows. # X.509 Certificate options # # DN options # The organization of the subject. organization = "Koko inc." # The organizational unit of the subject. unit = "sleeping dept." # The locality of the subject. # locality = # The state of the certificate owner. state = "Attiki" # The country of the subject. Two letter code. country = GR # The common name of the certificate owner. cn = "Cindy Lauper" # A user id of the certificate owner. #uid = "clauper" # Set domain components #dc = "name" #dc = "domain" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = 2.5.4.12 Dr. #dn_oid = 2.5.4.65 jackal # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # The serial number of the certificate serial = 007 # In how many days, counting from today, this certificate will expire. expiration_days = 700 # X.509 v3 extensions # A dnsname in case of a WWW server. #dns_name = "www.none.org" #dns_name = "www.morethanone.org" # A subject alternative name URI #uri = "http://www.example.com" # An IP address in case of a server. #ip_address = "192.168.1.1" # An email in case of a person email = "none@none.org" # Challenge password used in certificate requests challenge_passwd = 123456 # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. #crl_dist_points = "http://www.getcrl.crl/getcrl/" # Whether this is a CA certificate or not #ca # for microsoft smart card logon # key_purpose_oid = 1.3.6.1.4.1.311.20.2.2 ### Other predefined key purpose OIDs # Whether this certificate will be used for a TLS client #tls_www_client # Whether this certificate will be used for a TLS server #tls_www_server # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is preferred to use different # keys for encryption and signing. #encryption_key # Whether this key will be used to sign other certificates. #cert_signing_key # Whether this key will be used to sign CRLs. #crl_signing_key # Whether this key will be used to sign code. #code_signing_key # Whether this key will be used to sign OCSP data. #ocsp_signing_key # Whether this key will be used for time stamping. #time_stamping_key # Whether this key will be used for IPsec IKE operations. #ipsec_ike_key ### end of key purpose OIDs # When generating a certificate from a certificate # request, then honor the extensions stored in the request # and store them in the real certificate. #honor_crq_extensions # Path length contraint. Sets the maximum number of # certificates that can be used to certify this certificate. # (i.e. the certificate chain length) #path_len = -1 #path_len = 2 # OCSP URI # ocsp_uri = http://my.ocsp.server/ocsp # CA issuers URI # ca_issuers_uri = http://my.ca.issuer # Options for proxy certificates # proxy_policy_language = 1.3.6.1.5.5.7.21.1 # Options for generating a CRL # next CRL update will be in 43 days (wow) #crl_next_update = 43 # this is the 5th CRL by this CA #crl_number = 5  File: gnutls.info, Node: ocsptool Invocation, Next: Smart cards and HSMs, Prev: certtool Invocation, Up: More on certificate authentication 6.6 Invoking ocsptool ===================== Ocsptool is a program that can parse and print information about OCSP requests/responses, generate requests and verify responses. This section was generated by *AutoGen*, using the 'agtexi-cmd' template and the option descriptions for the 'ocsptool' program. This software is released under the GNU General Public License, version 3 or later. ocsptool help/usage ('--help') ------------------------------ This is the automatically generated usage text for ocsptool. The text printed is the same whether selected with the 'help' option ('--help') or the 'more-help' option ('--more-help'). 'more-help' will print the usage text by passing it through a pager program. 'more-help' is disabled on platforms without a working 'fork(2)' function. The 'PAGER' environment variable is used to select the program, defaulting to 'more'. Both will exit with a status code of 0. ocsptool - GnuTLS OCSP tool - Ver. @VERSION@ USAGE: lt-ocsptool [ - [] | --[{=| }] ]... -d, --debug=num Enable debugging. - It must be in the range: 0 to 9999 -V, --verbose More verbose output - may appear multiple times --infile=file Input file - file must pre-exist --outfile=str Output file --ask[=arg] Ask an OCSP/HTTP server on a certificate validity - requires these options: load-cert load-issuer -e, --verify-response Verify response -i, --request-info Print information on a OCSP request -j, --response-info Print information on a OCSP response -q, --generate-request Generate an OCSP request --nonce Don't add nonce to OCSP request - disabled as --no-nonce --load-issuer=file Read issuer certificate from file - file must pre-exist --load-cert=file Read certificate to check from file - file must pre-exist --load-trust=file Read OCSP trust anchors from file - prohibits these options: load-signer - file must pre-exist --load-signer=file Read OCSP response signer from file - prohibits these options: load-trust - file must pre-exist --inder Use DER format for input certificates and private keys - disabled as --no-inder -Q, --load-request=file Read DER encoded OCSP request from file - file must pre-exist -S, --load-response=file Read DER encoded OCSP response from file - file must pre-exist -v, --version[=arg] Output version information and exit -h, --help Display extended usage information and exit -!, --more-help Extended usage information passed thru pager Options are specified by doubled hyphens and their name or by a single hyphen and the flag character. Ocsptool is a program that can parse and print information about OCSP requests/responses, generate requests and verify responses. please send bug reports to: bug-gnutls@gnu.org debug option (-d) ----------------- This is the "enable debugging." option. This option takes an argument number. Specifies the debug level. ask option ---------- This is the "ask an ocsp/http server on a certificate validity" option. This option takes an optional argument string 'server name|url'. This option has some usage constraints. It: * must appear in combination with the following options: load-cert, load-issuer. Connects to the specified HTTP OCSP server and queries on the validity of the loaded certificate. ocsptool exit status -------------------- One of the following exit values will be returned: '0 (EXIT_SUCCESS)' Successful program execution. '1 (EXIT_FAILURE)' The operation failed or the command syntax was not valid. ocsptool See Also ----------------- certtool (1) ocsptool Examples ----------------- Print information about an OCSP request --------------------------------------- To parse an OCSP request and print information about the content, the '-i' or '--request-info' parameter may be used as follows. The '-Q' parameter specify the name of the file containing the OCSP request, and it should contain the OCSP request in binary DER format. $ ocsptool -i -Q ocsp-request.der The input file may also be sent to standard input like this: $ cat ocsp-request.der | ocsptool --request-info Print information about an OCSP response ---------------------------------------- Similar to parsing OCSP requests, OCSP responses can be parsed using the '-j' or '--response-info' as follows. $ ocsptool -j -Q ocsp-response.der $ cat ocsp-response.der | ocsptool --response-info Generate an OCSP request ------------------------ The '-q' or '--generate-request' parameters are used to generate an OCSP request. By default the OCSP request is written to standard output in binary DER format, but can be stored in a file using '--outfile'. To generate an OCSP request the issuer of the certificate to check needs to be specified with '--load-issuer' and the certificate to check with '--load-cert'. By default PEM format is used for these files, although '--inder' can be used to specify that the input files are in DER format. $ ocsptool -q --load-issuer issuer.pem --load-cert client.pem \ --outfile ocsp-request.der When generating OCSP requests, the tool will add an OCSP extension containing a nonce. This behaviour can be disabled by specifying '--no-nonce'. Verify signature in OCSP response --------------------------------- To verify the signature in an OCSP response the '-e' or '--verify-response' parameter is used. The tool will read an OCSP response in DER format from standard input, or from the file specified by '--load-response'. The OCSP response is verified against a set of trust anchors, which are specified using '--load-trust'. The trust anchors are concatenated certificates in PEM format. The certificate that signed the OCSP response needs to be in the set of trust anchors, or the issuer of the signer certificate needs to be in the set of trust anchors and the OCSP Extended Key Usage bit has to be asserted in the signer certificate. $ ocsptool -e --load-trust issuer.pem \ --load-response ocsp-response.der The tool will print status of verification. Verify signature in OCSP response against given certificate ----------------------------------------------------------- It is possible to override the normal trust logic if you know that a certain certificate is supposed to have signed the OCSP response, and you want to use it to check the signature. This is achieved using '--load-signer' instead of '--load-trust'. This will load one certificate and it will be used to verify the signature in the OCSP response. It will not check the Extended Key Usage bit. $ ocsptool -e --load-signer ocsp-signer.pem \ --load-response ocsp-response.der This approach is normally only relevant in two situations. The first is when the OCSP response does not contain a copy of the signer certificate, so the '--load-trust' code would fail. The second is if you want to avoid the indirect mode where the OCSP response signer certificate is signed by a trust anchor. Real-world example ------------------ Here is an example of how to generate an OCSP request for a certificate and to verify the response. For illustration we'll use the 'blog.josefsson.org' host, which (as of writing) uses a certificate from CACert. First we'll use 'gnutls-cli' to get a copy of the server certificate chain. The server is not required to send this information, but this particular one is configured to do so. $ echo | gnutls-cli -p 443 blog.josefsson.org --print-cert > chain.pem Use a text editor on 'chain.pem' to create three files for each separate certificates, called 'cert.pem' for the first certificate for the domain itself, secondly 'issuer.pem' for the intermediate certificate and 'root.pem' for the final root certificate. The domain certificate normally contains a pointer to where the OCSP responder is located, in the Authority Information Access Information extension. For example, from 'certtool -i < cert.pem' there is this information: Authority Information Access Information (not critical): Access Method: 1.3.6.1.5.5.7.48.1 (id-ad-ocsp) Access Location URI: http://ocsp.CAcert.org/ This means the CA support OCSP queries over HTTP. We are now ready to create a OCSP request for the certificate. $ ocsptool --ask ocsp.CAcert.org --load-issuer issuer.pem \ --load-cert cert.pem --outfile ocsp-response.der The request is sent via HTTP to the OCSP server address specified. If the address is ommited ocsptool will use the address stored in the certificate.  File: gnutls.info, Node: Smart cards and HSMs, Next: Abstract key types, Prev: ocsptool Invocation, Up: More on certificate authentication 6.7 Smart cards and HSMs ======================== In this section we present the smart-card and hardware security module (HSM) support in GnuTLS using PKCS #11 [_PKCS11_]. Hardware security modules and smart cards provide a way to store private keys and perform operations on them without exposing them. This decouples cryptographic keys from the applications that use them and provide an additional security layer against cryptographic key extraction. Since this can also be achieved in software components such as in Gnome keyring, we will use the term security module to describe any cryptographic key separation subsystem. PKCS #11 is plugin API allowing applications to access cryptographic operations on a security module, as well as to objects residing on it. PKCS #11 modules exist for hardware tokens such as smart cards(1), the trusted platform module (TPM)(2) as well as for software modules like Gnome Keyring. The objects residing on a security module may be certificates, public keys, private keys or secret keys. Of those certificates and public/private key pairs can be used with GnuTLS. PKCS #11's main advantage is that it allows operations on private key objects such as decryption and signing without exposing the key. Moreover PKCS #11 can be (ab)used to allow all applications in the same operating system to access shared cryptographic keys and certificates in a uniform way, as in *note Figure 6.2: fig:pkcs11-vision. That way applications could load their trusted certificate list, as well as user certificates from a common PKCS #11 module. Such a provider exists in the Gnome system, being the Gnome Keyring. [image src="pkcs11-vision.png"] Figure 6.2: PKCS #11 module usage. * Menu: * PKCS11 Initialization:: * Reading objects:: * Writing objects:: * Using a PKCS11 token with TLS:: * p11tool Invocation:: Invoking p11tool ---------- Footnotes ---------- (1) (2)  File: gnutls.info, Node: PKCS11 Initialization, Next: Reading objects, Up: Smart cards and HSMs 6.7.1 Initialization -------------------- To allow all the GnuTLS applications to access PKCS #11 tokens you can use a configuration per module, stored in '/etc/pkcs11/modules/'. These are the configuration files of p11-kit(1). For example a file that will load the OpenSC module, could be named '/etc/pkcs11/modules/opensc' and contain the following: module: /usr/lib/opensc-pkcs11.so If you use this file, then there is no need for other initialization in GnuTLS, except for the PIN and token functions. Those allow retrieving a PIN when accessing a protected object, such as a private key, as well as probe the user to insert the token. All the initialization functions are below. -- Function: int gnutls_pkcs11_init (unsigned int FLAGS, const char * DEPRECATED_CONFIG_FILE) FLAGS: 'GNUTLS_PKCS11_FLAG_MANUAL' or 'GNUTLS_PKCS11_FLAG_AUTO' DEPRECATED_CONFIG_FILE: either NULL or the location of a deprecated configuration file This function will initialize the PKCS 11 subsystem in gnutls. It will read configuration files if 'GNUTLS_PKCS11_FLAG_AUTO' is used or allow you to independently load PKCS 11 modules using 'gnutls_pkcs11_add_provider()' if 'GNUTLS_PKCS11_FLAG_MANUAL' is specified. Normally you don't need to call this function since it is being called by 'gnutls_global_init()' using the 'GNUTLS_PKCS11_FLAG_AUTO' . If other option is required then it must be called before it. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 2.12.0 'VOID *note gnutls_pkcs11_set_token_function:: (gnutls_pkcs11_token_callback_t FN, void * USERDATA)' 'VOID *note gnutls_pkcs11_set_pin_function:: (gnutls_pkcs11_pin_callback_t FN, void * USERDATA)' 'INT *note gnutls_pkcs11_add_provider:: (const char * NAME, const char * PARAMS)' Note that due to limitations of PKCS #11 there are issues when multiple libraries are sharing a module. To avoid this problem GnuTLS uses p11-kit that provides a middleware to control access to resources over the multiple users. Moreover PKCS #11 modules must be reinitialized on the child processes after a 'fork'. GnuTLS provides *note gnutls_pkcs11_reinit:: to be called for this purpose. -- Function: int gnutls_pkcs11_reinit ( VOID) This function will reinitialize the PKCS 11 subsystem in gnutls. This is required by PKCS 11 when an application uses 'fork()' . The reinitialization function must be called on the child. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 3.0 ---------- Footnotes ---------- (1)  File: gnutls.info, Node: Reading objects, Next: Writing objects, Prev: PKCS11 Initialization, Up: Smart cards and HSMs 6.7.2 Reading objects --------------------- All PKCS #11 objects are referenced by GnuTLS functions by URLs as described in [_PKCS11URI_]. This allows for a consistent naming of objects across systems and applications in the same system. For example a public key on a smart card may be referenced as: pkcs11:token=Nikos;serial=307521161601031;model=PKCS%2315; \ manufacturer=EnterSafe;object=test1;objecttype=public;\ id=32f153f3e37990b08624141077ca5dec2d15faed while the smart card itself can be referenced as: pkcs11:token=Nikos;serial=307521161601031;model=PKCS%2315;manufacturer=EnterSafe Objects stored in a PKCS #11 token can be extracted if they are not marked as sensitive. Usually only private keys are marked as sensitive and cannot be extracted, while certificates and other data can be retrieved. The functions that can be used to access objects are shown below. 'INT *note gnutls_pkcs11_obj_import_url:: (gnutls_pkcs11_obj_t CERT, const char * URL, unsigned int FLAGS)' 'INT *note gnutls_pkcs11_obj_export_url:: (gnutls_pkcs11_obj_t OBJ, gnutls_pkcs11_url_type_t DETAILED, char ** URL)' -- Function: int gnutls_pkcs11_obj_get_info (gnutls_pkcs11_obj_t CRT, gnutls_pkcs11_obj_info_t ITYPE, void * OUTPUT, size_t * OUTPUT_SIZE) CRT: should contain a 'gnutls_pkcs11_obj_t' structure ITYPE: Denotes the type of information requested OUTPUT: where output will be stored OUTPUT_SIZE: contains the maximum size of the output and will be overwritten with actual This function will return information about the PKCS11 certificate such as the label, id as well as token information where the key is stored. When output is text it returns null terminated string although 'output_size' contains the size of the actual data only. *Returns:* 'GNUTLS_E_SUCCESS' (0) on success or a negative error code on error. *Since:* 2.12.0 'INT *note gnutls_x509_crt_import_pkcs11:: (gnutls_x509_crt_t CRT, gnutls_pkcs11_obj_t PKCS11_CRT)' 'INT *note gnutls_x509_crt_import_pkcs11_url:: (gnutls_x509_crt_t CRT, const char * URL, unsigned int FLAGS)' 'INT *note gnutls_x509_crt_list_import_pkcs11:: (gnutls_x509_crt_t * CERTS, unsigned int CERT_MAX, gnutls_pkcs11_obj_t * const OBJS, unsigned int FLAGS)' Properties of the physical token can also be accessed and altered with GnuTLS. For example data in a token can be erased (initialized), PIN can be altered, etc. 'INT *note gnutls_pkcs11_token_init:: (const char * TOKEN_URL, const char * SO_PIN, const char * LABEL)' 'INT *note gnutls_pkcs11_token_get_url:: (unsigned int SEQ, gnutls_pkcs11_url_type_t DETAILED, char ** URL)' 'INT *note gnutls_pkcs11_token_get_info:: (const char * URL, gnutls_pkcs11_token_info_t TTYPE, void * OUTPUT, size_t * OUTPUT_SIZE)' 'INT *note gnutls_pkcs11_token_get_flags:: (const char * URL, unsigned int * FLAGS)' 'INT *note gnutls_pkcs11_token_set_pin:: (const char * TOKEN_URL, const char * OLDPIN, const char * NEWPIN, unsigned int FLAGS)' The following examples demonstrate the usage of the API. The first example will list all available PKCS #11 tokens in a system and the latter will list all certificates in a token that have a corresponding private key. int i; char* url; gnutls_global_init(); for (i=0;;i++) { ret = gnutls_pkcs11_token_get_url(i, &url); if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) break; if (ret < 0) exit(1); fprintf(stdout, "Token[%d]: URL: %s\n", i, url); gnutls_free(url); } gnutls_global_deinit(); /* This example code is placed in the public domain. */ #include #include #include #include #include #define URL "pkcs11:URL" int main (int argc, char** argv) { gnutls_pkcs11_obj_t *obj_list; gnutls_x509_crt_t xcrt; unsigned int obj_list_size = 0; gnutls_datum_t cinfo; int ret; unsigned int i; obj_list_size = 0; ret = gnutls_pkcs11_obj_list_import_url (NULL, &obj_list_size, URL, GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY, 0); if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) return -1; /* no error checking from now on */ obj_list = malloc (sizeof (*obj_list) * obj_list_size); gnutls_pkcs11_obj_list_import_url (obj_list, &obj_list_size, URL, GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY, 0); /* now all certificates are in obj_list */ for (i = 0; i < obj_list_size; i++) { gnutls_x509_crt_init (&xcrt); gnutls_x509_crt_import_pkcs11 (xcrt, obj_list[i]); gnutls_x509_crt_print (xcrt, GNUTLS_CRT_PRINT_FULL, &cinfo); fprintf (stdout, "cert[%d]:\n %s\n\n", i, cinfo.data); gnutls_free (cinfo.data); gnutls_x509_crt_deinit (xcrt); } return 0; }  File: gnutls.info, Node: Writing objects, Next: Using a PKCS11 token with TLS, Prev: Reading objects, Up: Smart cards and HSMs 6.7.3 Writing objects --------------------- With GnuTLS you can copy existing private keys and certificates to a token. Note that when copying private keys it is recommended to mark them as sensitive using the 'GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE' to prevent its extraction. An object can be marked as private using the flag 'GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE', to require PIN to be entered before accessing the object (for operations or otherwise). -- Function: int gnutls_pkcs11_copy_x509_privkey (const char * TOKEN_URL, gnutls_x509_privkey_t KEY, const char * LABEL, unsigned int KEY_USAGE, unsigned int FLAGS) TOKEN_URL: A PKCS '11' URL specifying a token KEY: A private key LABEL: A name to be used for the stored data KEY_USAGE: One of GNUTLS_KEY_* FLAGS: One of GNUTLS_PKCS11_OBJ_* flags This function will copy a private key into a PKCS '11' token specified by a URL. It is highly recommended flags to contain 'GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE' unless there is a strong reason not to. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 2.12.0 -- Function: int gnutls_pkcs11_copy_x509_crt (const char * TOKEN_URL, gnutls_x509_crt_t CRT, const char * LABEL, unsigned int FLAGS) TOKEN_URL: A PKCS '11' URL specifying a token CRT: A certificate LABEL: A name to be used for the stored data FLAGS: One of GNUTLS_PKCS11_OBJ_FLAG_* This function will copy a certificate into a PKCS '11' token specified by a URL. The certificate can be marked as trusted or not. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 2.12.0 -- Function: int gnutls_pkcs11_delete_url (const char * OBJECT_URL, unsigned int FLAGS) OBJECT_URL: The URL of the object to delete. FLAGS: One of GNUTLS_PKCS11_OBJ_* flags This function will delete objects matching the given URL. Note that not all tokens support the delete operation. *Returns:* On success, the number of objects deleted is returned, otherwise a negative error value. *Since:* 2.12.0  File: gnutls.info, Node: Using a PKCS11 token with TLS, Next: p11tool Invocation, Prev: Writing objects, Up: Smart cards and HSMs 6.7.4 Using a PKCS #11 token with TLS ------------------------------------- It is possible to use a PKCS #11 token to a TLS session, as shown in *note ex:pkcs11-client::. In addition the following functions can be used to load PKCS #11 key and certificates by specifying a PKCS #11 URL instead of a filename. 'INT *note gnutls_certificate_set_x509_trust_file:: (gnutls_certificate_credentials_t CRED, const char * CAFILE, gnutls_x509_crt_fmt_t TYPE)' 'INT *note gnutls_certificate_set_x509_key_file:: (gnutls_certificate_credentials_t RES, const char * CERTFILE, const char * KEYFILE, gnutls_x509_crt_fmt_t TYPE)' -- Function: int gnutls_certificate_set_x509_system_trust (gnutls_certificate_credentials_t CRED) CRED: is a 'gnutls_certificate_credentials_t' structure. 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  File: gnutls.info, Node: p11tool Invocation, Prev: Using a PKCS11 token with TLS, Up: Smart cards and HSMs 6.7.5 Invoking p11tool ---------------------- Program that allows handling data from PKCS #11 smart cards and security modules. To use PKCS #11 tokens with gnutls the configuration file /etc/gnutls/pkcs11.conf has to exist and contain a number of lines of the form 'load=/usr/lib/opensc-pkcs11.so'. This section was generated by *AutoGen*, using the 'agtexi-cmd' template and the option descriptions for the 'p11tool' program. This software is released under the GNU General Public License, version 3 or later. p11tool help/usage ('--help') ............................. This is the automatically generated usage text for p11tool. The text printed is the same whether selected with the 'help' option ('--help') or the 'more-help' option ('--more-help'). 'more-help' will print the usage text by passing it through a pager program. 'more-help' is disabled on platforms without a working 'fork(2)' function. The 'PAGER' environment variable is used to select the program, defaulting to 'more'. Both will exit with a status code of 0. p11tool - GnuTLS PKCS #11 tool - Ver. @VERSION@ USAGE: lt-p11tool [ - [] | --[{=| }] ]... [url] -d, --debug=num Enable debugging. - It must be in the range: 0 to 9999 --outfile=str Output file --list-tokens List all available tokens --export Export the object specified by the URL --list-mechanisms List all available mechanisms in a token --list-all List all available objects in a token --list-all-certs List all available certificates in a token --list-certs List all certificates that have an associated private key --list-all-privkeys List all available private keys in a token --list-all-trusted List all available certificates marked as trusted --initialize Initializes a PKCS #11 token --write Writes the loaded objects to a PKCS #11 token --delete Deletes the objects matching the PKCS #11 URL --generate-rsa Generate an RSA private-public key pair --generate-dsa Generate an RSA private-public key pair --generate-ecc Generate an RSA private-public key pair --label=str Sets a label for the write operation --trusted Marks the object to be written as trusted - disabled as --no-trusted --private Marks the object to be written as private - disabled as --no-private - enabled by default --login Force login to token - disabled as --no-login --detailed-url Print detailed URLs - disabled as --no-detailed-url --secret-key=str Provide a hex encoded secret key --load-privkey=file Private key file to use - file must pre-exist --load-pubkey=file Public key file to use - file must pre-exist --load-certificate=file Certificate file to use - file must pre-exist -8, --pkcs8 Use PKCS #8 format for private keys --bits=num Specify the number of bits for key generate --sec-param=str Specify the security level --inder Use DER/RAW format for input - disabled as --no-inder --inraw This is an alias for 'inder' --provider=file Specify the PKCS #11 provider library - file must pre-exist -v, --version[=arg] Output version information and exit -h, --help Display extended usage information and exit -!, --more-help Extended usage information passed thru pager Options are specified by doubled hyphens and their name or by a single hyphen and the flag character. Operands and options may be intermixed. They will be reordered. Program that allows handling data from PKCS #11 smart cards and security modules. To use PKCS #11 tokens with gnutls the configuration file /etc/gnutls/pkcs11.conf has to exist and contain a number of lines of the form 'load=/usr/lib/opensc-pkcs11.so'. please send bug reports to: bug-gnutls@gnu.org debug option (-d) ................. This is the "enable debugging." option. This option takes an argument number. Specifies the debug level. write option ............ This is the "writes the loaded objects to a pkcs #11 token" option. It can be used to write private keys, certificates or secret keys to a token. generate-rsa option ................... This is the "generate an rsa private-public key pair" option. Generates an RSA private-public key pair on the specified token. generate-dsa option ................... This is the "generate an rsa private-public key pair" option. Generates an RSA private-public key pair on the specified token. generate-ecc option ................... This is the "generate an rsa private-public key pair" option. Generates an RSA private-public key pair on the specified token. private option .............. This is the "marks the object to be written as private" option. This option has some usage constraints. It: * is enabled by default. The written object will require a PIN to be used. sec-param option ................ This is the "specify the security level" option. This option takes an argument string 'Security parameter'. This is alternative to the bits option. Available options are [low, legacy, normal, high, ultra]. inder option ............ This is the "use der/raw format for input" option. Use DER/RAW format for input certificates and private keys. inraw option ............ This is an alias for the 'inder' option, *note the inder option documentation: p11tool inder. provider option ............... This is the "specify the pkcs #11 provider library" option. This option takes an argument file. This will override the default options in /etc/gnutls/pkcs11.conf p11tool exit status ................... One of the following exit values will be returned: '0 (EXIT_SUCCESS)' Successful program execution. '1 (EXIT_FAILURE)' The operation failed or the command syntax was not valid. p11tool See Also ................ certtool (1) p11tool Examples ................ To view all tokens in your system use: $ p11tool --list-tokens To view all objects in a token use: $ p11tool --login --list-all "pkcs11:TOKEN-URL" To store a private key and a certificate in a token run: $ p11tool --login --write "pkcs11:URL" --load-privkey key.pem \ --label "Mykey" $ p11tool --login --write "pkcs11:URL" --load-certificate cert.pem \ --label "Mykey" Note that some tokens require the same label to be used for the certificate and its corresponding private key.  File: gnutls.info, Node: Abstract key types, Prev: Smart cards and HSMs, Up: More on certificate authentication 6.8 Abstract key types ====================== Since there are many forms of a public or private keys supported by GnuTLS such as X.509, OpenPGP, or PKCS #11 it is desirable to allow common operations on them. For these reasons the abstract 'gnutls_privkey_t' and 'gnutls_pubkey_t' were introduced in 'gnutls/abstract.h' header. Those types are initialized using a specific type of key and then can be used to perform operations in an abstract way. For example in order to sign an X.509 certificate with a key that resides in a token the following steps must be used. #inlude #inlude void sign_cert( gnutls_x509_crt_t to_be_signed) { gnutls_pkcs11_privkey_t ca_key; gnutls_x509_crt_t ca_cert; gnutls_privkey_t abs_key; /* load the PKCS #11 key and certificates */ gnutls_pkcs11_privkey_init(&ca_key); gnutls_pkcs11_privkey_import_url(ca_key, key_url); gnutls_x509_crt_init(&ca_cert); gnutls_x509_crt_import_pkcs11_url(&ca_cert, cert_url); /* initialize the abstract key */ gnutls_privkey_init(&abs_key); gnutls_privkey_import_pkcs11(abs_key, ca_key); /* sign the certificate to be signed */ gnutls_x509_crt_privkey_sign(to_be_signed, ca_cert, ca_key, GNUTLS_DIG_SHA256, 0); } * Menu: * Abstract public keys:: * Abstract private keys:: * Operations::  File: gnutls.info, Node: Abstract public keys, Next: Abstract private keys, Up: Abstract key types 6.8.1 Public keys ----------------- An abstract 'gnutls_pubkey_t' can be initialized using the functions below. It can be imported through an existing structure like 'gnutls_x509_crt_t', or through an ASN.1 encoding of the X.509 'SubjectPublicKeyInfo' sequence. -- Function: int gnutls_pubkey_import_x509 (gnutls_pubkey_t KEY, gnutls_x509_crt_t CRT, unsigned int FLAGS) KEY: The public key CRT: The certificate to be imported FLAGS: should be zero This function will import the given public key to the abstract 'gnutls_pubkey_t' structure. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 2.12.0 'INT *note gnutls_pubkey_import_openpgp:: (gnutls_pubkey_t KEY, gnutls_openpgp_crt_t CRT, unsigned int FLAGS)' 'INT *note gnutls_pubkey_import_pkcs11:: (gnutls_pubkey_t KEY, gnutls_pkcs11_obj_t OBJ, unsigned int FLAGS)' 'INT *note gnutls_pubkey_import_pkcs11_url:: (gnutls_pubkey_t KEY, const char * URL, unsigned int FLAGS)' 'INT *note gnutls_pubkey_import_privkey:: (gnutls_pubkey_t KEY, gnutls_privkey_t PKEY, unsigned int USAGE, unsigned int FLAGS)' 'INT *note gnutls_pubkey_import:: (gnutls_pubkey_t KEY, const gnutls_datum_t * DATA, gnutls_x509_crt_fmt_t FORMAT)' -- Function: int gnutls_pubkey_export (gnutls_pubkey_t KEY, gnutls_x509_crt_fmt_t FORMAT, void * OUTPUT_DATA, size_t * OUTPUT_DATA_SIZE) KEY: Holds the certificate FORMAT: the format of output params. One of PEM or DER. OUTPUT_DATA: will contain a certificate PEM or DER encoded OUTPUT_DATA_SIZE: holds the size of output_data (and will be replaced by the actual size of parameters) This function will export the public key to DER or PEM format. The contents of the exported data is the SubjectPublicKeyInfo X.509 structure. If the buffer provided is not long enough to hold the output, then *output_data_size is updated and 'GNUTLS_E_SHORT_MEMORY_BUFFER' will be returned. If the structure is PEM encoded, it will have a header of "BEGIN CERTIFICATE". *Returns:* In case of failure a negative error code will be returned, and 0 on success. *Since:* 2.12.0 Additional functions are available that will return information over a public key. 'INT *note gnutls_pubkey_get_pk_algorithm:: (gnutls_pubkey_t KEY, unsigned int * BITS)' 'INT *note gnutls_pubkey_get_preferred_hash_algorithm:: (gnutls_pubkey_t KEY, gnutls_digest_algorithm_t * HASH, unsigned int * MAND)' 'INT *note gnutls_pubkey_get_key_id:: (gnutls_pubkey_t KEY, unsigned int FLAGS, unsigned char * OUTPUT_DATA, size_t * OUTPUT_DATA_SIZE)'  File: gnutls.info, Node: Abstract private keys, Next: Operations, Prev: Abstract public keys, Up: Abstract key types 6.8.2 Private keys ------------------ An abstract 'gnutls_privkey_t' can be initialized using the functions below. It can be imported through an existing structure like 'gnutls_x509_privkey_t', but unlike public keys it cannot be exported. That is to allow abstraction over PKCS #11 keys that are not extractable. 'INT *note gnutls_privkey_import_x509:: (gnutls_privkey_t PKEY, gnutls_x509_privkey_t KEY, unsigned int FLAGS)' 'INT *note gnutls_privkey_import_openpgp:: (gnutls_privkey_t PKEY, gnutls_openpgp_privkey_t KEY, unsigned int FLAGS)' 'INT *note gnutls_privkey_import_pkcs11:: (gnutls_privkey_t PKEY, gnutls_pkcs11_privkey_t KEY, unsigned int FLAGS)' 'INT *note gnutls_privkey_get_pk_algorithm:: (gnutls_privkey_t KEY, unsigned int * BITS)' 'GNUTLS_PRIVKEY_TYPE_T *note gnutls_privkey_get_type:: (gnutls_privkey_t KEY)' In order to support cryptographic operations using an external API, the following function is provided. This allows for a simple extensibility API without resorting to PKCS #11. -- Function: int gnutls_privkey_import_ext (gnutls_privkey_t PKEY, gnutls_pk_algorithm_t PK, void* USERDATA, gnutls_privkey_sign_func SIGN_FUNC, gnutls_privkey_decrypt_func DECRYPT_FUNC, unsigned int FLAGS) PKEY: The private key PK: The public key algorithm USERDATA: private data to be provided to the callbacks SIGN_FUNC: callback for signature operations DECRYPT_FUNC: callback for decryption operations FLAGS: Flags for the import This function will associate the given callbacks with the 'gnutls_privkey_t' structure. At least one of the two callbacks must be non-null. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 3.0  File: gnutls.info, Node: Operations, Prev: Abstract private keys, Up: Abstract key types 6.8.3 Operations ---------------- The abstract key types can be used to access signing and signature verification operations with the underlying keys. -- Function: int gnutls_pubkey_verify_data2 (gnutls_pubkey_t PUBKEY, gnutls_sign_algorithm_t ALGO, unsigned int FLAGS, const gnutls_datum_t * DATA, const gnutls_datum_t * SIGNATURE) PUBKEY: Holds the public key ALGO: The signature algorithm used FLAGS: should be 0 for now DATA: holds the signed data SIGNATURE: contains the signature This function will verify the given signed data, using the parameters from the certificate. *Returns:* In case of a verification failure 'GNUTLS_E_PK_SIG_VERIFY_FAILED' is returned, and zero or positive code on success. *Since:* 3.0 -- Function: int gnutls_pubkey_verify_hash2 (gnutls_pubkey_t KEY, gnutls_sign_algorithm_t ALGO, unsigned int FLAGS, const gnutls_datum_t * HASH, const gnutls_datum_t * SIGNATURE) KEY: Holds the public key ALGO: The signature algorithm used FLAGS: should be 0 for now HASH: holds the hash digest to be verified SIGNATURE: contains the signature This function will verify the given signed digest, using the parameters from the public key. *Returns:* In case of a verification failure 'GNUTLS_E_PK_SIG_VERIFY_FAILED' is returned, and zero or positive code on success. *Since:* 3.0 -- Function: int gnutls_pubkey_encrypt_data (gnutls_pubkey_t KEY, unsigned int FLAGS, const gnutls_datum_t * PLAINTEXT, gnutls_datum_t * CIPHERTEXT) KEY: Holds the public key FLAGS: should be 0 for now PLAINTEXT: The data to be encrypted CIPHERTEXT: contains the encrypted data This function will encrypt the given data, using the public key. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 3.0 -- Function: int gnutls_privkey_sign_data (gnutls_privkey_t SIGNER, gnutls_digest_algorithm_t HASH, unsigned int FLAGS, const gnutls_datum_t * DATA, gnutls_datum_t * SIGNATURE) SIGNER: Holds the key HASH: should be a digest algorithm FLAGS: should be 0 for now DATA: holds the data to be signed SIGNATURE: will contain the signature allocate with 'gnutls_malloc()' This function will sign the given data using a signature algorithm supported by the private key. Signature algorithms are always used together with a hash functions. Different hash functions may be used for the RSA algorithm, but only the SHA family for the DSA keys. Use 'gnutls_pubkey_get_preferred_hash_algorithm()' to determine the hash algorithm. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 2.12.0 -- Function: int gnutls_privkey_sign_hash (gnutls_privkey_t SIGNER, gnutls_digest_algorithm_t HASH_ALGO, unsigned int FLAGS, const gnutls_datum_t * HASH_DATA, gnutls_datum_t * SIGNATURE) SIGNER: Holds the signer's key HASH_ALGO: The hash algorithm used FLAGS: zero for now HASH_DATA: holds the data to be signed SIGNATURE: will contain newly allocated signature This function will sign the given hashed data using a signature algorithm supported by the private key. Signature algorithms are always used together with a hash functions. Different hash functions may be used for the RSA algorithm, but only SHA-XXX for the DSA keys. Use 'gnutls_pubkey_get_preferred_hash_algorithm()' to determine the hash algorithm. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 2.12.0 -- Function: int gnutls_privkey_decrypt_data (gnutls_privkey_t KEY, unsigned int FLAGS, const gnutls_datum_t * CIPHERTEXT, gnutls_datum_t * PLAINTEXT) KEY: Holds the key FLAGS: zero for now CIPHERTEXT: holds the data to be decrypted PLAINTEXT: will contain the decrypted data, allocated with 'gnutls_malloc()' This function will decrypt the given data using the algorithm supported by the private key. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 2.12.0 Signing existing structures, such as certificates, CRLs, or certificate requests, as well as associating public keys with structures is also possible using the key abstractions. -- Function: int gnutls_x509_crq_set_pubkey (gnutls_x509_crq_t CRQ, gnutls_pubkey_t KEY) CRQ: should contain a 'gnutls_x509_crq_t' structure KEY: holds a public key This function will set the public parameters from the given public key to the request. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 2.12.0 -- Function: int gnutls_x509_crt_set_pubkey (gnutls_x509_crt_t CRT, gnutls_pubkey_t KEY) CRT: should contain a 'gnutls_x509_crt_t' structure KEY: holds a public key This function will set the public parameters from the given public key to the request. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error value. *Since:* 2.12.0 'INT *note gnutls_x509_crt_privkey_sign:: (gnutls_x509_crt_t CRT, gnutls_x509_crt_t ISSUER, gnutls_privkey_t ISSUER_KEY, gnutls_digest_algorithm_t DIG, unsigned int FLAGS)' 'INT *note gnutls_x509_crl_privkey_sign:: (gnutls_x509_crl_t CRL, gnutls_x509_crt_t ISSUER, gnutls_privkey_t ISSUER_KEY, gnutls_digest_algorithm_t DIG, unsigned int FLAGS)' 'INT *note gnutls_x509_crq_privkey_sign:: (gnutls_x509_crq_t CRQ, gnutls_privkey_t KEY, gnutls_digest_algorithm_t DIG, unsigned int FLAGS)'  File: gnutls.info, Node: How to use GnuTLS in applications, Next: GnuTLS application examples, Prev: More on certificate authentication, Up: Top 7 How to use GnuTLS in applications *********************************** * Menu: * Introduction to the library:: * Preparation:: * Session initialization:: * Associating the credentials:: * Setting up the transport layer:: * TLS handshake:: * Data transfer and termination:: * Handling alerts:: * Priority Strings:: * Advanced and other topics:: * Using the cryptographic library:: * Selecting cryptographic key sizes::  File: gnutls.info, Node: Introduction to the library, Next: Preparation, Up: How to use GnuTLS in applications 7.1 Introduction ================ * Menu: * General idea:: * Error handling:: * Common types:: * Debugging and auditing:: * Thread safety:: * Callback functions::  File: gnutls.info, Node: General idea, Next: Error handling, Up: Introduction to the library 7.1.1 General idea ------------------ A brief description of how GnuTLS works internally is shown at *note Figure 7.1: fig:gnutls-design. This section may become more clear after having read the rest of this section. As shown in the figure, there is a read-only global state that is initialized once by the global initialization function. This global structure, among others, contains the memory allocation functions used, and structures needed for the ASN.1 parser. This structure is never modified by any GnuTLS function, except for the deinitialization function which frees all allocated memory and is called after the program has permanently finished using GnuTLS. [image src="gnutls-internals.png"] Figure 7.1: High level design of GnuTLS. The credentials structures are used by the authentication methods, such as certificate authentication. They store certificates, privates keys, and other information that is needed to prove the identity to the peer, and/or verify the indentity of the peer. The information stored in the credentials structures is initialized once and then can be shared by many TLS sessions. A GnuTLS session contains all the required information to handle one secure connection. The session communicates with the peers using the provided functions of the transport layer. Every session has a unique session ID shared with the peer. Since TLS sessions can be resumed, servers need a database back-end to hold the session's parameters. Every GnuTLS session after a successful handshake calls the appropriate back-end function (see *note resume::) to store the newly negotiated session. The session database is examined by the server just after having received the client hello(1), and if the session ID sent by the client, matches a stored session, the stored session will be retrieved, and the new session will be a resumed one, and will share the same session ID with the previous one. ---------- Footnotes ---------- (1) The first message in a TLS handshake  File: gnutls.info, Node: Error handling, Next: Common types, Prev: General idea, Up: Introduction to the library 7.1.2 Error handling -------------------- In GnuTLS most functions return an integer type as a result. In almost all cases a zero or a positive number means success, and a negative number indicates failure, or a situation that some action has to be taken. Thus negative error codes may be fatal or not. Fatal errors terminate the connection immediately and further sends and receives will be disallowed. Such an example is 'GNUTLS_E_DECRYPTION_FAILED'. Non-fatal errors may warn about something, i.e., a warning alert was received, or indicate the some action has to be taken. This is the case with the error code 'GNUTLS_E_REHANDSHAKE' returned by *note gnutls_record_recv::. This error code indicates that the server requests a re-handshake. The client may ignore this request, or may reply with an alert. You can test if an error code is a fatal one by using the *note gnutls_error_is_fatal::. All errors can be converted to a descriptive string using *note gnutls_strerror::. If any non fatal errors, that require an action, are to be returned by a function, these error codes will be documented in the function's reference. For example the error codes 'GNUTLS_E_WARNING_ALERT_RECEIVED' and 'GNUTLS_E_FATAL_ALERT_RECEIVED' that may returned when receiving data, should be handled by notifying the user of the alert (as explained in *note Handling alerts::). See *note Error codes::, for a description of the available error codes.  File: gnutls.info, Node: Common types, Next: Debugging and auditing, Prev: Error handling, Up: Introduction to the library 7.1.3 Common types ------------------ Several functions in GnuTLS use 'gnutls_datum_t' which is convenient way to combine a pointer to data and data's size. Its definition is shown below. typedef struct { unsigned char *data; unsigned int size; } gnutls_datum_t; Other functions that require data for scattered read use a structure similar to 'struct iovec' typically used by 'readv'. It is shown below. typedef struct { void *iov_base; /* Starting address */ size_t iov_len; /* Number of bytes to transfer */ } giovec_t;  File: gnutls.info, Node: Debugging and auditing, Next: Thread safety, Prev: Common types, Up: Introduction to the library 7.1.4 Debugging and auditing ---------------------------- In many cases things may not go as expected and further information, to assist debugging, from GnuTLS is desired. Those are the cases where the *note gnutls_global_set_log_level:: and *note gnutls_global_set_log_function:: are to be used. Those will print verbose information on the GnuTLS functions internal flow. 'VOID *note gnutls_global_set_log_level:: (int LEVEL)' 'VOID *note gnutls_global_set_log_function:: (gnutls_log_func LOG_FUNC)' When debugging is not required, important issues, such as detected attacks on the protocol still need to be logged. This is provided by the logging function set by *note gnutls_global_set_audit_log_function::. The provided function will receive an message and the corresponding TLS session. The session information might be used to derive IP addresses or other information about the peer involved. -- Function: void gnutls_global_set_audit_log_function (gnutls_audit_log_func LOG_FUNC) LOG_FUNC: it is the audit log function This is the function where you set the logging function gnutls is going to use. This is different from 'gnutls_global_set_log_function()' because it will report the session of the event if any. Note that that session might be null if there is no corresponding TLS session. 'gnutls_audit_log_func' is of the form, void (*gnutls_audit_log_func)( gnutls_session_t, int level, const char*); *Since:* 3.0  File: gnutls.info, Node: Thread safety, Next: Callback functions, Prev: Debugging and auditing, Up: Introduction to the library 7.1.5 Thread safety ------------------- The GnuTLS library is thread safe by design, meaning that objects of the library such as TLS sessions, can be safely divided across threads as long as a single thread accesses a single object. This is sufficient to support a server which handles several sessions per thread. If, however, an object needs to be shared across threads then access must be protected with a mutex. Read-only access to objects, for example the credentials holding structures, is also thread-safe. The random generator of the cryptographic back-end, is not thread safe and requires mutex locks which are setup by GnuTLS. Applications can either call *note gnutls_global_init:: which will initialize the default operating system provided locks (i.e. 'pthreads' on GNU/Linux and 'CriticalSection' on Windows), or manually specify the locking system using the function *note gnutls_global_set_mutex:: before calling *note gnutls_global_init::. Setting mutexes manually is recommended only for applications that have full control of the underlying libraries. If this is not the case, the use of the operating system defaults is recommended. An example of non-native thread usage is shown below. #include int main() { /* When the system mutexes are not to be used * gnutls_global_set_mutex() must be called explicitly */ gnutls_global_set_mutex (mutex_init, mutex_deinit, mutex_lock, mutex_unlock); gnutls_global_init(); } -- Function: void gnutls_global_set_mutex (mutex_init_func INIT, mutex_deinit_func DEINIT, mutex_lock_func LOCK, mutex_unlock_func UNLOCK) INIT: mutex initialization function DEINIT: mutex deinitialization function LOCK: mutex locking function UNLOCK: mutex unlocking function With this function you are allowed to override the default mutex locks used in some parts of gnutls and dependent libraries. This function should be used if you have complete control of your program and libraries. Do not call this function from a library. Instead only initialize gnutls and the default OS mutex locks will be used. This function must be called before 'gnutls_global_init()' . *Since:* 2.12.0  File: gnutls.info, Node: Callback functions, Prev: Thread safety, Up: Introduction to the library 7.1.6 Callback functions ------------------------ There are several cases where GnuTLS may need out of band input from your program. This is now implemented using some callback functions, which your program is expected to register. An example of this type of functions are the push and pull callbacks which are used to specify the functions that will retrieve and send data to the transport layer. 'VOID *note gnutls_transport_set_push_function:: (gnutls_session_t SESSION, gnutls_push_func PUSH_FUNC)' 'VOID *note gnutls_transport_set_pull_function:: (gnutls_session_t SESSION, gnutls_pull_func PULL_FUNC)' Other callback functions may require more complicated input and data to be allocated. Such an example is *note gnutls_srp_set_server_credentials_function::. All callbacks should allocate and free memory using 'gnutls_malloc' and 'gnutls_free'.  File: gnutls.info, Node: Preparation, Next: Session initialization, Prev: Introduction to the library, Up: How to use GnuTLS in applications 7.2 Preparation =============== To use GnuTLS, you have to perform some changes to your sources and your build system. The necessary changes are explained in the following subsections. * Menu: * Headers:: * Initialization:: * Version check:: * Building the source::  File: gnutls.info, Node: Headers, Next: Initialization, Up: Preparation 7.2.1 Headers ------------- All the data types and functions of the GnuTLS library are defined in the header file 'gnutls/gnutls.h'. This must be included in all programs that make use of the GnuTLS library.  File: gnutls.info, Node: Initialization, Next: Version check, Prev: Headers, Up: Preparation 7.2.2 Initialization -------------------- GnuTLS must be initialized before it can be used. The library is initialized by calling *note gnutls_global_init::. The resources allocated by the initialization process can be released if the application no longer has a need to call GnuTLS functions, this is done by calling *note gnutls_global_deinit::. In order to take advantage of the internationalization features in GnuTLS, such as translated error messages, the application must set the current locale using 'setlocale' before initializing GnuTLS.  File: gnutls.info, Node: Version check, Next: Building the source, Prev: Initialization, Up: Preparation 7.2.3 Version check ------------------- It is often desirable to check that the version of 'gnutls' used is indeed one which fits all requirements. Even with binary compatibility new features may have been introduced but due to problem with the dynamic linker an old version is actually used. So you may want to check that the version is okay right after program start-up. See the function *note gnutls_check_version::.  File: gnutls.info, Node: Building the source, Prev: Version check, Up: Preparation 7.2.4 Building the source ------------------------- If you want to compile a source file including the 'gnutls/gnutls.h' header file, you must make sure that the compiler can find it in the directory hierarchy. This is accomplished by adding the path to the directory in which the header file is located to the compilers include file search path (via the '-I' option). However, the path to the include file is determined at the time the source is configured. To solve this problem, the library uses the external package 'pkg-config' that knows the path to the include file and other configuration options. The options that need to be added to the compiler invocation at compile time are output by the '--cflags' option to 'pkg-config gnutls'. The following example shows how it can be used at the command line: gcc -c foo.c `pkg-config gnutls --cflags` Adding the output of 'pkg-config gnutls --cflags' to the compilers command line will ensure that the compiler can find the 'gnutls/gnutls.h' header file. A similar problem occurs when linking the program with the library. Again, the compiler has to find the library files. For this to work, the path to the library files has to be added to the library search path (via the '-L' option). For this, the option '--libs' to 'pkg-config gnutls' can be used. For convenience, this option also outputs all other options that are required to link the program with the library (for instance, the '-ltasn1' option). The example shows how to link 'foo.o' with the library to a program 'foo'. gcc -o foo foo.o `pkg-config gnutls --libs` Of course you can also combine both examples to a single command by specifying both options to 'pkg-config': gcc -o foo foo.c `pkg-config gnutls --cflags --libs` When a program uses the GNU autoconf system, then the following line or similar can be used to detect the presence of GnuTLS. PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 3.0.0]) AC_SUBST([LIBGNUTLS_CFLAGS]) AC_SUBST([LIBGNUTLS_LIBS])  File: gnutls.info, Node: Session initialization, Next: Associating the credentials, Prev: Preparation, Up: How to use GnuTLS in applications 7.3 Session initialization ========================== In the previous sections we have discussed the global initialization required for GnuTLS as well as the initialization required for each authentication method's credentials (see *note Authentication::). In this section we elaborate on the TLS or DTLS session initiation. Each session is initialized using *note gnutls_init:: which among others is used to specify the type of the connection (server or client), and the underlying protocol type, i.e., datagram (UDP) or reliable (TCP). -- Function: int gnutls_init (gnutls_session_t * SESSION, unsigned int FLAGS) SESSION: is a pointer to a 'gnutls_session_t' structure. FLAGS: indicate if this session is to be used for server or client. This function initializes the current session to null. Every session must be initialized before use, so internal structures can be allocated. This function allocates structures which can only be free'd by calling 'gnutls_deinit()' . Returns 'GNUTLS_E_SUCCESS' (0) on success. 'flags' can be one of 'GNUTLS_CLIENT' and 'GNUTLS_SERVER' . For a DTLS entity, the flags 'GNUTLS_DATAGRAM' and 'GNUTLS_NONBLOCK' are also available. The latter flag will enable a non-blocking operation of the DTLS timers. *Returns:* 'GNUTLS_E_SUCCESS' on success, or an error code. After the session initialization details on the allowed ciphersuites and protocol versions should be set using the priority functions such as *note gnutls_priority_set_direct::. We elaborate on them in *note Priority Strings::. The credentials used for the key exchange method, such as certificates or usernames and passwords should also be associated with the session current session using *note gnutls_credentials_set::. -- Function: int gnutls_credentials_set (gnutls_session_t SESSION, gnutls_credentials_type_t TYPE, void * CRED) SESSION: is a 'gnutls_session_t' structure. TYPE: is the type of the credentials CRED: is a pointer to a structure. Sets the needed credentials for the specified type. Eg username, password - or public and private keys etc. The 'cred' parameter is a structure that depends on the specified type and on the current session (client or server). In order to minimize memory usage, and share credentials between several threads gnutls keeps a pointer to cred, and not the whole cred structure. Thus you will have to keep the structure allocated until you call 'gnutls_deinit()' . For 'GNUTLS_CRD_ANON' , 'cred' should be 'gnutls_anon_client_credentials_t' in case of a client. In case of a server it should be 'gnutls_anon_server_credentials_t' . For 'GNUTLS_CRD_SRP' , 'cred' should be 'gnutls_srp_client_credentials_t' in case of a client, and 'gnutls_srp_server_credentials_t' , in case of a server. For 'GNUTLS_CRD_CERTIFICATE' , 'cred' should be 'gnutls_certificate_credentials_t' . *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise a negative error code is returned.  File: gnutls.info, Node: Associating the credentials, Next: Setting up the transport layer, Prev: Session initialization, Up: How to use GnuTLS in applications 7.4 Associating the credentials =============================== * Menu: * Certificate credentials:: * SRP credentials:: * PSK credentials:: * Anonymous credentials:: Each authentication method is associated with a key exchange method, and a credentials type. The contents of the credentials is method-dependent, e.g. certificates for certificate authentication and should be initialized and associated with a session (see *note gnutls_credentials_set::). A mapping of the key exchange methods with the credential types is shown in *note Table 7.1: tab:key-exchange-cred. Authentication Key exchange Client Server method credentials credentials -------------------------------------------------------------------- Certificate 'KX_RSA', 'CRD_CERTIFICATE''CRD_CERTIFICATE' 'KX_DHE_RSA', 'KX_DHE_DSS', 'KX_ECDHE_RSA', 'KX_ECDHE_ECDSA', 'KX_RSA_EXPORT' Password and 'KX_SRP_RSA', 'CRD_SRP' 'CRD_CERTIFICATE', certificate 'KX_SRP_DSS' 'CRD_SRP' Password 'KX_SRP' 'CRD_SRP' 'CRD_SRP' Anonymous 'KX_ANON_DH', 'CRD_ANON' 'CRD_ANON' 'KX_ANON_ECDH' Pre-shared key 'KX_PSK', 'CRD_PSK' 'CRD_PSK' 'KX_DHE_PSK', 'KX_ECDHE_PSK' Table 7.1: Key exchange algorithms and the corresponding credential types.  File: gnutls.info, Node: Certificate credentials, Next: SRP credentials, Up: Associating the credentials 7.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. 'INT *note gnutls_certificate_allocate_credentials:: (gnutls_certificate_credentials_t * RES)' 'VOID *note 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 *note gnutls_certificate_set_x509_key_mem:: (gnutls_certificate_credentials_t RES, const gnutls_datum_t * CERT, const gnutls_datum_t * KEY, gnutls_x509_crt_fmt_t TYPE)' 'INT *note 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)' 'INT *note gnutls_certificate_set_x509_key_file:: (gnutls_certificate_credentials_t RES, const char * CERTFILE, const char * KEYFILE, gnutls_x509_crt_fmt_t TYPE)' 'INT *note gnutls_certificate_set_openpgp_key_mem:: (gnutls_certificate_credentials_t RES, const gnutls_datum_t * CERT, const gnutls_datum_t * KEY, gnutls_openpgp_crt_fmt_t FORMAT)' 'INT *note gnutls_certificate_set_openpgp_key:: (gnutls_certificate_credentials_t RES, gnutls_openpgp_crt_t CRT, gnutls_openpgp_privkey_t PKEY)' 'INT *note gnutls_certificate_set_openpgp_key_file:: (gnutls_certificate_credentials_t RES, const char * CERTFILE, const char * KEYFILE, gnutls_openpgp_crt_fmt_t FORMAT)' 'INT *note 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)' 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 *note 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 *note gnutls_sign_algorithm_get_requested::. Both functions are shown below. 'VOID *note gnutls_certificate_set_retrieve_function:: (gnutls_certificate_credentials_t CRED, gnutls_certificate_retrieve_function * FUNC)' 'VOID *note gnutls_certificate_set_retrieve_function2:: (gnutls_certificate_credentials_t CRED, gnutls_certificate_retrieve_function2 * FUNC)' 'INT *note 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 *note gnutls_server_name_get::, and serve the appropriate certificate. 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 *note Table 4.1: tab:key-exchange. 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 *note gnutls_certificate_server_set_request::. The request contains a list of the acceptable by the server 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 *note 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' structure. REQ: is one of GNUTLS_CERT_REQUEST, GNUTLS_CERT_REQUIRE 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 an 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. -- Function: void gnutls_certificate_send_x509_rdn_sequence (gnutls_session_t SESSION, int STATUS) SESSION: is a pointer to a 'gnutls_session_t' structure. 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. 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 and OpenPGP certificates. 'INT *note gnutls_certificate_set_x509_trust_file:: (gnutls_certificate_credentials_t CRED, const char * CAFILE, gnutls_x509_crt_fmt_t TYPE)' 'INT *note gnutls_certificate_set_openpgp_keyring_file:: (gnutls_certificate_credentials_t C, const char * FILE, gnutls_openpgp_crt_fmt_t FORMAT)' The peer's certificate is not automatically verified and one should call *note gnutls_certificate_verify_peers2:: after a successful handshake to verify the certificate's signature. Alternative the verification can occur during the handshake by using *note gnutls_certificate_set_verify_function::. In order to report a detailed verification output, an alternative way has to be used. For that, one should call *note gnutls_certificate_get_peers:: to obtain the raw certificate of the peer and verify it using the functions discussed in *note X.509 certificates::. -- Function: int gnutls_certificate_verify_peers2 (gnutls_session_t SESSION, unsigned int * STATUS) SESSION: is a gnutls session STATUS: is the output of the verification This function will try to verify the peer's certificate and return its status (trusted, invalid etc.). The value of 'status' should be one or more of the gnutls_certificate_status_t enumerated elements bitwise or'd. To avoid denial of service attacks some default upper limits regarding the certificate key size and chain size are set. To override them use 'gnutls_certificate_set_verify_limits()' . Note that you must also check the peer's name in order to check if the verified certificate belongs to the actual peer. This function uses 'gnutls_x509_crt_list_verify()' with the CAs in the credentials as trusted CAs. *Returns:* a negative error code on error and 'GNUTLS_E_SUCCESS' (0) on success. -- Function: void gnutls_certificate_set_verify_function (gnutls_certificate_credentials_t CRED, gnutls_certificate_verify_function * FUNC) CRED: is a 'gnutls_certificate_credentials_t' structure. FUNC: is the callback function This function sets a callback to be called when peer's certificate has been received in order to verify it on receipt rather than doing after the handshake is completed. The callback's function prototype is: int (*callback)(gnutls_session_t); If the callback function is provided then gnutls will call it, in the handshake, just after the certificate message has been received. To verify or obtain the certificate the 'gnutls_certificate_verify_peers2()' , 'gnutls_certificate_type_get()' , 'gnutls_certificate_get_peers()' functions can be used. The callback function should return 0 for the handshake to continue or non-zero to terminate. *Since:* 2.10.0  File: gnutls.info, Node: SRP credentials, Next: PSK credentials, Prev: Certificate credentials, Up: Associating the credentials 7.4.2 SRP --------- The initialization functions in SRP credentials differ between client and server. Clients supporting SRP should set the username and password prior to connection, to the credentials structure. Alternatively *note gnutls_srp_set_client_credentials_function:: may be used instead, to specify a callback function that should return the SRP username and password. The callback is called once during the TLS handshake. 'INT *note gnutls_srp_allocate_server_credentials:: (gnutls_srp_server_credentials_t * SC)' 'INT *note gnutls_srp_allocate_client_credentials:: (gnutls_srp_client_credentials_t * SC)' 'VOID *note gnutls_srp_free_server_credentials:: (gnutls_srp_server_credentials_t SC)' 'VOID *note gnutls_srp_free_client_credentials:: (gnutls_srp_client_credentials_t SC)' 'INT *note gnutls_srp_set_client_credentials:: (gnutls_srp_client_credentials_t RES, const char * USERNAME, const char * PASSWORD)' -- Function: void gnutls_srp_set_client_credentials_function (gnutls_srp_client_credentials_t CRED, gnutls_srp_client_credentials_function * FUNC) CRED: is a 'gnutls_srp_server_credentials_t' structure. FUNC: is the callback function This function can be used to set a callback to retrieve the username and password for client SRP authentication. The callback's function form is: int (*callback)(gnutls_session_t, char** username, char**password); The 'username' and 'password' must be allocated using 'gnutls_malloc()' . 'username' and 'password' should be ASCII strings or UTF-8 strings prepared using the "SASLprep" profile of "stringprep". The callback function will be called once per handshake before the initial hello message is sent. The callback should not return a negative error code the second time called, since the handshake procedure will be aborted. The callback function should return 0 on success. -1 indicates an error. In server side the default behavior of GnuTLS is to read the usernames and SRP verifiers from password files. These password file format is compatible the with the _Stanford srp libraries_ format. If a different password file format is to be used, then *note gnutls_srp_set_server_credentials_function:: should be called, to set an appropriate callback. -- Function: int gnutls_srp_set_server_credentials_file (gnutls_srp_server_credentials_t RES, const char * PASSWORD_FILE, const char * PASSWORD_CONF_FILE) RES: is a 'gnutls_srp_server_credentials_t' structure. PASSWORD_FILE: is the SRP password file (tpasswd) PASSWORD_CONF_FILE: is the SRP password conf file (tpasswd.conf) This function sets the password files, in a 'gnutls_srp_server_credentials_t' structure. Those password files hold usernames and verifiers and will be used for SRP authentication. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, or an error code. -- Function: void gnutls_srp_set_server_credentials_function (gnutls_srp_server_credentials_t CRED, gnutls_srp_server_credentials_function * FUNC) CRED: is a 'gnutls_srp_server_credentials_t' structure. FUNC: is the callback function This function can be used to set a callback to retrieve the user's SRP credentials. The callback's function form is: int (*callback)(gnutls_session_t, const char* username, gnutls_datum_t* salt, gnutls_datum_t *verifier, gnutls_datum_t* g, gnutls_datum_t* n); 'username' contains the actual username. The 'salt' , 'verifier' , 'generator' and 'prime' must be filled in using the 'gnutls_malloc()' . For convenience 'prime' and 'generator' may also be one of the static parameters defined in gnutls.h. In case the callback returned a negative number then gnutls will assume that the username does not exist. In order to prevent attackers from guessing valid usernames, if a user does not exist, g and n values should be filled in using a random user's parameters. In that case the callback must return the special value (1). The callback function will only be called once per handshake. The callback function should return 0 on success, while -1 indicates an error.  File: gnutls.info, Node: PSK credentials, Next: Anonymous credentials, Prev: SRP credentials, Up: Associating the credentials 7.4.3 PSK --------- The initialization functions in PSK credentials differ between client and server. 'INT *note gnutls_psk_allocate_server_credentials:: (gnutls_psk_server_credentials_t * SC)' 'INT *note gnutls_psk_allocate_client_credentials:: (gnutls_psk_client_credentials_t * SC)' 'VOID *note gnutls_psk_free_server_credentials:: (gnutls_psk_server_credentials_t SC)' 'VOID *note gnutls_psk_free_client_credentials:: (gnutls_psk_client_credentials_t SC)' Clients supporting PSK should supply the username and key before a TLS session is established. Alternatively *note gnutls_psk_set_client_credentials_function:: can be used to specify a callback function. This has the advantage that the callback will be called only if PSK has been negotiated. 'INT *note gnutls_psk_set_client_credentials:: (gnutls_psk_client_credentials_t RES, const char * USERNAME, const gnutls_datum_t * KEY, gnutls_psk_key_flags FLAGS)' -- Function: void gnutls_psk_set_client_credentials_function (gnutls_psk_client_credentials_t CRED, gnutls_psk_client_credentials_function * FUNC) CRED: is a 'gnutls_psk_server_credentials_t' structure. FUNC: is the callback function This function can be used to set a callback to retrieve the username and password for client PSK authentication. The callback's function form is: int (*callback)(gnutls_session_t, char** username, gnutls_datum_t* key); The 'username' and 'key' ->data must be allocated using 'gnutls_malloc()' . 'username' should be ASCII strings or UTF-8 strings prepared using the "SASLprep" profile of "stringprep". The callback function will be called once per handshake. The callback function should return 0 on success. -1 indicates an error. In server side the default behavior of GnuTLS is to read the usernames and PSK keys from a password file. The password file should contain usernames and keys in hexadecimal format. The name of the password file can be stored to the credentials structure by calling *note gnutls_psk_set_server_credentials_file::. If a different password file format is to be used, then a callback should be set instead by *note gnutls_psk_set_server_credentials_function::. The server can help the client chose a suitable username and password, by sending a hint. Note that there is no common profile for the PSK hint and applications are discouraged to use it. A server, may specify the hint by calling *note gnutls_psk_set_server_credentials_hint::. The client can retrieve the hint, for example in the callback function, using *note gnutls_psk_client_get_hint::. -- Function: int gnutls_psk_set_server_credentials_file (gnutls_psk_server_credentials_t RES, const char * PASSWORD_FILE) RES: is a 'gnutls_psk_server_credentials_t' structure. PASSWORD_FILE: is the PSK password file (passwd.psk) This function sets the password file, in a 'gnutls_psk_server_credentials_t' structure. This password file holds usernames and keys and will be used for PSK authentication. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise an error code is returned. 'VOID *note gnutls_psk_set_server_credentials_function:: (gnutls_psk_server_credentials_t CRED, gnutls_psk_server_credentials_function * FUNC)' 'INT *note gnutls_psk_set_server_credentials_hint:: (gnutls_psk_server_credentials_t RES, const char * HINT)' 'CONST CHAR * *note gnutls_psk_client_get_hint:: (gnutls_session_t SESSION)'  File: gnutls.info, Node: Anonymous credentials, Prev: PSK credentials, Up: Associating the credentials 7.4.4 Anonymous --------------- The key exchange methods for anonymous authentication might require Diffie-Hellman parameters to be generated by the server and associated with an anonymous credentials structure. Check *note Parameter generation:: for more information. The initialization functions for the credentials are shown below. 'INT *note gnutls_anon_allocate_server_credentials:: (gnutls_anon_server_credentials_t * SC)' 'INT *note gnutls_anon_allocate_client_credentials:: (gnutls_anon_client_credentials_t * SC)' 'VOID *note gnutls_anon_free_server_credentials:: (gnutls_anon_server_credentials_t SC)' 'VOID *note gnutls_anon_free_client_credentials:: (gnutls_anon_client_credentials_t SC)'  File: gnutls.info, Node: Setting up the transport layer, Next: TLS handshake, Prev: Associating the credentials, Up: How to use GnuTLS in applications 7.5 Setting up the transport layer ================================== The next step is to setup the underlying transport layer details. The Berkeley sockets are implicitly used by GnuTLS, thus a call to *note gnutls_transport_set_ptr2:: would be sufficient to specify the socket descriptor. -- Function: void gnutls_transport_set_ptr2 (gnutls_session_t SESSION, gnutls_transport_ptr_t RECV_PTR, gnutls_transport_ptr_t SEND_PTR) SESSION: is a 'gnutls_session_t' structure. RECV_PTR: is the value for the pull function SEND_PTR: is the value for the push function Used to set the first argument of the transport function (for push and pull callbacks). In berkeley style sockets this function will set the connection descriptor. With this function you can use two different pointers for receiving and sending. 'VOID *note gnutls_transport_set_ptr:: (gnutls_session_t SESSION, gnutls_transport_ptr_t PTR)' If however another transport layer than TCP is selected, then the following functions have to be specified. -- Function: void gnutls_transport_set_push_function (gnutls_session_t SESSION, gnutls_push_func PUSH_FUNC) SESSION: is a 'gnutls_session_t' structure. PUSH_FUNC: a callback function similar to 'write()' This is the function where you set a push function for gnutls to use in order to send data. If you are going to use berkeley style sockets, you do not need to use this function since the default send(2) will probably be ok. Otherwise you should specify this function for gnutls to be able to send data. The callback should return a positive number indicating the bytes sent, and -1 on error. 'push_func' is of the form, ssize_t (*gnutls_push_func)(gnutls_transport_ptr_t, const void*, size_t); -- Function: void gnutls_transport_set_vec_push_function (gnutls_session_t SESSION, gnutls_vec_push_func VEC_FUNC) SESSION: is a 'gnutls_session_t' structure. VEC_FUNC: a callback function similar to 'writev()' Using this function you can override the default writev(2) function for gnutls to send data. Setting this callback instead of 'gnutls_transport_set_push_function()' is recommended since it introduces less overhead in the TLS handshake process. 'vec_func' is of the form, ssize_t (*gnutls_vec_push_func) (gnutls_transport_ptr_t, const giovec_t * iov, int iovcnt); *Since:* 2.12.0 -- Function: void gnutls_transport_set_pull_function (gnutls_session_t SESSION, gnutls_pull_func PULL_FUNC) SESSION: is a 'gnutls_session_t' structure. PULL_FUNC: a callback function similar to 'read()' This is the function where you set a function for gnutls to receive data. Normally, if you use berkeley style sockets, do not need to use this function since the default recv(2) will probably be ok. The callback should return 0 on connection termination, a positive number indicating the number of bytes received, and -1 on error. 'gnutls_pull_func' is of the form, ssize_t (*gnutls_pull_func)(gnutls_transport_ptr_t, void*, size_t); The functions above accept a callback function which should return the number of bytes written, or -1 on error and should set 'errno' appropriately. In some environments, setting 'errno' is unreliable. For example Windows have several errno variables in different CRTs, or in other systems it may be a non thread-local variable. If this is a concern to you, call *note gnutls_transport_set_errno:: with the intended errno value instead of setting 'errno' directly. -- Function: void gnutls_transport_set_errno (gnutls_session_t SESSION, int ERR) SESSION: is a 'gnutls_session_t' structure. ERR: error value to store in session-specific errno variable. Store 'err' in the session-specific errno variable. Useful values for 'err' is EAGAIN and EINTR, other values are treated will be treated as real errors in the push/pull function. This function is useful in replacement push and pull functions set by 'gnutls_transport_set_push_function()' and 'gnutls_transport_set_pull_function()' under Windows, where the replacements may not have access to the same 'errno' variable that is used by GnuTLS (e.g., the application is linked to msvcr71.dll and gnutls is linked to msvcrt.dll). GnuTLS currently only interprets the EINTR, EAGAIN and EMSGSIZE errno values and returns the corresponding GnuTLS error codes: * 'GNUTLS_E_INTERRUPTED' * 'GNUTLS_E_AGAIN' * 'GNUTLS_E_LARGE_PACKET' The EINTR and EAGAIN values are returned by interrupted system calls, or when non blocking IO is used. All GnuTLS functions can be resumed (called again), if any of the above error codes is returned. The EMSGSIZE value is returned when attempting to send a large datagram. In the case of DTLS it is also desirable to override the generic transport functions with functions that emulate the operation of 'recvfrom' and 'sendto'. In addition DTLS requires timers during the receive of a handshake message, set using the *note gnutls_transport_set_pull_timeout_function:: function. To check the retransmission timers the function *note gnutls_dtls_get_timeout:: is provided, which returns the time remaining until the next retransmission, or better the time until *note gnutls_handshake:: should be called again. -- Function: void gnutls_transport_set_pull_timeout_function (gnutls_session_t SESSION, gnutls_pull_timeout_func FUNC) SESSION: is a 'gnutls_session_t' structure. FUNC: a callback function This is the function where you set a function for gnutls to know whether data are ready to be received. It should wait for data a given time frame in milliseconds. The callback should return 0 on timeout, a positive number if data can be received, and -1 on error. You'll need to override this function if 'select()' is not suitable for the provided transport calls. The callback function is used in DTLS only. 'gnutls_pull_timeout_func' is of the form, ssize_t (*gnutls_pull_timeout_func)(gnutls_transport_ptr_t, unsigned int ms); *Since:* 3.0 -- Function: unsigned int gnutls_dtls_get_timeout (gnutls_session_t SESSION) SESSION: is a 'gnutls_session_t' structure. This function will return the milliseconds remaining for a retransmission of the previously sent handshake message. This function is useful when DTLS is used in non-blocking mode, to estimate when to call 'gnutls_handshake()' if no packets have been received. *Returns:* the remaining time in milliseconds. *Since:* 3.0 * Menu: * Asynchronous operation:: * DTLS sessions::  File: gnutls.info, Node: Asynchronous operation, Next: DTLS sessions, Up: Setting up the transport layer 7.5.1 Asynchronous operation ---------------------------- GnuTLS can be used with asynchronous socket or event-driven programming. The approach is similar to using Berkeley sockets under such an environment. The blocking, due to network interaction, calls such as *note gnutls_handshake::, *note gnutls_record_recv::, can be set to non-blocking by setting the underlying sockets to non-blocking. If other push and pull functions are setup, then they should behave the same way as 'recv' and 'send' when used in a non-blocking way, i.e., set errno to 'EAGAIN'. Since, during a TLS protocol session GnuTLS does not block except for network interaction, the non blocking 'EAGAIN' errno will be propagated and GnuTLS functions will return the 'GNUTLS_E_AGAIN' error code. Such calls can be resumed the same way as a system call would. The only exception is *note gnutls_record_send::, which if interrupted subsequent calls need not to include the data to be sent (can be called with NULL argument). The 'select' system call can also be used in combination with the GnuTLS functions. 'select' allows monitoring of sockets and notifies on them being ready for reading or writing data. Note however that this system call cannot notify on data present in GnuTLS read buffers, it is only applicable to the kernel sockets API. Thus if you are using it for reading from a GnuTLS session, make sure that any cached data are read completely. That can be achieved by checking there are no data waiting to be read (using *note gnutls_record_check_pending::), either before the 'select' system call, or after a call to *note gnutls_record_recv::. GnuTLS does not keep a write buffer, thus when writing no additional actions are required. Although in the TLS protocol implementation each call to receive or send function implies to restoring the same function that was interrupted, in the DTLS protocol this requirement isn't true. There are cases where a retransmission is required, which are indicated by a received message and thus *note gnutls_record_get_direction:: must be called to decide which direction to check prior to restoring a function call. -- Function: int gnutls_record_get_direction (gnutls_session_t SESSION) SESSION: is a 'gnutls_session_t' structure. This function provides information about the internals of the record protocol and is only useful if a prior gnutls function call (e.g. 'gnutls_handshake()' ) was interrupted for some reason, that is, if a function returned 'GNUTLS_E_INTERRUPTED' or 'GNUTLS_E_AGAIN' . In such a case, you might want to call 'select()' or 'poll()' before calling the interrupted gnutls function again. To tell you whether a file descriptor should be selected for either reading or writing, 'gnutls_record_get_direction()' returns 0 if the interrupted function was trying to read data, and 1 if it was trying to write data. *Returns:* 0 if trying to read data, 1 if trying to write data. Moreover, to prevent blocking from DTLS' retransmission timers to block a handshake, the *note gnutls_init:: function should be called with the 'GNUTLS_NONBLOCK' flag set (see *note Session initialization::).  File: gnutls.info, Node: DTLS sessions, Prev: Asynchronous operation, Up: Setting up the transport layer 7.5.2 DTLS sessions ------------------- Because datagram TLS can operate over connections where the peer of a server cannot be reliably verified, functionality is available to prevent denial of service attacks. GnuTLS requires a server to generate a secret key that is used to sign a cookie(1). That cookie is sent to the client using *note gnutls_dtls_cookie_send::, and the client must reply using the correct cookie. The server side should verify the initial message sent by client using *note gnutls_dtls_cookie_verify::. If successful the session should be initialized and associated with the cookie using *note gnutls_dtls_prestate_set::, before proceeding to the handshake. 'INT *note gnutls_key_generate:: (gnutls_datum_t * KEY, unsigned int KEY_SIZE)' 'INT *note gnutls_dtls_cookie_send:: (gnutls_datum_t* KEY, void* CLIENT_DATA, size_t CLIENT_DATA_SIZE, gnutls_dtls_prestate_st* PRESTATE, gnutls_transport_ptr_t PTR, gnutls_push_func PUSH_FUNC)' 'INT *note gnutls_dtls_cookie_verify:: (gnutls_datum_t* KEY, void* CLIENT_DATA, size_t CLIENT_DATA_SIZE, void* _MSG, size_t MSG_SIZE, gnutls_dtls_prestate_st* PRESTATE)' 'VOID *note gnutls_dtls_prestate_set:: (gnutls_session_t SESSION, gnutls_dtls_prestate_st* PRESTATE)' Note that the above apply to server side only and they are not mandatory to be used. Not using them, however, allows denial of service attacks. The client side cookie handling is part of *note gnutls_handshake::. Datagrams are typically restricted by a maximum transfer unit (MTU). For that both client and server side should set the correct maximum transfer unit for the layer underneath GnuTLS. This will allow proper fragmentation of DTLS messages and prevent messages from being silently discarded by the transport layer. The "correct" maximum transfer unit can be obtained through a path MTU discovery mechanism [_RFC4821_]. 'VOID *note gnutls_dtls_set_mtu:: (gnutls_session_t SESSION, unsigned int MTU)' 'UNSIGNED INT *note gnutls_dtls_get_mtu:: (gnutls_session_t SESSION)' 'UNSIGNED INT *note gnutls_dtls_get_data_mtu:: (gnutls_session_t SESSION)' ---------- Footnotes ---------- (1) A key of 128 bits or 16 bytes should be sufficient for this purpose.  File: gnutls.info, Node: TLS handshake, Next: Data transfer and termination, Prev: Setting up the transport layer, Up: How to use GnuTLS in applications 7.6 TLS handshake ================= Once a session has been initialized and a network connection has been set up, TLS and DTLS protocols perform a handshake. The handshake is the actual key exchange. -- Function: int gnutls_handshake (gnutls_session_t SESSION) SESSION: is a 'gnutls_session_t' structure. This function does the handshake of the TLS/SSL protocol, and initializes the TLS connection. This function will fail if any problem is encountered, and will return a negative error code. In case of a client, if the client has asked to resume a session, but the server couldn't, then a full handshake will be performed. The non-fatal errors such as 'GNUTLS_E_AGAIN' and 'GNUTLS_E_INTERRUPTED' interrupt the handshake procedure, which should be resumed later. Call this function again, until it returns 0; cf. 'gnutls_record_get_direction()' and 'gnutls_error_is_fatal()' . If this function is called by a server after a rehandshake request then 'GNUTLS_E_GOT_APPLICATION_DATA' or 'GNUTLS_E_WARNING_ALERT_RECEIVED' may be returned. Note that these are non fatal errors, only in the specific case of a rehandshake. Their meaning is that the client rejected the rehandshake request or in the case of 'GNUTLS_E_GOT_APPLICATION_DATA' it might also mean that some data were pending. *Returns:* 'GNUTLS_E_SUCCESS' on success, otherwise a negative error code. The handshake process doesn't ensure the verification of the peer's identity. When certificates are in use, this can be done, either after the handshake is complete, or during the handshake if *note gnutls_certificate_set_verify_function:: has been used. In both cases the *note gnutls_certificate_verify_peers2:: function can be used to verify the peer's certificate (see *note Certificate authentication:: for more information). 'INT *note gnutls_certificate_verify_peers2:: (gnutls_session_t SESSION, unsigned int * STATUS)'  File: gnutls.info, Node: Data transfer and termination, Next: Handling alerts, Prev: TLS handshake, Up: How to use GnuTLS in applications 7.7 Data transfer and termination ================================= Once the handshake is complete and peer's identity has been verified data can be exchanged. The available functions resemble the POSIX 'recv' and 'send' functions. It is suggested to use *note gnutls_error_is_fatal:: to check whether the error codes returned by these functions are fatal for the protocol or can be ignored. -- Function: ssize_t gnutls_record_send (gnutls_session_t SESSION, const void * DATA, size_t DATA_SIZE) SESSION: is a 'gnutls_session_t' structure. DATA: contains the data to send DATA_SIZE: is the length of the data This function has the similar semantics with 'send()' . The only difference is that it accepts a GnuTLS session, and uses different error codes. Note that if the send buffer is full, 'send()' will block this function. See the 'send()' documentation for full information. You can replace the default push function by using 'gnutls_transport_set_ptr2()' with a call to 'send()' with a MSG_DONTWAIT flag if blocking is a problem. If the EINTR is returned by the internal push function (the default is 'send()' ) then 'GNUTLS_E_INTERRUPTED' will be returned. If 'GNUTLS_E_INTERRUPTED' or 'GNUTLS_E_AGAIN' is returned, you must call this function again, with the same parameters; alternatively you could provide a 'NULL' pointer for data, and 0 for size. cf. 'gnutls_record_get_direction()' . The errno value EMSGSIZE maps to 'GNUTLS_E_LARGE_PACKET' . *Returns:* The number of bytes sent, or a negative error code. The number of bytes sent might be less than 'data_size' . The maximum number of bytes this function can send in a single call depends on the negotiated maximum record size. -- Function: ssize_t gnutls_record_recv (gnutls_session_t SESSION, void * DATA, size_t DATA_SIZE) SESSION: is a 'gnutls_session_t' structure. DATA: the buffer that the data will be read into DATA_SIZE: the number of requested bytes This function has the similar semantics with 'recv()' . The only difference is that it accepts a GnuTLS session, and uses different error codes. In the special case that a server requests a renegotiation, the client may receive an error code of 'GNUTLS_E_REHANDSHAKE' . This message may be simply ignored, replied with an alert 'GNUTLS_A_NO_RENEGOTIATION' , or replied with a new handshake, depending on the client's will. If 'EINTR' is returned by the internal push function (the default is 'recv()' ) then 'GNUTLS_E_INTERRUPTED' will be returned. If 'GNUTLS_E_INTERRUPTED' or 'GNUTLS_E_AGAIN' is returned, you must call this function again to get the data. See also 'gnutls_record_get_direction()' . A server may also receive 'GNUTLS_E_REHANDSHAKE' when a client has initiated a handshake. In that case the server can only initiate a handshake or terminate the connection. *Returns:* The number of bytes received and zero on EOF (for stream connections). A negative error code is returned in case of an error. The number of bytes received might be less than the requested 'data_size' . -- Function: int gnutls_error_is_fatal (int ERROR) ERROR: is a GnuTLS error code, a negative error code If a GnuTLS function returns a negative error code you may feed that value to this function to see if the error condition is fatal. Note that you may also want to check the error code manually, since some non-fatal errors to the protocol (such as a warning alert or a rehandshake request) may be fatal for your program. This function is only useful if you are dealing with errors from the record layer or the handshake layer. *Returns:* 1 if the error code is fatal, for positive 'error' values, 0 is returned. For unknown 'error' values, -1 is returned. Although, in the TLS protocol the receive function can be called at any time, when DTLS is used the GnuTLS receive functions must be called once a message is available for reading, even if no data are expected. This is because in DTLS various (internal) actions may be required due to retransmission timers. Moreover, an extended receive function is shown below, which allows the extraction of the message's sequence number. Due to the unreliable nature of the protocol, this field allows distinguishing out-of-order messages. -- Function: ssize_t gnutls_record_recv_seq (gnutls_session_t SESSION, void * DATA, size_t DATA_SIZE, unsigned char * SEQ) SESSION: is a 'gnutls_session_t' structure. DATA: the buffer that the data will be read into DATA_SIZE: the number of requested bytes SEQ: is the packet's 64-bit sequence number. Should have space for 8 bytes. This function is the same as 'gnutls_record_recv()' , except that it returns in addition to data, the sequence number of the data. This is useful in DTLS where record packets might be received out-of-order. The returned 8-byte sequence number is an integer in big-endian format and should be treated as a unique message identification. *Returns:* The number of bytes received and zero on EOF. A negative error code is returned in case of an error. The number of bytes received might be less than 'data_size' . *Since:* 3.0 The *note gnutls_record_check_pending:: helper function is available to allow checking whether data are available to be read in a GnuTLS session buffers. Note that this function complements but does not replace 'select', i.e., *note gnutls_record_check_pending:: reports no data to be read, 'select' should be called to check for data in the network buffers. -- Function: size_t gnutls_record_check_pending (gnutls_session_t SESSION) SESSION: is a 'gnutls_session_t' structure. This function checks if there are unread data in the gnutls buffers. If the return value is non-zero the next call to 'gnutls_record_recv()' is guarranteed not to block. *Returns:* Returns the size of the data or zero. 'INT *note gnutls_record_get_direction:: (gnutls_session_t SESSION)' Once a TLS or DTLS session is no longer needed, it is recommended to use *note gnutls_bye:: to terminate the session. That way the peer is notified securely about the intention of termination, which allows distinguishing it from a malicious connection termination. A session can be deinitialized with the *note gnutls_deinit:: function. -- Function: int gnutls_bye (gnutls_session_t SESSION, gnutls_close_request_t HOW) SESSION: is a 'gnutls_session_t' structure. HOW: is an integer Terminates the current TLS/SSL connection. The connection should have been initiated using 'gnutls_handshake()' . 'how' should be one of 'GNUTLS_SHUT_RDWR' , 'GNUTLS_SHUT_WR' . In case of 'GNUTLS_SHUT_RDWR' the TLS session gets terminated and further receives and sends will be disallowed. If the return value is zero you may continue using the underlying transport layer. 'GNUTLS_SHUT_RDWR' sends an alert containing a close request and waits for the peer to reply with the same message. In case of 'GNUTLS_SHUT_WR' the TLS session gets terminated and further sends will be disallowed. In order to reuse the connection you should wait for an EOF from the peer. 'GNUTLS_SHUT_WR' sends an alert containing a close request. Note that not all implementations will properly terminate a TLS connection. Some of them, usually for performance reasons, will terminate only the underlying transport layer, and thus not distinguishing between a malicious party prematurely terminating the connection and normal termination. This function may also return 'GNUTLS_E_AGAIN' or 'GNUTLS_E_INTERRUPTED' ; cf. 'gnutls_record_get_direction()' . *Returns:* 'GNUTLS_E_SUCCESS' on success, or an error code, see function documentation for entire semantics. -- Function: void gnutls_deinit (gnutls_session_t SESSION) SESSION: is a 'gnutls_session_t' structure. This function clears all buffers associated with the 'session' . This function will also remove session data from the session database if the session was terminated abnormally.  File: gnutls.info, Node: Handling alerts, Next: Priority Strings, Prev: Data transfer and termination, Up: How to use GnuTLS in applications 7.8 Handling alerts =================== During a TLS connection alert messages may be exchanged by the two peers. Those messages may be fatal, meaning the connection must be terminated afterwards, or warning when something needs to be reported to the peer, but without interrupting the session. The error codes 'GNUTLS_E_WARNING_ALERT_RECEIVED' or 'GNUTLS_E_FATAL_ALERT_RECEIVED' signal those alerts when received, and may be returned by all GnuTLS functions that receive data from the peer, being *note gnutls_handshake:: and *note gnutls_record_recv::. If those error codes are received the alert and its level should be logged or reported to the peer using the functions below. -- Function: gnutls_alert_description_t gnutls_alert_get (gnutls_session_t SESSION) SESSION: is a 'gnutls_session_t' structure. This function will return the last alert number received. This function should be called when 'GNUTLS_E_WARNING_ALERT_RECEIVED' or 'GNUTLS_E_FATAL_ALERT_RECEIVED' errors are returned by a gnutls function. The peer may send alerts if he encounters an error. If no alert has been received the returned value is undefined. *Returns:* the last alert received, a 'gnutls_alert_description_t' value. -- Function: const char * gnutls_alert_get_name (gnutls_alert_description_t ALERT) ALERT: is an alert number. This function will return a string that describes the given alert number, or 'NULL' . See 'gnutls_alert_get()' . *Returns:* string corresponding to 'gnutls_alert_description_t' value. The peer may also be warned or notified of a fatal issue by using one of the functions below. All the available alerts are listed in *note The Alert Protocol::. -- Function: int gnutls_alert_send (gnutls_session_t SESSION, gnutls_alert_level_t LEVEL, gnutls_alert_description_t DESC) SESSION: is a 'gnutls_session_t' structure. LEVEL: is the level of the alert DESC: is the alert description This function will send an alert to the peer in order to inform him of something important (eg. his Certificate could not be verified). If the alert level is Fatal then the peer is expected to close the connection, otherwise he may ignore the alert and continue. The error code of the underlying record send function will be returned, so you may also receive 'GNUTLS_E_INTERRUPTED' or 'GNUTLS_E_AGAIN' as well. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, otherwise an error code is returned. -- Function: int gnutls_error_to_alert (int ERR, int * LEVEL) ERR: is a negative integer LEVEL: the alert level will be stored there Get an alert depending on the error code returned by a gnutls function. All alerts sent by this function should be considered fatal. The only exception is when 'err' is 'GNUTLS_E_REHANDSHAKE' , where a warning alert should be sent to the peer indicating that no renegotiation will be performed. If there is no mapping to a valid alert the alert to indicate internal error is returned. *Returns:* the alert code to use for a particular error code.  File: gnutls.info, Node: Priority Strings, Next: Advanced and other topics, Prev: Handling alerts, Up: How to use GnuTLS in applications 7.9 Priority strings ==================== In order to specify cipher suite preferences on a TLS session there are priority functions that accept a string specifying the enabled for the handshake algorithms. That string may contain a single initial keyword such as in *note Table 7.2: tab:prio-keywords. and may be followed by additional algorithm or special keywords. 'INT *note gnutls_priority_set_direct:: (gnutls_session_t SESSION, const char * PRIORITIES, const char ** ERR_POS)' 'INT *note gnutls_priority_set:: (gnutls_session_t SESSION, gnutls_priority_t PRIORITY)' Keyword Description ------------------------------------------------------------------ PERFORMANCE All the known to be secure ciphersuites are enabled, limited to 128 bit ciphers and sorted by terms of speed performance. The message authenticity security level is of 64 bits or more. NORMAL Means all the known to be secure ciphersuites. The ciphers are sorted by security margin, although the 256-bit ciphers are included as a fallback only. The message authenticity security level is of 64 bits or more. SECURE128 Means all known to be secure ciphersuites that offer a security level 128-bit or more and a message authenticity security level of 80 bits or more. SECURE192 Means all the known to be secure ciphersuites that offer a security level 192-bit or more and a message authenticity security level of 128 bits or more. SECURE256 Currently alias for SECURE192. SUITEB128 Means all the NSA Suite B cryptography (RFC5430) ciphersuites with an 128 bit security level. SUITEB192 Means all the NSA Suite B cryptography (RFC5430) ciphersuites with an 192 bit security level. EXPORT Means all ciphersuites are enabled, including the low-security 40 bit ciphers. NONE Means nothing is enabled. This disables even protocols and compression methods. It should be followed by the algorithms to be enabled. Table 7.2: Supported initial keywords. Unless the initial keyword is "NONE" the defaults (in preference order) are for TLS protocols TLS 1.2, TLS1.1, TLS1.0, SSL3.0; for compression NULL; for certificate types X.509. In key exchange algorithms when in NORMAL or SECURE levels the perfect forward secrecy algorithms take precedence of the other protocols. In all cases all the supported key exchange algorithms are enabled(1). Note that the SECURE levels distinguish between overall security level and message authenticity security level. That is because the message authenticity security level requires the adversary to break the algorithms at real-time during the protocol run, whilst the overall security level refers to off-line adversaries (e.g. adversaries breaking the ciphertext years after it was captured). The NONE keyword, if used, must followed by keywords specifying the algorithms and protocols to be enabled. The other initial keywords may be followed by such keywords. The order with which every algorithm or protocol is specified is significant. Algorithms specified before others will take precedence. The supported algorithms and protocols are shown in *note Table 7.3: tab:prio-algorithms. To avoid collisions in order to specify a compression algorithm in the priority string you have to prefix it with "COMP-", protocol versions with "VERS-", signature algorithms with "SIGN-" and certificate types with "CTYPE-". All other algorithms don't need a prefix. Each specified keyword can be prefixed with any of the following characters. '!' or '-' appended with an algorithm will remove this algorithm. "+" appended with an algorithm will add this algorithm. Type Keywords ------------------------------------------------------------------ Ciphers AES-128-CBC, AES-256-CBC, AES-128-GCM, CAMELLIA-128-CBC, CAMELLIA-256-CBC, ARCFOUR-128, 3DES-CBC ARCFOUR-40. Catch all name is CIPHER-ALL which will add all the algorithms from NORMAL priority. Key exchange RSA, DHE-RSA, DHE-DSS, SRP, SRP-RSA, SRP-DSS, PSK, DHE-PSK, ECDHE-RSA, ANON-ECDH, ANON-DH, RSA-EXPORT. The Catch all name is KX-ALL which will add all the algorithms from NORMAL priority. MAC MD5, SHA1, SHA256, AEAD (used with GCM ciphers only). All algorithms from NORMAL priority can be accessed with MAC-ALL. Compression COMP-NULL, COMP-DEFLATE. Catch all is COMP-ALL. algorithms TLS versions VERS-SSL3.0, VERS-TLS1.0, VERS-TLS1.1, VERS-TLS1.2, VERS-DTLS1.0. Catch all is VERS-TLS-ALL. Signature SIGN-RSA-SHA1, SIGN-RSA-SHA224, SIGN-RSA-SHA256, algorithms SIGN-RSA-SHA384, SIGN-RSA-SHA512, SIGN-DSA-SHA1, SIGN-DSA-SHA224, SIGN-DSA-SHA256, SIGN-RSA-MD5. Catch all is SIGN-ALL. This is only valid for TLS 1.2 and later. Elliptic CURVE-SECP192R1, CURVE-SECP224R1, curves CURVE-SECP256R1, CURVE-SECP384R1, CURVE-SECP521R1. Catch all is CURVE-ALL. Table 7.3: The supported algorithm keywords in priority strings. Note that the DHE key exchange methods are generally slower(2) than their elliptic curves counterpart (ECDHE). Moreover the plain Diffie-Hellman key exchange requires parameters to be generated and associated with a credentials structure by the server (see *note Parameter generation::). The available special keywords are shown in *note Table 7.4: tab:prio-special. Keyword Description ------------------------------------------------------------------ %COMPAT will enable compatibility mode. It might mean that violations of the protocols are allowed as long as maximum compatibility with problematic clients and servers is achieved. More specifically this string would disable TLS record random padding and tolerate packets over the maximum allowed TLS record. %NO_EXTENSIONS will prevent the sending of any TLS extensions in client side. Note that TLS 1.2 requires extensions to be used, as well as safe renegotiation thus this option must be used with care. %STATELESS_COMPRESSION will disable keeping state across records when compressing. This may help to mitigate attacks when compression is used but an attacker is in control of input data. %SERVER_PRECEDENCE The ciphersuite will be selected according to server priorities and not the client's. %DISABLE_SAFE_RENEGOTIATION will disable safe renegotiation completely. Do not use unless you know what you are doing. Testing purposes only. %UNSAFE_RENEGOTIATION will allow handshakes and re-handshakes without the safe renegotiation extension. Note that for clients this mode is insecure (you may be under attack), and for servers it will allow insecure clients to connect (which could be fooled by an attacker). Do not use unless you know what you are doing and want maximum compatibility. %PARTIAL_RENEGOTIATION will allow initial handshakes to proceed, but not re-handshakes. This leaves the client vulnerable to attack, and servers will be compatible with non-upgraded clients for initial handshakes. This is currently the default for clients and servers, for compatibility reasons. %SAFE_RENEGOTIATION will enforce safe renegotiation. Clients and servers will refuse to talk to an insecure peer. Currently this causes interoperability problems, but is required for full protection. %SSL3_RECORD_VERSION will use SSL3.0 record version in client hello. This is the default. %LATEST_RECORD_VERSION will use the latest TLS version record version in client hello. %VERIFY_ALLOW_SIGN_RSA_MD5 will allow RSA-MD5 signatures in certificate chains. %VERIFY_ALLOW_X509_V1_CA_CRT will allow V1 CAs in chains. Table 7.4: Special priority string keywords. Finally the ciphersuites enabled by any priority string can be listed using the 'gnutls-cli' application (see *note gnutls-cli Invocation::), or by using the priority functions as in *note Listing the ciphersuites in a priority string::. Example priority strings are: The default priority without the HMAC-MD5: "NORMAL:-MD5" Specifying RSA with AES-128-CBC: "NONE:+VERS-TLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL" Specifying the defaults except ARCFOUR-128: "NORMAL:-ARCFOUR-128" Enabling the 128-bit secure ciphers, while disabling SSL 3.0 and enabling compression: "SECURE128:-VERS-SSL3.0:+COMP-DEFLATE" ---------- Footnotes ---------- (1) Except for the RSA-EXPORT which is only enabled in EXPORT level. (2) It depends on the group used. Primes with lesser bits are always faster, but also easier to break. See *note Selecting cryptographic key sizes:: for the acceptable security levels.  File: gnutls.info, Node: Advanced and other topics, Next: Using the cryptographic library, Prev: Priority Strings, Up: How to use GnuTLS in applications 7.10 Advanced and other topics ============================== * Menu: * Session resumption:: * Parameter generation:: * Keying Material Exporters:: * Channel Bindings:: * Interoperability:: * Compatibility with the OpenSSL library::  File: gnutls.info, Node: Session resumption, Next: Parameter generation, Up: Advanced and other topics 7.10.1 Session resumption ------------------------- Client side ........... To reduce time and roundtrips spent in a handshake the client can request session resumption from a server that previously shared a session with. For that the client has to retrieve and store the session parameters. Before establishing a new session to the same server the parameters must be re-associated with the GnuTLS session using *note gnutls_session_set_data::. 'INT *note gnutls_session_get_data:: (gnutls_session_t SESSION, void * SESSION_DATA, size_t * SESSION_DATA_SIZE)' 'INT *note gnutls_session_get_id:: (gnutls_session_t SESSION, void * SESSION_ID, size_t * SESSION_ID_SIZE)' 'INT *note gnutls_session_set_data:: (gnutls_session_t SESSION, const void * SESSION_DATA, size_t SESSION_DATA_SIZE)' Keep in mind that sessions will be expired after some time, depending on the server, and a server may choose not to resume a session even when requested to. The expiration is to prevent temporal session keys from becoming long-term keys. Also note that as a client you must enable, using the priority functions, at least the algorithms used in the last session. It is highly recommended for clients to enable the session ticket extension using *note gnutls_session_ticket_enable_client:: in order to allow resumption with servers that do not store any state. 'INT *note gnutls_session_ticket_enable_client:: (gnutls_session_t SESSION)' -- Function: int gnutls_session_is_resumed (gnutls_session_t SESSION) SESSION: is a 'gnutls_session_t' structure. Check whether session is resumed or not. *Returns:* non zero if this session is resumed, or a zero if this is a new session. Server side ........... In order to support resumption a server can store the session security parameters in a local database or by using session tickets (see *note Session tickets::) to delegate storage to the client. Because session tickets might not be supported by all clients, servers could combine the two methods. A storing server needs to specify callback functions to store, retrieve and delete session data. These can be registered with the functions below. The stored sessions in the database can be checked using *note gnutls_db_check_entry:: for expiration. 'VOID *note gnutls_db_set_retrieve_function:: (gnutls_session_t SESSION, gnutls_db_retr_func RETR_FUNC)' 'VOID *note gnutls_db_set_store_function:: (gnutls_session_t SESSION, gnutls_db_store_func STORE_FUNC)' 'VOID *note gnutls_db_set_ptr:: (gnutls_session_t SESSION, void * PTR)' 'VOID *note gnutls_db_set_remove_function:: (gnutls_session_t SESSION, gnutls_db_remove_func REM_FUNC)' 'INT *note gnutls_db_check_entry:: (gnutls_session_t SESSION, gnutls_datum_t SESSION_ENTRY)' A server utilizing tickets should generate ticket encryption and authentication keys using *note gnutls_session_ticket_key_generate::. Those keys should be associated with the GnuTLS session using *note gnutls_session_ticket_enable_server::. -- Function: int gnutls_session_ticket_enable_server (gnutls_session_t SESSION, const gnutls_datum_t * KEY) SESSION: is a 'gnutls_session_t' structure. KEY: key to encrypt session parameters. Request that the server should attempt session resumption using SessionTicket. 'key' must be initialized with 'gnutls_session_ticket_key_generate()' . *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, or an error code. *Since:* 2.10.0 -- Function: int gnutls_session_ticket_key_generate (gnutls_datum_t * KEY) KEY: is a pointer to a 'gnutls_datum_t' which will contain a newly created key. Generate a random key to encrypt security parameters within SessionTicket. *Returns:* On success, 'GNUTLS_E_SUCCESS' (0) is returned, or an error code. *Since:* 2.10.0 -- Function: int gnutls_session_resumption_requested (gnutls_session_t SESSION) SESSION: is a 'gnutls_session_t' structure. Check whether the client has asked for session resumption. This function is valid only on server side. *Returns:* non zero if session resumption was asked, or a zero if not. A server enabling both session tickets and a storage for session data would use session tickets when clients support it and the storage otherwise.  File: gnutls.info, Node: Parameter generation, Next: Keying Material Exporters, Prev: Session resumption, Up: Advanced and other topics 7.10.2 Parameter generation --------------------------- Several TLS ciphersuites require additional parameters that need to be generated or provided by the application. The Diffie-Hellman based ciphersuites (ANON-DH or DHE), require the group parameters to be provided. Those can either be be generated on the fly using *note gnutls_dh_params_generate2:: or imported from pregenerated data using *note gnutls_dh_params_import_pkcs3::. The parameters can be used in a TLS session by calling *note gnutls_certificate_set_dh_params:: or *note gnutls_anon_set_server_dh_params:: for anonymous sessions. 'INT *note gnutls_dh_params_generate2:: (gnutls_dh_params_t PARAMS, unsigned int BITS)' 'INT *note gnutls_dh_params_import_pkcs3:: (gnutls_dh_params_t PARAMS, const gnutls_datum_t * PKCS3_PARAMS, gnutls_x509_crt_fmt_t FORMAT)' 'VOID *note gnutls_certificate_set_dh_params:: (gnutls_certificate_credentials_t RES, gnutls_dh_params_t DH_PARAMS)' 'VOID *note gnutls_anon_set_server_dh_params:: (gnutls_anon_server_credentials_t RES, gnutls_dh_params_t DH_PARAMS)' Due to the time-consuming calculations required for the generation of Diffie-Hellman parameters we suggest against performing generation of them within an application. The 'certtool' tool can be used to generate or export known safe values that can be stored in code or in a configuration file to provide the ability to replace. We also recommend the usage of *note gnutls_sec_param_to_pk_bits:: (see *note Selecting cryptographic key sizes::) to determine the bit size of the generated parameters. Note that the information stored in the generated PKCS #3 structure changed with GnuTLS 3.0.9. Since that version the 'privateValueLength' member of the structure is set, allowing the server utilizing the parameters to use keys of the size of the security parameter. This provides better performance in key exchange. The ciphersuites that involve the RSA-EXPORT key exchange require additional parameters. Those ciphersuites are rarely used today because they are by design insecure, thus if you have no requirement for them, the rest of this section can be skipped. The RSA-EXPORT key exchange requires 512-bit RSA keys to be generated. It is recommended those parameters to be refreshed (regenerated) in short intervals. The following functions can be used for these parameters. 'INT *note gnutls_rsa_params_generate2:: (gnutls_rsa_params_t PARAMS, unsigned int BITS)' 'VOID *note gnutls_certificate_set_rsa_export_params:: (gnutls_certificate_credentials_t RES, gnutls_rsa_params_t RSA_PARAMS)' 'INT *note gnutls_rsa_params_import_pkcs1:: (gnutls_rsa_params_t PARAMS, const gnutls_datum_t * PKCS1_PARAMS, gnutls_x509_crt_fmt_t FORMAT)' 'INT *note gnutls_rsa_params_export_pkcs1:: (gnutls_rsa_params_t PARAMS, gnutls_x509_crt_fmt_t FORMAT, unsigned char * PARAMS_DATA, size_t * PARAMS_DATA_SIZE)' To allow renewal of the parameters within an application without accessing the credentials, which are a shared structure, an alternative interface is available using a callback function. -- Function: void gnutls_certificate_set_params_function (gnutls_certificate_credentials_t RES, gnutls_params_function * FUNC) RES: is a gnutls_certificate_credentials_t structure FUNC: is the function to be called This function will set a callback in order for the server to get the Diffie-Hellman or RSA parameters for certificate authentication. The callback should return 'GNUTLS_E_SUCCESS' (0) on success.  File: gnutls.info, Node: Keying Material Exporters, Next: Channel Bindings, Prev: Parameter generation, Up: Advanced and other topics 7.10.3 Keying material exporters -------------------------------- The TLS PRF can be used by other protocols to derive keys based on the TLS master secret. The API to use is *note gnutls_prf::. The function needs to be provided with the label in the parameter 'label', and the extra data to mix in the 'extra' parameter. Depending on whether you want to mix in the client or server random data first, you can set the 'server_random_first' parameter. For example, after establishing a TLS session using *note gnutls_handshake::, you can invoke the TLS PRF with this call: #define MYLABEL "EXPORTER-FOO" #define MYCONTEXT "some context data" char out[32]; rc = gnutls_prf (session, strlen (MYLABEL), MYLABEL, 0, strlen (MYCONTEXT), MYCONTEXT, 32, out); If you don't want to mix in the client/server random, there is a low-level TLS PRF interface called *note gnutls_prf_raw::.  File: gnutls.info, Node: Channel Bindings, Next: Interoperability, Prev: Keying Material Exporters, Up: Advanced and other topics 7.10.4 Channel bindings ----------------------- In user authentication protocols (e.g., EAP or SASL mechanisms) it is useful to have a unique string that identifies the secure channel that is used, to bind together the user authentication with the secure channel. This can protect against man-in-the-middle attacks in some situations. That unique string is called a "channel binding". For background and discussion see [_RFC5056_]. In GnuTLS you can extract a channel binding using the *note gnutls_session_channel_binding:: function. Currently only the type 'GNUTLS_CB_TLS_UNIQUE' is supported, which corresponds to the 'tls-unique' channel binding for TLS defined in [_RFC5929_]. The following example describes how to print the channel binding data. Note that it must be run after a successful TLS handshake. { gnutls_datum_t cb; int rc; rc = gnutls_session_channel_binding (session, GNUTLS_CB_TLS_UNIQUE, &cb); if (rc) fprintf (stderr, "Channel binding error: %s\n", gnutls_strerror (rc)); else { size_t i; printf ("- Channel binding 'tls-unique': "); for (i = 0; i < cb.size; i++) printf ("%02x", cb.data[i]); printf ("\n"); } }  File: gnutls.info, Node: Interoperability, Next: Compatibility with the OpenSSL library, Prev: Channel Bindings, Up: Advanced and other topics 7.10.5 Interoperability ----------------------- The TLS protocols support many ciphersuites, extensions and version numbers. As a result, few implementations are not able to properly interoperate once faced with extensions or version protocols they do not support and understand. The TLS protocol allows for a graceful downgrade to the commonly supported options, but practice shows it is not always implemented correctly. Because there is no way to achieve maximum interoperability with broken peers without sacrificing security, GnuTLS ignores such peers by default. This might not be acceptable in cases where maximum compatibility is required. Thus we allow enabling compatibility with broken peers using priority strings (see *note Priority Strings::). A conservative priority string that would disable certain TLS protocol options that are known to cause compatibility problems, is shown below. NORMAL:%COMPAT For broken peers that do not tolerate TLS version numbers over TLS 1.0 another priority string is: NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0:+VERS-SSL3.0:%COMPAT This priority string will in addition to above, only enable SSL 3.0 and TLS 1.0 as protocols. Note however that there are known attacks against those protocol versions, especially over the CBC-mode ciphersuites. To mitigate them another priority string that only allows the stream cipher ARCFOUR is below. NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0:+VERS-SSL3.0:-CIPHER-ALL:+ARCFOUR-128:%COMPAT  File: gnutls.info, Node: Compatibility with the OpenSSL library, Prev: Interoperability, Up: Advanced and other topics 7.10.6 Compatibility with the OpenSSL library --------------------------------------------- To ease GnuTLS' integration with existing applications, a compatibility layer with the OpenSSL library is included in the 'gnutls-openssl' library. This compatibility layer is not complete and it is not intended to completely re-implement the OpenSSL API with GnuTLS. It only provides limited source-level compatibility. The prototypes for the compatibility functions are in the 'gnutls/openssl.h' header file. The limitations imposed by the compatibility layer include: * Error handling is not thread safe.  File: gnutls.info, Node: Using the cryptographic library, Next: Selecting cryptographic key sizes, Prev: Advanced and other topics, Up: How to use GnuTLS in applications 7.11 Using the cryptographic library ==================================== GnuTLS is not a low-level cryptographic library, i.e., it does not provide access to basic cryptographic primitives. However it abstracts the internal cryptographic back-end (see *note Cryptographic Backend::), providing symmetric crypto, hash and HMAC algorithms, as well access to the random number generation. * Menu: * Symmetric cryptography:: * Hash and HMAC functions:: * Random number generation::  File: gnutls.info, Node: Symmetric cryptography, Next: Hash and HMAC functions, Up: Using the cryptographic library 7.11.1 Symmetric cryptography ----------------------------- The available functions to access symmetric crypto algorithms operations are shown below. The supported algorithms are the algorithms required by the TLS protocol. They are listed in *note Table 3.1: tab:ciphers. 'INT *note gnutls_cipher_init:: (gnutls_cipher_hd_t * HANDLE, gnutls_cipher_algorithm_t CIPHER, const gnutls_datum_t * KEY, const gnutls_datum_t * IV)' 'INT *note gnutls_cipher_encrypt2:: (gnutls_cipher_hd_t HANDLE, const void * TEXT, size_t TEXTLEN, void * CIPHERTEXT, size_t CIPHERTEXTLEN)' 'INT *note gnutls_cipher_decrypt2:: (gnutls_cipher_hd_t HANDLE, const void * CIPHERTEXT, size_t CIPHERTEXTLEN, void * TEXT, size_t TEXTLEN)' 'VOID *note gnutls_cipher_set_iv:: (gnutls_cipher_hd_t HANDLE, void * IV, size_t IVLEN)' 'VOID *note gnutls_cipher_deinit:: (gnutls_cipher_hd_t HANDLE)' In order to support authenticated encryption with associated data (AEAD) algorithms the following functions are provided to set the associated data and retrieve the authentication tag. 'INT *note gnutls_cipher_add_auth:: (gnutls_cipher_hd_t HANDLE, const void * TEXT, size_t TEXT_SIZE)' 'INT *note gnutls_cipher_tag:: (gnutls_cipher_hd_t HANDLE, void * TAG, size_t TAG_SIZE)'  File: gnutls.info, Node: Hash and HMAC functions, Next: Random number generation, Prev: Symmetric cryptography, Up: Using the cryptographic library 7.11.2 Hash and HMAC functions ------------------------------ The available operations to access hash functions and hash-MAC (HMAC) algorithms are shown below. HMAC algorithms provided keyed hash functionality. They supported HMAC algorithms are listed in *note Table 3.2: tab:macs. 'INT *note gnutls_hmac_init:: (gnutls_hmac_hd_t * DIG, gnutls_mac_algorithm_t ALGORITHM, const void * KEY, size_t KEYLEN)' 'INT *note gnutls_hmac:: (gnutls_hmac_hd_t HANDLE, const void * TEXT, size_t TEXTLEN)' 'VOID *note gnutls_hmac_output:: (gnutls_hmac_hd_t HANDLE, void * DIGEST)' 'VOID *note gnutls_hmac_deinit:: (gnutls_hmac_hd_t HANDLE, void * DIGEST)' 'INT *note gnutls_hmac_get_len:: (gnutls_mac_algorithm_t ALGORITHM)' 'INT *note gnutls_hmac_fast:: (gnutls_mac_algorithm_t ALGORITHM, const void * KEY, size_t KEYLEN, const void * TEXT, size_t TEXTLEN, void * DIGEST)' The available functions to access hash functions are shown below. The supported hash functions are the same as the HMAC algorithms. 'INT *note gnutls_hash_init:: (gnutls_hash_hd_t * DIG, gnutls_digest_algorithm_t ALGORITHM)' 'INT *note gnutls_hash:: (gnutls_hash_hd_t HANDLE, const void * TEXT, size_t TEXTLEN)' 'VOID *note gnutls_hash_output:: (gnutls_hash_hd_t HANDLE, void * DIGEST)' 'VOID *note gnutls_hash_deinit:: (gnutls_hash_hd_t HANDLE, void * DIGEST)' 'INT *note gnutls_hash_get_len:: (gnutls_digest_algorithm_t ALGORITHM)' 'INT *note gnutls_hash_fast:: (gnutls_digest_algorithm_t ALGORITHM, const void * TEXT, size_t TEXTLEN, void * DIGEST)'  File: gnutls.info, Node: Random number generation, Prev: Hash and HMAC functions, Up: Using the cryptographic library 7.11.3 Random number generation ------------------------------- Access to the random number generator is provided using the *note gnutls_rnd:: function. It allows obtaining random data of various levels. 'GNUTLS_RND_NONCE' Non-predictable random number. Fatal in parts of session if broken, i.e., vulnerable to statistical analysis. 'GNUTLS_RND_RANDOM' Pseudo-random cryptographic random number. Fatal in session if broken. 'GNUTLS_RND_KEY' Fatal in many sessions if broken. Figure 7.2: The random number levels. -- Function: int gnutls_rnd (gnutls_rnd_level_t LEVEL, void * DATA, size_t LEN) LEVEL: a security level DATA: place to store random bytes LEN: The requested size This function will generate random data and store it to output buffer. *Returns:* Zero or a negative error code on error. *Since:* 2.12.0  File: gnutls.info, Node: Selecting cryptographic key sizes, Prev: Using the cryptographic library, Up: How to use GnuTLS in applications 7.12 Selecting cryptographic key sizes ====================================== Because many algorithms are involved in TLS, it is not easy to set a consistent security level. For this reason in *note Table 7.5: tab:key-sizes. we present some correspondence between key sizes of symmetric algorithms and public key algorithms based on [_ECRYPT_]. Those can be used to generate certificates with appropriate key sizes as well as select parameters for Diffie-Hellman and SRP authentication. SecurityRSA, DH ECC Security Description bits and SRP key parameter parameter size size ----------------------------------------------------------------- 80 1248 160 'LOW' Very short term protection against agencies 96 1776 192 'LEGACY' Legacy standard level 112 2432 224 'NORMAL' Medium-term protection 128 3248 256 'HIGH' Long term protection 256 15424 512 'ULTRA' Foreseeable future Table 7.5: Key sizes and security parameters. The first column provides a security parameter in a number of bits. This gives an indication of the number of combinations to be tried by an adversary to brute force a key. For example to test all possible keys in a 112 bit security parameter 2^{112} combinations have to be tried. For today's technology this is infeasible. The next two columns correlate the security parameter with actual bit sizes of parameters for DH, RSA, SRP and ECC algorithms. A mapping to 'gnutls_sec_param_t' value is given for each security parameter, on the next column, and finally a brief description of the level. Note, however, that the values suggested here are nothing more than an educated guess that is valid today. There are no guarantees that an algorithm will remain unbreakable or that these values will remain constant in time. There could be scientific breakthroughs that cannot be predicted or total failure of the current public key systems by quantum computers. On the other hand though the cryptosystems used in TLS are selected in a conservative way and such catastrophic breakthroughs or failures are believed to be unlikely. The NIST publication SP 800-57 [_NISTSP80057_] contains a similar table. When using GnuTLS and a decision on bit sizes for a public key algorithm is required, use of the following functions is recommended: -- Function: unsigned int gnutls_sec_param_to_pk_bits (gnutls_pk_algorithm_t ALGO, gnutls_sec_param_t PARAM) ALGO: is a public key algorithm PARAM: is a security parameter When generating private and public key pairs a difficult question is which size of "bits" the modulus will be in RSA and the group size in DSA. The easy answer is 1024, which is also wrong. This function will convert a human understandable security parameter to an appropriate size for the specific algorithm. *Returns:* The number of bits, or (0). *Since:* 2.12.0 -- Function: gnutls_sec_param_t gnutls_pk_bits_to_sec_param (gnutls_pk_algorithm_t ALGO, unsigned int BITS) ALGO: is a public key algorithm BITS: is the number of bits This is the inverse of 'gnutls_sec_param_to_pk_bits()' . Given an algorithm and the number of bits, it will return the security parameter. This is a rough indication. *Returns:* The security parameter. *Since:* 2.12.0 Those functions will convert a human understandable security parameter of 'gnutls_sec_param_t' type, to a number of bits suitable for a public key algorithm. The following functions will set the minimum acceptable group size for Diffie-Hellman and SRP authentication. 'VOID *note gnutls_dh_set_prime_bits:: (gnutls_session_t SESSION, unsigned int BITS)' 'VOID *note gnutls_srp_set_prime_bits:: (gnutls_session_t SESSION, unsigned int BITS)'  File: gnutls.info, Node: GnuTLS application examples, Next: Other included programs, Prev: How to use GnuTLS in applications, Up: Top 8 GnuTLS application examples ***************************** In this chapter several examples of real-world use cases are listed. The examples are simplified to promote readability and contain little or no error checking. * Menu: * Client examples:: * Server examples:: * OCSP example:: * Miscellaneous examples::  File: gnutls.info, Node: Client examples, Next: Server examples, Up: GnuTLS application examples 8.1 Client examples =================== This section contains examples of TLS and SSL clients, using GnuTLS. Note that some of the examples require functions implemented by another example. * Menu: * Simple client example with X.509 certificate support:: * Simple client example with SSH-style certificate verification:: * Simple client example with anonymous authentication:: * Simple Datagram TLS client example:: * Obtaining session information:: * Using a callback to select the certificate to use:: * Verifying a certificate:: * Client using a smart card with TLS:: * Client with Resume capability example:: * Simple client example with SRP authentication:: * Simple client example in C++:: * Helper functions for TCP connections:: * Helper functions for UDP connections::  File: gnutls.info, Node: Simple client example with X.509 certificate support, Next: Simple client example with SSH-style certificate verification, Up: Client examples 8.1.1 Simple client example with X.509 certificate support ---------------------------------------------------------- Let's assume now that we want to create a TCP client which communicates with servers that use X.509 or OpenPGP certificate authentication. The following client is a very simple TLS client, which uses the high level verification functions for certificates, but does not support session resumption. /* This example code is placed in the public domain. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include "examples.h" /* A very basic TLS client, with X.509 authentication and server certificate * verification. Note that error checking for missing files etc. is missing * for simplicity. */ #define MAX_BUF 1024 #define CAFILE "/etc/ssl/certs/ca-certificates.crt" #define MSG "GET / HTTP/1.0\r\n\r\n" extern int tcp_connect (void); extern void tcp_close (int sd); static int _verify_certificate_callback (gnutls_session_t session); int main (void) { int ret, sd, ii; gnutls_session_t session; char buffer[MAX_BUF + 1]; const char *err; gnutls_certificate_credentials_t xcred; gnutls_global_init (); /* X509 stuff */ gnutls_certificate_allocate_credentials (&xcred); /* sets the trusted cas file */ /* gnutls_certificate_set_x509_system_trust(xcred); */ gnutls_certificate_set_x509_trust_file (xcred, CAFILE, GNUTLS_X509_FMT_PEM); gnutls_certificate_set_verify_function (xcred, _verify_certificate_callback); /* If client holds a certificate it can be set using the following: * gnutls_certificate_set_x509_key_file (xcred, "cert.pem", "key.pem", GNUTLS_X509_FMT_PEM); */ /* Initialize TLS session */ gnutls_init (&session, GNUTLS_CLIENT); gnutls_session_set_ptr (session, (void *) "my_host_name"); gnutls_server_name_set (session, GNUTLS_NAME_DNS, "my_host_name", strlen("my_host_name")); /* Use default priorities */ ret = gnutls_priority_set_direct (session, "NORMAL", &err); if (ret < 0) { if (ret == GNUTLS_E_INVALID_REQUEST) { fprintf (stderr, "Syntax error at: %s\n", err); } exit (1); } /* put the x509 credentials to the current session */ gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); /* connect to the peer */ sd = tcp_connect (); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); /* Perform the TLS handshake */ do { ret = gnutls_handshake (session); } while (ret < 0 && gnutls_error_is_fatal (ret) == 0); if (ret < 0) { fprintf (stderr, "*** Handshake failed\n"); gnutls_perror (ret); goto end; } else { printf ("- Handshake was completed\n"); } gnutls_record_send (session, MSG, strlen (MSG)); ret = gnutls_record_recv (session, buffer, MAX_BUF); if (ret == 0) { printf ("- Peer has closed the TLS connection\n"); goto end; } else if (ret < 0) { fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret)); goto end; } printf ("- Received %d bytes: ", ret); for (ii = 0; ii < ret; ii++) { fputc (buffer[ii], stdout); } fputs ("\n", stdout); gnutls_bye (session, GNUTLS_SHUT_RDWR); end: tcp_close (sd); gnutls_deinit (session); gnutls_certificate_free_credentials (xcred); gnutls_global_deinit (); return 0; } /* This function will verify the peer's certificate, and check * if the hostname matches, as well as the activation, expiration dates. */ static int _verify_certificate_callback (gnutls_session_t session) { unsigned int status; const gnutls_datum_t *cert_list; unsigned int cert_list_size; int ret; gnutls_x509_crt_t cert; const char *hostname; /* read hostname */ hostname = gnutls_session_get_ptr (session); /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ ret = gnutls_certificate_verify_peers2 (session, &status); if (ret < 0) { printf ("Error\n"); return GNUTLS_E_CERTIFICATE_ERROR; } if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) printf ("The certificate hasn't got a known issuer.\n"); if (status & GNUTLS_CERT_REVOKED) printf ("The certificate has been revoked.\n"); if (status & GNUTLS_CERT_EXPIRED) printf ("The certificate has expired\n"); if (status & GNUTLS_CERT_NOT_ACTIVATED) printf ("The certificate is not yet activated\n"); if (status & GNUTLS_CERT_INVALID) { printf ("The certificate is not trusted.\n"); return GNUTLS_E_CERTIFICATE_ERROR; } /* Up to here the process is the same for X.509 certificates and * OpenPGP keys. From now on X.509 certificates are assumed. This can * be easily extended to work with openpgp keys as well. */ if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) return GNUTLS_E_CERTIFICATE_ERROR; if (gnutls_x509_crt_init (&cert) < 0) { printf ("error in initialization\n"); return GNUTLS_E_CERTIFICATE_ERROR; } cert_list = gnutls_certificate_get_peers (session, &cert_list_size); if (cert_list == NULL) { printf ("No certificate was found!\n"); return GNUTLS_E_CERTIFICATE_ERROR; } if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) { printf ("error parsing certificate\n"); return GNUTLS_E_CERTIFICATE_ERROR; } if (!gnutls_x509_crt_check_hostname (cert, hostname)) { printf ("The certificate's owner does not match hostname '%s'\n", hostname); return GNUTLS_E_CERTIFICATE_ERROR; } gnutls_x509_crt_deinit (cert); /* notify gnutls to continue handshake normally */ return 0; }  File: gnutls.info, Node: Simple client example with SSH-style certificate verification, Next: Simple client example with anonymous authentication, Prev: Simple client example with X.509 certificate support, Up: Client examples 8.1.2 Simple client example with SSH-style certificate verification ------------------------------------------------------------------- This is an alternative verification function that will use the X.509 certificate authorities for verification, but also assume an trust on first use (SSH-like) authentication system. That is the user is prompted on unknown public keys and known public keys are considered trusted. /* This example code is placed in the public domain. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include "examples.h" /* This function will verify the peer's certificate, check * if the hostname matches. In addition it will perform an * SSH-style authentication, where ultimately trusted keys * are only the keys that have been seen before. */ int _ssh_verify_certificate_callback (gnutls_session_t session) { unsigned int status; const gnutls_datum_t *cert_list; unsigned int cert_list_size; int ret; gnutls_x509_crt_t cert; const char *hostname; /* read hostname */ hostname = gnutls_session_get_ptr (session); /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ ret = gnutls_certificate_verify_peers2 (session, &status); if (ret < 0) { printf ("Error\n"); return GNUTLS_E_CERTIFICATE_ERROR; } if (status & GNUTLS_CERT_INVALID) printf ("The certificate is not trusted.\n"); if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) printf ("The certificate hasn't got a known issuer.\n"); if (status & GNUTLS_CERT_REVOKED) printf ("The certificate has been revoked.\n"); if (status & GNUTLS_CERT_EXPIRED) printf ("The certificate has expired\n"); if (status & GNUTLS_CERT_NOT_ACTIVATED) printf ("The certificate is not yet activated\n"); /* Up to here the process is the same for X.509 certificates and * OpenPGP keys. From now on X.509 certificates are assumed. This can * be easily extended to work with openpgp keys as well. */ if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) return GNUTLS_E_CERTIFICATE_ERROR; if (gnutls_x509_crt_init (&cert) < 0) { printf ("error in initialization\n"); return GNUTLS_E_CERTIFICATE_ERROR; } cert_list = gnutls_certificate_get_peers (session, &cert_list_size); if (cert_list == NULL) { printf ("No certificate was found!\n"); return GNUTLS_E_CERTIFICATE_ERROR; } /* This is not a real world example, since we only check the first * certificate in the given chain. */ if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) { printf ("error parsing certificate\n"); return GNUTLS_E_CERTIFICATE_ERROR; } if (!gnutls_x509_crt_check_hostname (cert, hostname)) { printf ("The certificate's owner does not match hostname '%s'\n", hostname); status |= GNUTLS_CERT_INVALID; } gnutls_x509_crt_deinit (cert); /* service may be obtained alternatively using getservbyport() */ ret = gnutls_verify_stored_pubkey(NULL, NULL, hostname, "https", GNUTLS_CRT_X509, &cert_list[0], 0); if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND) { printf("Host %s is not known.", hostname); if (status == 0) printf("Its certificate is valid for %s.\n", hostname); /* the certificate must be printed and user must be asked on * whether it is trustworthy. --see gnutls_x509_crt_print() */ /* if not trusted */ return GNUTLS_E_CERTIFICATE_ERROR; } else if (ret == GNUTLS_E_CERTIFICATE_KEY_MISMATCH) { printf("Warning: host %s is known but has another key associated.", hostname); printf("It might be that the server has multiple keys, or you are under attack\n"); if (status == 0) printf("Its certificate is valid for %s.\n", hostname); /* the certificate must be printed and user must be asked on * whether it is trustworthy. --see gnutls_x509_crt_print() */ /* if not trusted */ return GNUTLS_E_CERTIFICATE_ERROR; } else if (ret < 0) { printf("gnutls_verify_stored_pubkey: %s\n", gnutls_strerror(ret)); return ret; } /* user trusts the key -> store it */ if (ret != 0) { ret = gnutls_store_pubkey(NULL, NULL, hostname, "https", GNUTLS_CRT_X509, &cert_list[0], 0, 0); if (ret < 0) printf("gnutls_store_pubkey: %s\n", gnutls_strerror(ret)); } /* notify gnutls to continue handshake normally */ return 0; }