bool Plugin::onLoad(LightBird::IApi *api) { int error; const char *err_pos = NULL; this->api = api; try { ASSERT_INIT(gnutls_global_init(), "global"); if (!gnutls_check_version(GNUTLS_CHECK_VERSION)) throw Properties("error", "Bad GnuTLS version").add("version required", GNUTLS_CHECK_VERSION); gnutls_global_set_audit_log_function(Plugin::log); this->_loadConfiguration(); this->_loadPrivateKey(); this->_loadCertificate(); this->_loadDHParams(); ASSERT_INIT(gnutls_certificate_allocate_credentials(&this->x509_cred), "credentials"); ASSERT(gnutls_certificate_set_x509_key(this->x509_cred, &this->crt, 1, this->key)); ASSERT_INIT(gnutls_priority_init(&this->priority, this->priorityStrings.data(), &err_pos), "priority"); gnutls_certificate_set_dh_params(this->x509_cred, this->dhParams); } catch (Properties p) { if (err_pos) p.add("error position", err_pos).add("priority string", this->priorityStrings); LOG_FATAL("Unable to initialize GnuTLS", p.toMap(), "Plugin", "onLoad"); this->_deinit(); return (false); } this->api->contexts().declareInstance("handshake", (this->handshake = new Handshake(this->api, this->handshakeTimeout))); this->api->contexts().declareInstance("record", (this->record = new Record(this->api))); return (true); }
int tls_certificates_load(gnutls_x509_privkey key, const char *certfname, gnutls_certificate_credentials cred) { int ret; size_t size; gnutls_datum certfile; unsigned int cert_max, i; gnutls_x509_crt certs[1024]; ret = _requiem_load_file(certfname, &certfile.data, &size); if ( ret < 0 ) return ret; certfile.size = (unsigned int) size; cert_max = sizeof(certs) / sizeof(*certs); ret = _requiem_tls_crt_list_import(certs, &cert_max, &certfile, GNUTLS_X509_FMT_PEM); if ( ret < 0 ) { ret = requiem_error_verbose(REQUIEM_ERROR_PROFILE, "error importing certificate listing: %s", gnutls_strerror(ret)); goto err; } for ( i = 0; i < cert_max; i++) { ret = gnutls_certificate_set_x509_key(cred, &certs[i], 1, key); gnutls_x509_crt_deinit(certs[i]); if ( ret < 0 ) { ret = requiem_error_verbose(REQUIEM_ERROR_PROFILE, "error importing certificate: %s", gnutls_strerror(ret)); break; } } err: _requiem_unload_file(certfile.data, certfile.size); return ret; }
void certificate_credentials::set_x509_key (gnutls_x509_crt_t * cert_list, int cert_list_size, gnutls_x509_privkey_t key) { RETWRAP (gnutls_certificate_set_x509_key (cred, cert_list, cert_list_size, key)); }
static gboolean infinoted_startup_load_credentials(InfinotedStartup* startup, GError** error) { gnutls_x509_crt_t* certs; guint n_certs; gnutls_certificate_credentials_t creds; int res; if(startup->options->security_policy != INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED) { startup->private_key = infinoted_startup_load_key( startup->log, startup->options->create_key, startup->options->key_file, error ); if(startup->private_key == NULL) return FALSE; certs = infinoted_startup_load_certificate( startup->log, startup->options->create_certificate, startup->private_key, startup->options->certificate_file, startup->options->certificate_chain_file, &n_certs, error ); if(certs == NULL) return FALSE; /* Takes ownership of certificates: */ startup->certificates = inf_certificate_chain_new(certs, n_certs); startup->credentials = inf_certificate_credentials_new(); creds = inf_certificate_credentials_get(startup->credentials); res = gnutls_certificate_set_x509_key( creds, inf_certificate_chain_get_raw(startup->certificates), inf_certificate_chain_get_n_certificates(startup->certificates), startup->private_key ); if(res != 0) { inf_gnutls_set_error(error, res); return FALSE; } } return TRUE; }
int ufwissl_ssl_context_keypair_from_data(ufwissl_ssl_context * ctx, ufwissl_ssl_client_cert * cert) { int ret; ret = gnutls_certificate_set_x509_key(ctx->cred, &cert->cert.subject, 1, cert->pkey); if (ret != 0) return UFWISSL_ERROR; gnutls_certificate_set_dh_params(ctx->cred, ctx->dh); return (ret == 0) ? UFWISSL_OK : UFWISSL_ERROR; }
static int import_key(gnutls_certificate_credentials_t xcred, const gnutls_datum_t *skey, const gnutls_datum_t *cert) { gnutls_x509_privkey_t key; gnutls_x509_crt_t *crt_list; unsigned crt_list_size, idx, i; gnutls_datum_t tcert; int ret; assert(gnutls_x509_privkey_init(&key)>=0); ret = gnutls_x509_crt_list_import2(&crt_list, &crt_list_size, cert, GNUTLS_X509_FMT_PEM, 0); if (ret < 0) { fail("error in gnutls_x509_crt_list_import2: %s\n", gnutls_strerror(ret)); } ret = gnutls_x509_privkey_import(key, skey, GNUTLS_X509_FMT_PEM); if (ret < 0) { fail("error in key import: %s\n", gnutls_strerror(ret)); } ret = gnutls_certificate_set_x509_key(xcred, crt_list, crt_list_size, key); if (ret < 0) { success("error in gnutls_certificate_set_x509_key: %s\n", gnutls_strerror(ret)); idx = ret; goto cleanup; } /* return index */ idx = ret; /* verify whether the stored certificate match the ones we have */ for (i=0;i<MIN(2, crt_list_size);i++) { ret = gnutls_certificate_get_crt_raw(xcred, idx, i, &tcert); if (ret < 0) { fail("error in %d: cert: %d: %s\n", __LINE__, i, gnutls_strerror(ret)); exit(1); } compare(&tcert, cert->data+i); } cleanup: gnutls_x509_privkey_deinit(key); for (i=0;i<crt_list_size;i++) { gnutls_x509_crt_deinit(crt_list[i]); } gnutls_free(crt_list); return idx; }
void Gobby::CertificateManager::make_credentials() { InfCertificateCredentials* creds = inf_certificate_credentials_new(); gnutls_certificate_credentials_t gnutls_creds = inf_certificate_credentials_get(creds); if(m_preferences.security.authentication_enabled && m_key != NULL && m_certificates != NULL) { gnutls_certificate_set_x509_key( gnutls_creds, inf_certificate_chain_get_raw(m_certificates), inf_certificate_chain_get_n_certificates(m_certificates), m_key ); } if(m_preferences.security.use_system_trust) { const int n_cas = gnutls_certificate_set_x509_system_trust( gnutls_creds); if(n_cas < 0) { g_warning("Failed to add system CAs: %s\n", gnutls_strerror(n_cas)); } } if(!m_trust.empty()) { gnutls_certificate_set_x509_trust( gnutls_creds, &m_trust[0], m_trust.size() ); } if(m_dh_params != NULL) gnutls_certificate_set_dh_params(gnutls_creds, m_dh_params); gnutls_certificate_set_verify_flags( gnutls_creds, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); InfCertificateCredentials* old_creds = m_credentials; m_credentials = creds; m_signal_credentials_changed.emit(); if(old_creds != NULL) inf_certificate_credentials_unref(old_creds); }
X509Credentials(const std::string& certstr, const std::string& keystr) : key(keystr) , certs(certstr) { // Throwing is ok here, the destructor of Credentials is called in that case int ret = gnutls_certificate_set_x509_key(cred, certs.raw(), certs.size(), key.get()); ThrowOnError(ret, "Unable to set cert/key pair"); #ifdef GNUTLS_NEW_CERT_CALLBACK_API gnutls_certificate_set_retrieve_function(cred, cert_callback); #else gnutls_certificate_client_set_retrieve_function(cred, cert_callback); #endif }
static void test_success2(const char *name, const char *prio) { int ret; /* Server stuff. */ gnutls_certificate_credentials_t serverx509cred; gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_session_t client; int cret = GNUTLS_E_AGAIN; gnutls_x509_crt_t *crts; unsigned int crts_size; unsigned i; gnutls_x509_privkey_t pkey; unsigned status; success("testing cert verification success2 for %s\n", name); to_server_len = 0; to_client_len = 0; ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &server_cert, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_privkey_init(&pkey); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_privkey_import(pkey, &server_key, GNUTLS_X509_FMT_PEM); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } /* Init server */ gnutls_certificate_allocate_credentials(&serverx509cred); gnutls_certificate_set_x509_key(serverx509cred, crts, crts_size, pkey); gnutls_x509_privkey_deinit(pkey); for (i=0;i<crts_size;i++) gnutls_x509_crt_deinit(crts[i]); gnutls_free(crts); gnutls_init(&server, GNUTLS_SERVER); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred); assert(gnutls_priority_set_direct(server, prio, NULL)>=0); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_ptr(server, server); gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST); /* Init client */ /* Init client */ ret = gnutls_certificate_allocate_credentials(&clientx509cred); if (ret < 0) exit(1); ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) exit(1); ret = gnutls_certificate_set_x509_key_mem(clientx509cred, &cli_cert, &cli_key, GNUTLS_X509_FMT_PEM); ret = gnutls_init(&client, GNUTLS_CLIENT); if (ret < 0) exit(1); ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred); if (ret < 0) exit(1); assert(gnutls_priority_set_direct(client, prio, NULL)>=0); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_ptr(client, client); gnutls_session_set_verify_cert(client, "localhost", 0); HANDSHAKE(client, server); status = gnutls_session_get_verify_cert_status(client); if (status != 0) { fail("%s: should have accepted: %u!\n", __func__, status); exit(1); } gnutls_deinit(client); gnutls_deinit(server); gnutls_certificate_free_credentials(serverx509cred); gnutls_certificate_free_credentials(clientx509cred); }
static void test_failure(const char *name, const char *prio) { int ret; /* Server stuff. */ gnutls_certificate_credentials_t serverx509cred; gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_session_t client; int cret = GNUTLS_E_AGAIN; gnutls_x509_crt_t *crts; unsigned int crts_size; unsigned i; gnutls_typed_vdata_st vdata[2]; gnutls_x509_privkey_t pkey; unsigned status; success("testing cert verification failure for %s\n", name); to_server_len = 0; to_client_len = 0; ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &server_cert, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_privkey_init(&pkey); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_privkey_import(pkey, &server_key, GNUTLS_X509_FMT_PEM); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } /* Init server */ gnutls_certificate_allocate_credentials(&serverx509cred); gnutls_certificate_set_x509_key(serverx509cred, crts, crts_size, pkey); gnutls_x509_privkey_deinit(pkey); for (i=0;i<crts_size;i++) gnutls_x509_crt_deinit(crts[i]); gnutls_free(crts); gnutls_init(&server, GNUTLS_SERVER); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred); assert(gnutls_priority_set_direct(server, prio, NULL) >= 0); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_ptr(server, server); gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST); /* Init client */ /* Init client */ ret = gnutls_certificate_allocate_credentials(&clientx509cred); if (ret < 0) exit(1); ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) exit(1); ret = gnutls_certificate_set_x509_key_mem(clientx509cred, &cli_cert, &cli_key, GNUTLS_X509_FMT_PEM); ret = gnutls_init(&client, GNUTLS_CLIENT); if (ret < 0) exit(1); ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred); if (ret < 0) exit(1); assert(gnutls_priority_set_direct(client, prio, NULL) >= 0); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_ptr(client, client); memset(vdata, 0, sizeof(vdata)); /* check with wrong hostname */ vdata[0].type = GNUTLS_DT_DNS_HOSTNAME; vdata[0].data = (void*)"localhost1"; vdata[1].type = GNUTLS_DT_KEY_PURPOSE_OID; vdata[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER; gnutls_session_set_verify_cert2(client, vdata, 2, 0); HANDSHAKE_EXPECT(client, server, GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR, GNUTLS_E_AGAIN); status = gnutls_session_get_verify_cert_status(client); if (status == 0) { fail("should not have accepted!\n"); exit(1); } gnutls_deinit(client); gnutls_deinit(server); gnutls_certificate_free_credentials(serverx509cred); gnutls_certificate_free_credentials(clientx509cred); }
static InfdXmppServer* inf_test_certificate_setup_server(InfIo* io, const char* key_file, const char* cert_file, GError** error) { InfdTcpServer* tcp; InfdXmppServer* xmpp; gnutls_x509_privkey_t key; GPtrArray* certs; InfCertificateCredentials* creds; guint i; int res; key = inf_cert_util_read_private_key(key_file, error); if(!key) return NULL; certs = inf_cert_util_read_certificate(cert_file, NULL, error); if(!certs) { gnutls_x509_privkey_deinit(key); return NULL; } creds = inf_certificate_credentials_new(); res = gnutls_certificate_set_x509_key( inf_certificate_credentials_get(creds), (gnutls_x509_crt_t*)certs->pdata, certs->len, key ); gnutls_x509_privkey_deinit(key); for(i = 0; i < certs->len; ++i) gnutls_x509_crt_deinit(certs->pdata[i]); g_ptr_array_free(certs, TRUE); if(res != 0) { inf_certificate_credentials_unref(creds); inf_gnutls_set_error(error, res); return NULL; } tcp = g_object_new( INFD_TYPE_TCP_SERVER, "io", io, "local-port", 6524, NULL ); if(infd_tcp_server_open(tcp, error) == FALSE) { inf_certificate_credentials_unref(creds); return NULL; } xmpp = infd_xmpp_server_new( tcp, INF_XMPP_CONNECTION_SECURITY_ONLY_TLS, creds, NULL, NULL ); /* Keep client connections alive */ g_signal_connect( G_OBJECT(xmpp), "new-connection", G_CALLBACK(inf_test_certificate_validate_new_connection_cb), NULL ); inf_certificate_credentials_unref(creds); return xmpp; }
/* * initialize a new TLS context */ static int tlsg_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) { tlsg_ctx *ctx = lo->ldo_tls_ctx; int rc; if ( lo->ldo_tls_ciphersuite && tlsg_parse_ciphers( ctx, lt->lt_ciphersuite )) { Debug( LDAP_DEBUG_ANY, "TLS: could not set cipher list %s.\n", lo->ldo_tls_ciphersuite, 0, 0 ); return -1; } if (lo->ldo_tls_cacertdir != NULL) { Debug( LDAP_DEBUG_ANY, "TLS: warning: cacertdir not implemented for gnutls\n", NULL, NULL, NULL ); } if (lo->ldo_tls_cacertfile != NULL) { rc = gnutls_certificate_set_x509_trust_file( ctx->cred, lt->lt_cacertfile, GNUTLS_X509_FMT_PEM ); if ( rc < 0 ) return -1; } if ( lo->ldo_tls_certfile && lo->ldo_tls_keyfile ) { gnutls_x509_privkey_t key; gnutls_datum_t buf; gnutls_x509_crt_t certs[VERIFY_DEPTH]; unsigned int max = VERIFY_DEPTH; rc = gnutls_x509_privkey_init( &key ); if ( rc ) return -1; /* OpenSSL builds the cert chain for us, but GnuTLS * expects it to be present in the certfile. If it's * not, we have to build it ourselves. So we have to * do some special checks here... */ rc = tlsg_getfile( lt->lt_keyfile, &buf ); if ( rc ) return -1; rc = gnutls_x509_privkey_import( key, &buf, GNUTLS_X509_FMT_PEM ); LDAP_FREE( buf.data ); if ( rc < 0 ) return rc; rc = tlsg_getfile( lt->lt_certfile, &buf ); if ( rc ) return -1; rc = gnutls_x509_crt_list_import( certs, &max, &buf, GNUTLS_X509_FMT_PEM, 0 ); LDAP_FREE( buf.data ); if ( rc < 0 ) return rc; /* If there's only one cert and it's not self-signed, * then we have to build the cert chain. */ if ( max == 1 && !gnutls_x509_crt_check_issuer( certs[0], certs[0] )) { gnutls_x509_crt_t *cas; unsigned int i, j, ncas; gnutls_certificate_get_x509_cas( ctx->cred, &cas, &ncas ); for ( i = 1; i<VERIFY_DEPTH; i++ ) { for ( j = 0; j<ncas; j++ ) { if ( gnutls_x509_crt_check_issuer( certs[i-1], cas[j] )) { certs[i] = cas[j]; max++; /* If this CA is self-signed, we're done */ if ( gnutls_x509_crt_check_issuer( cas[j], cas[j] )) j = ncas; break; } } /* only continue if we found a CA and it was not self-signed */ if ( j == ncas ) break; } } rc = gnutls_certificate_set_x509_key( ctx->cred, certs, max, key ); if ( rc ) return -1; } else if ( lo->ldo_tls_certfile || lo->ldo_tls_keyfile ) { Debug( LDAP_DEBUG_ANY, "TLS: only one of certfile and keyfile specified\n", NULL, NULL, NULL ); return -1; } if ( lo->ldo_tls_dhfile ) { Debug( LDAP_DEBUG_ANY, "TLS: warning: ignoring dhfile\n", NULL, NULL, NULL ); } if ( lo->ldo_tls_crlfile ) { rc = gnutls_certificate_set_x509_crl_file( ctx->cred, lt->lt_crlfile, GNUTLS_X509_FMT_PEM ); if ( rc < 0 ) return -1; rc = 0; } /* FIXME: ITS#5992 - this should go be configurable, * and V1 CA certs should be phased out ASAP. */ gnutls_certificate_set_verify_flags( ctx->cred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT ); if ( is_server ) { gnutls_dh_params_init(&ctx->dh_params); gnutls_dh_params_generate2(ctx->dh_params, DH_BITS); } return 0; }
void doit(void) { int exit_code = EXIT_SUCCESS; int ret; /* Server stuff. */ gnutls_certificate_credentials_t serverx509cred; gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_session_t client; int cret = GNUTLS_E_AGAIN; gnutls_x509_crt_t *crts; unsigned int crts_size; unsigned i; gnutls_x509_privkey_t pkey; /* General init. */ global_init(); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(2); ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &server_cert, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_privkey_init(&pkey); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_privkey_import(pkey, &server_key, GNUTLS_X509_FMT_PEM); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } /* Init server */ gnutls_certificate_allocate_credentials(&serverx509cred); gnutls_certificate_set_x509_key(serverx509cred, crts, crts_size, pkey); gnutls_x509_privkey_deinit(pkey); for (i=0;i<crts_size;i++) gnutls_x509_crt_deinit(crts[i]); gnutls_free(crts); gnutls_init(&server, GNUTLS_SERVER); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred); gnutls_priority_set_direct(server, "NORMAL:-CIPHER-ALL:+AES-128-GCM", NULL); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_ptr(server, server); gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST); /* Init client */ /* Init client */ ret = gnutls_certificate_allocate_credentials(&clientx509cred); if (ret < 0) exit(1); ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) exit(1); gnutls_certificate_set_retrieve_function2(clientx509cred, cert_callback); ret = gnutls_init(&client, GNUTLS_CLIENT); if (ret < 0) exit(1); ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred); if (ret < 0) exit(1); gnutls_priority_set_direct(client, "NORMAL", NULL); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_ptr(client, client); HANDSHAKE(client, server); if (gnutls_certificate_get_ours(client) == NULL) { fail("client certificate was not sent!\n"); exit(1); } /* check gnutls_certificate_get_ours() - server side */ { const gnutls_datum_t *mcert; gnutls_datum_t scert; gnutls_x509_crt_t crt; mcert = gnutls_certificate_get_ours(server); if (mcert == NULL) { fail("gnutls_certificate_get_ours(): failed\n"); exit(1); } gnutls_x509_crt_init(&crt); ret = gnutls_x509_crt_import(crt, &server_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) { fail("gnutls_x509_crt_import: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &scert); if (ret < 0) { fail("gnutls_x509_crt_export2: %s\n", gnutls_strerror(ret)); exit(1); } gnutls_x509_crt_deinit(crt); if (scert.size != mcert->size || memcmp(scert.data, mcert->data, mcert->size) != 0) { fail("gnutls_certificate_get_ours output doesn't match cert\n"); exit(1); } gnutls_free(scert.data); } /* check gnutls_certificate_get_ours() - client side */ { const gnutls_datum_t *mcert; gnutls_datum_t ccert; gnutls_x509_crt_t crt; mcert = gnutls_certificate_get_ours(client); if (mcert == NULL) { fail("gnutls_certificate_get_ours(): failed\n"); exit(1); } gnutls_x509_crt_init(&crt); ret = gnutls_x509_crt_import(crt, &cli_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) { fail("gnutls_x509_crt_import: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &ccert); if (ret < 0) { fail("gnutls_x509_crt_export2: %s\n", gnutls_strerror(ret)); exit(1); } gnutls_x509_crt_deinit(crt); if (ccert.size != mcert->size || memcmp(ccert.data, mcert->data, mcert->size) != 0) { fail("gnutls_certificate_get_ours output doesn't match cert\n"); exit(1); } gnutls_free(ccert.data); } /* check the number of certificates received */ { unsigned cert_list_size = 0; gnutls_typed_vdata_st data[2]; unsigned status; memset(data, 0, sizeof(data)); /* check with wrong hostname */ data[0].type = GNUTLS_DT_DNS_HOSTNAME; data[0].data = (void*)"localhost1"; data[1].type = GNUTLS_DT_KEY_PURPOSE_OID; data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER; gnutls_certificate_get_peers(client, &cert_list_size); if (cert_list_size < 2) { fprintf(stderr, "received a certificate list of %d!\n", cert_list_size); exit(1); } ret = gnutls_certificate_verify_peers(client, data, 2, &status); if (ret < 0) { fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (status == 0) { fprintf(stderr, "should not have accepted!\n"); exit(1); } /* check with wrong purpose */ data[0].type = GNUTLS_DT_DNS_HOSTNAME; data[0].data = (void*)"localhost"; data[1].type = GNUTLS_DT_KEY_PURPOSE_OID; data[1].data = (void*)GNUTLS_KP_TLS_WWW_CLIENT; gnutls_certificate_get_peers(client, &cert_list_size); if (cert_list_size < 2) { fprintf(stderr, "received a certificate list of %d!\n", cert_list_size); exit(1); } ret = gnutls_certificate_verify_peers(client, data, 2, &status); if (ret < 0) { fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (status == 0) { fprintf(stderr, "should not have accepted!\n"); exit(1); } /* check with correct purpose */ data[0].type = GNUTLS_DT_DNS_HOSTNAME; data[0].data = (void*)"localhost"; data[1].type = GNUTLS_DT_KEY_PURPOSE_OID; data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER; ret = gnutls_certificate_verify_peers(client, data, 2, &status); if (ret < 0) { fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (status != 0) { fprintf(stderr, "could not verify certificate: %.4x\n", status); exit(1); } } if (gnutls_certificate_client_get_request_status(client) == 0) { fail("gnutls_certificate_client_get_request_status - 2 failed\n"); exit(1); } gnutls_bye(client, GNUTLS_SHUT_RDWR); gnutls_bye(server, GNUTLS_SHUT_RDWR); gnutls_deinit(client); gnutls_deinit(server); gnutls_certificate_free_credentials(serverx509cred); gnutls_certificate_free_credentials(clientx509cred); gnutls_global_deinit(); if (debug > 0) { if (exit_code == 0) puts("Self-test successful"); else puts("Self-test failed"); } }
bool load_p12(gnutls_certificate_credentials_t xcred, const char *const p12_file, const char *const password) { FILE*p12file; gnutls_datum_t p12blob; gnutls_pkcs12_t p12 = NULL; gnutls_x509_privkey_t key = NULL; gnutls_x509_crt_t certs[MAX_CERTS]; int certs_nr; int id_cert; uint8_t key_id[20]; size_t key_id_size; bool is_success = false; int ret; int i; assert(p12_file != NULL); /* Read file */ p12file = fopen(p12_file, "rb"); if(p12file == NULL) { trace(LOG_ERR, "failed to open PKCS#12 file '%s': %s (%d)", p12_file, strerror(errno), errno); ret = GNUTLS_E_FILE_ERROR; goto error; } p12blob.data = malloc(32768 * sizeof(char)); p12blob.size = fread((void*) p12blob.data, sizeof(char), 32768, p12file); fclose(p12file); /* Init structure and import P12 */ ret = gnutls_pkcs12_init(&p12); if(ret < 0) { trace(LOG_ERR, "failed to init PKCS#12 object (%d)", ret); goto free_blob; } ret = gnutls_pkcs12_import(p12, &p12blob, GNUTLS_X509_FMT_DER, 0); if(ret < 0) { trace(LOG_ERR, "failed to import PKCS#12 data (%d)", ret); goto deinit_pkcs12; } if(password) { ret = gnutls_pkcs12_verify_mac(p12, password); if(ret < 0) { trace(LOG_ERR, "failed to verify PKCS#12 MAC (%d)", ret); goto deinit_pkcs12; } } /* extract the private key and the certificates from PKCS#12 */ if(!tls_parse_pkcs12(&p12, password, &key, certs, &certs_nr)) { trace(LOG_ERR, "failed to parse PKCS#12 file '%s'", p12_file); goto deinit_pkcs12; } if(certs_nr < 2) { trace(LOG_ERR, "too few certificates in PKCS#12 file '%s'", p12_file); goto free_certs_key; } /* get the ID of private key */ key_id_size = sizeof(key_id); ret = gnutls_x509_privkey_get_key_id(key, 0, key_id, &key_id_size); if(ret < 0) { trace(LOG_ERR, "failed to get key ID"); goto free_certs_key; } id_cert = -1; for(i = 0; i < certs_nr; i++) { uint8_t cert_id[20]; size_t cert_id_size; cert_id_size = sizeof(cert_id); ret = gnutls_x509_crt_get_key_id(certs[i], 0, cert_id, &cert_id_size); if(ret < 0) { trace(LOG_ERR, "failed to get key ID for certificate #%d (%d)", i, ret); goto free_certs_key; } if(key_id_size == cert_id_size && memcmp(cert_id, key_id, cert_id_size) == 0) { /* it's the key certificate ! */ if(id_cert != -1) { ret = GNUTLS_E_INTERRUPTED; trace(LOG_ERR, "Duplicate key certificate !\n"); goto free_certs_key; } id_cert = i; } } if(id_cert == -1) { ret = GNUTLS_E_INTERRUPTED; trace(LOG_ERR, "Unable to find key certificate !\n"); goto free_certs_key; } /* Now have fun with the key and certs ! */ ret = gnutls_certificate_set_x509_key(xcred, &certs[id_cert], 1, key); if(ret < 0) { trace(LOG_ERR, "failed to set key for main certificate"); goto free_certs_key; } for(i = 0; i < certs_nr; i++) { if(i != id_cert) { ret = gnutls_certificate_set_x509_trust(xcred, &certs[i], 1); if(ret < 0) { trace(LOG_ERR, "failed to trust certificate #%d", i + 1); goto free_certs_key; } } } is_success = true; free_certs_key: gnutls_x509_privkey_deinit(key); for(i = 0; i < certs_nr; i++) { gnutls_x509_crt_deinit(certs[i]); } deinit_pkcs12: gnutls_pkcs12_deinit(p12); free_blob: free(p12blob.data); error: return is_success; }
/** * gnutls_certificate_set_x509_simple_pkcs12_mem: * @res: is a #gnutls_certificate_credentials_t type. * @p12blob: the PKCS#12 blob. * @type: is PEM or DER of the @pkcs12file. * @password: optional password used to decrypt PKCS#12 file, bags and keys. * * This function sets a certificate/private key pair and/or a CRL in * the gnutls_certificate_credentials_t type. This function may * be called more than once (in case multiple keys/certificates exist * for the server). * * Encrypted PKCS#12 bags and PKCS#8 private keys are supported. However, * only password based security, and the same password for all * operations, are supported. * * PKCS#12 file may contain many keys and/or certificates, and this * function will try to auto-detect based on the key ID the certificate * and key pair to use. If the PKCS#12 file contain the issuer of * the selected certificate, it will be appended to the certificate * to form a chain. * * If more than one private keys are stored in the PKCS#12 file, * then only one key will be read (and it is undefined which one). * * It is believed that the limitations of this function is acceptable * for most usage, and that any more flexibility would introduce * complexity that would make it harder to use this functionality at * all. * * Note that, this function by default returns zero on success and a negative value on error. * Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags() * it returns an index (greater or equal to zero). That index can be used to other functions to refer to the added key-pair. * * Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior). * * Since: 2.8.0 **/ int gnutls_certificate_set_x509_simple_pkcs12_mem (gnutls_certificate_credentials_t res, const gnutls_datum_t * p12blob, gnutls_x509_crt_fmt_t type, const char *password) { gnutls_pkcs12_t p12; gnutls_x509_privkey_t key = NULL; gnutls_x509_crt_t *chain = NULL; gnutls_x509_crl_t crl = NULL; unsigned int chain_size = 0, i; int ret, idx; ret = gnutls_pkcs12_init(&p12); if (ret < 0) { gnutls_assert(); return ret; } ret = gnutls_pkcs12_import(p12, p12blob, type, 0); if (ret < 0) { gnutls_assert(); gnutls_pkcs12_deinit(p12); return ret; } if (password) { ret = gnutls_pkcs12_verify_mac(p12, password); if (ret < 0) { gnutls_assert(); gnutls_pkcs12_deinit(p12); return ret; } } ret = gnutls_pkcs12_simple_parse(p12, password, &key, &chain, &chain_size, NULL, NULL, &crl, 0); gnutls_pkcs12_deinit(p12); if (ret < 0) { gnutls_assert(); return ret; } if (key && chain) { ret = gnutls_certificate_set_x509_key(res, chain, chain_size, key); if (ret < 0) { gnutls_assert(); goto done; } idx = ret; } else { gnutls_assert(); ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto done; } if (crl) { ret = gnutls_certificate_set_x509_crl(res, &crl, 1); if (ret < 0) { gnutls_assert(); goto done; } } if (res->flags & GNUTLS_CERTIFICATE_API_V2) ret = idx; else ret = 0; done: if (chain) { for (i = 0; i < chain_size; i++) gnutls_x509_crt_deinit(chain[i]); gnutls_free(chain); } if (key) gnutls_x509_privkey_deinit(key); if (crl) gnutls_x509_crl_deinit(crl); return ret; }