diff options
Diffstat (limited to 'doc/examples/ex-cert-select-pkcs11.c')
-rw-r--r-- | doc/examples/ex-cert-select-pkcs11.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/doc/examples/ex-cert-select-pkcs11.c b/doc/examples/ex-cert-select-pkcs11.c new file mode 100644 index 0000000..2923a47 --- /dev/null +++ b/doc/examples/ex-cert-select-pkcs11.c @@ -0,0 +1,175 @@ +/* This example code is placed in the public domain. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <gnutls/gnutls.h> +#include <gnutls/x509.h> +#include <gnutls/pkcs11.h> +#include <assert.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <getpass.h> /* for getpass() */ + +/* A TLS client that loads the certificate and key. + */ + +#define CHECK(x) assert((x)>=0) + +#define MAX_BUF 1024 +#define MSG "GET / HTTP/1.0\r\n\r\n" +#define MIN(x,y) (((x)<(y))?(x):(y)) + +#define CAFILE "/etc/ssl/certs/ca-certificates.crt" + +/* The URLs of the objects can be obtained + * using p11tool --list-all --login + */ +#define KEY_URL "pkcs11:manufacturer=SomeManufacturer;object=Private%20Key" \ + ";objecttype=private;id=%db%5b%3e%b5%72%33" +#define CERT_URL "pkcs11:manufacturer=SomeManufacturer;object=Certificate;" \ + "objecttype=cert;id=db%5b%3e%b5%72%33" + +extern int tcp_connect(void); +extern void tcp_close(int sd); + +static int +pin_callback(void *user, int attempt, const char *token_url, + const char *token_label, unsigned int flags, char *pin, + size_t pin_max) +{ + const char *password; + int len; + + printf("PIN required for token '%s' with URL '%s'\n", token_label, + token_url); + if (flags & GNUTLS_PIN_FINAL_TRY) + printf("*** This is the final try before locking!\n"); + if (flags & GNUTLS_PIN_COUNT_LOW) + printf("*** Only few tries left before locking!\n"); + if (flags & GNUTLS_PIN_WRONG) + printf("*** Wrong PIN\n"); + + password = getpass("Enter pin: "); + /* FIXME: ensure that we are in UTF-8 locale */ + if (password == NULL || password[0] == 0) { + fprintf(stderr, "No password given\n"); + exit(1); + } + + len = MIN(pin_max - 1, strlen(password)); + memcpy(pin, password, len); + pin[len] = 0; + + return 0; +} + +int main(void) +{ + int ret, sd, ii; + gnutls_session_t session; + char buffer[MAX_BUF + 1]; + gnutls_certificate_credentials_t xcred; + /* Allow connections to servers that have OpenPGP keys as well. + */ + + if (gnutls_check_version("3.1.4") == NULL) { + fprintf(stderr, "GnuTLS 3.1.4 or later is required for this example\n"); + exit(1); + } + + /* for backwards compatibility with gnutls < 3.3.0 */ + CHECK(gnutls_global_init()); + + /* The PKCS11 private key operations may require PIN. + * Register a callback. */ + gnutls_pkcs11_set_pin_function(pin_callback, NULL); + + /* X509 stuff */ + CHECK(gnutls_certificate_allocate_credentials(&xcred)); + + /* sets the trusted cas file + */ + CHECK(gnutls_certificate_set_x509_trust_file(xcred, CAFILE, + GNUTLS_X509_FMT_PEM)); + + CHECK(gnutls_certificate_set_x509_key_file(xcred, CERT_URL, KEY_URL, + GNUTLS_X509_FMT_DER)); + + /* Note that there is no server certificate verification in this example + */ + + + /* Initialize TLS session + */ + CHECK(gnutls_init(&session, GNUTLS_CLIENT)); + + /* Use default priorities */ + CHECK(gnutls_set_default_priority(session)); + + /* put the x509 credentials to the current session + */ + CHECK(gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred)); + + /* connect to the peer + */ + sd = tcp_connect(); + + gnutls_transport_set_int(session, sd); + + /* Perform the TLS handshake + */ + ret = gnutls_handshake(session); + + if (ret < 0) { + fprintf(stderr, "*** Handshake failed\n"); + gnutls_perror(ret); + goto end; + } else { + char *desc; + + desc = gnutls_session_get_desc(session); + printf("- Session info: %s\n", desc); + gnutls_free(desc); + } + + CHECK(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); + + CHECK(gnutls_bye(session, GNUTLS_SHUT_RDWR)); + + end: + + tcp_close(sd); + + gnutls_deinit(session); + + gnutls_certificate_free_credentials(xcred); + + gnutls_global_deinit(); + + return 0; +} |