static void aes_deinit (void *_ctx) { gnutls_free (_ctx); }
int generate_create_conf (char *tpasswd_conf) { FILE *fd; char line[5 * 1024]; int index = 1; gnutls_datum_t g, n; gnutls_datum_t str_g, str_n; fd = fopen (tpasswd_conf, "w"); if (fd == NULL) { fprintf (stderr, "Cannot open file '%s'\n", tpasswd_conf); return -1; } for (index = 1; index <= 3; index++) { if (index == 1) { n = gnutls_srp_1024_group_prime; g = gnutls_srp_1024_group_generator; } else if (index == 2) { n = gnutls_srp_1536_group_prime; g = gnutls_srp_1536_group_generator; } else { n = gnutls_srp_2048_group_prime; g = gnutls_srp_2048_group_generator; } printf ("\nGroup %d, of %d bits:\n", index, n.size * 8); print_num ("Generator", &g); print_num ("Prime", &n); if (gnutls_srp_base64_encode_alloc (&n, &str_n) < 0) { fprintf (stderr, "Could not encode\n"); return -1; } if (gnutls_srp_base64_encode_alloc (&g, &str_g) < 0) { fprintf (stderr, "Could not encode\n"); return -1; } sprintf (line, "%d:%s:%s\n", index, str_n.data, str_g.data); gnutls_free (str_n.data); gnutls_free (str_g.data); fwrite (line, 1, strlen (line), fd); } fclose (fd); return 0; }
static void wrap_nettle_cipher_close (void *h) { gnutls_free (h); }
void TLSTransaction::init (TLSServer& server) { int ret = gnutls_init (&_session, GNUTLS_SERVER); if (ret < 0) throw format ("TLS server init error. {1}", gnutls_strerror (ret)); ret = gnutls_priority_set (_session, server._priorities); if (ret < 0) throw format ("Error initializing TLS. {1}", gnutls_strerror (ret)); // Apply the x509 credentials to the current session. ret = gnutls_credentials_set (_session, GNUTLS_CRD_CERTIFICATE, server._credentials); if (ret < 0) throw format ("TLS credentials error. {1}", gnutls_strerror (ret)); // Store the TLSTransaction instance, so that the verification callback can // access it during the handshake below and call the verifcation method. gnutls_session_set_ptr (_session, (void*) this); // Require client certificate. gnutls_certificate_server_set_request (_session, GNUTLS_CERT_REQUIRE); /* // Set maximum compatibility mode. This is only suggested on public // webservers that need to trade security for compatibility gnutls_session_enable_compatibility_mode (_session); */ struct sockaddr_in sa_cli = {0}; socklen_t client_len = sizeof sa_cli; do { _socket = accept (server._socket, (struct sockaddr *) &sa_cli, &client_len); } while (errno == EINTR); if (_socket < 0) throw std::string (::strerror (errno)); // Obtain client info. char topbuf[512]; _address = inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf, sizeof (topbuf)); _port = ntohs (sa_cli.sin_port); if (_debug) std::cout << "s: INFO connection from " << _address << " port " << _port << "\n"; #if GNUTLS_VERSION_NUMBER >= 0x030109 gnutls_transport_set_int (_session, _socket); #else gnutls_transport_set_ptr (_session, (gnutls_transport_ptr_t) (intptr_t) _socket); #endif // Perform the TLS handshake do { ret = gnutls_handshake (_session); } while (ret < 0 && gnutls_error_is_fatal (ret) == 0); if (ret < 0) throw std::string ("Handshake has failed (") + gnutls_strerror (ret) + ")"; #if GNUTLS_VERSION_NUMBER < 0x02090a // The automatic verification for the server certificate with // gnutls_certificate_set_verify_function does only work with gnutls // >=2.9.10. So with older versions we should call the verify function // manually after the gnutls handshake. ret = verify_certificate (); if (ret < 0) { if (_debug) std::cout << "s: ERROR Certificate verification failed.\n"; throw std::string ("Error initializing TLS."); } #endif if (_debug) { #if GNUTLS_VERSION_NUMBER >= 0x03010a char* desc = gnutls_session_get_desc (_session); std::cout << "s: INFO Handshake was completed: " << desc << "\n"; gnutls_free (desc); #else std::cout << "s: INFO Handshake was completed.\n"; #endif } }
static void server(int fd) { int ret, csend = 0; gnutls_anon_server_credentials_t anoncred; char buffer[MAX_BUF + 1]; gnutls_datum_t cookie_key; gnutls_dtls_prestate_st prestate; gnutls_session_t session; unsigned try = 0; /* this must be called once in the program */ global_init(); if (debug) { gnutls_global_set_log_function(server_log_func); gnutls_global_set_log_level(4711); } ret = gnutls_key_generate(&cookie_key, GNUTLS_COOKIE_KEY_SIZE); if (ret < 0) { fail("Cannot generate key: %s\n", gnutls_strerror(ret)); exit(1); } gnutls_anon_allocate_server_credentials(&anoncred); gnutls_init(&session, GNUTLS_SERVER | GNUTLS_DATAGRAM); gnutls_handshake_set_timeout(session, SERV_TIMEOUT * 1000); gnutls_dtls_set_mtu(session, 1500); /* avoid calling all the priority functions, since the defaults * are adequate. */ gnutls_priority_set_direct(session, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL", NULL); gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred); gnutls_transport_set_int(session, fd); gnutls_transport_set_push_function(session, push); for (;;) { ret = recv_timeout(fd, buffer, sizeof(buffer), MSG_PEEK, SERV_TIMEOUT); if (ret < 0) { if (try != 0) { success("Server was terminated as expected!\n"); goto exit; } else { fail("Error receiving first message\n"); exit(1); } } try++; memset(&prestate, 0, sizeof(prestate)); prestate.record_seq = 105791312; prestate.hsk_write_seq = 67166359; ret = gnutls_dtls_cookie_verify(&cookie_key, CLI_ADDR, CLI_ADDR_LEN, buffer, ret, &prestate); if (ret < 0) { /* cookie not valid */ if (debug) success("Sending hello verify request\n"); ret = gnutls_dtls_cookie_send(&cookie_key, CLI_ADDR, CLI_ADDR_LEN, &prestate, (gnutls_transport_ptr_t) (long) fd, push); if (ret < 0) { fail("Cannot send data\n"); exit(1); } /* discard peeked data */ recv_timeout(fd, buffer, sizeof(buffer), 0, SERV_TIMEOUT); csend++; if (csend > 2) { fail("too many cookies sent\n"); exit(1); } continue; } /* success */ break; } fail("Shouldn't have reached here\n"); exit(1); exit: gnutls_deinit(session); gnutls_free(cookie_key.data); gnutls_anon_free_server_credentials(anoncred); gnutls_global_deinit(); }
int main(void) { int ret, sd, ii; gnutls_session_t session; gnutls_priority_t priorities_cache; char buffer[MAX_BUF + 1]; gnutls_certificate_credentials_t xcred; /* Allow connections to servers that have OpenPGP keys as well. */ gnutls_global_init(); /* PKCS11 private key operations might require PIN. * Register a callback. */ gnutls_pkcs11_set_pin_function(pin_callback, NULL); /* X509 stuff */ gnutls_certificate_allocate_credentials(&xcred); /* priorities */ gnutls_priority_init(&priorities_cache, "NORMAL", NULL); /* sets the trusted cas file */ gnutls_certificate_set_x509_trust_file(xcred, CAFILE, GNUTLS_X509_FMT_PEM); gnutls_certificate_set_x509_key_file(xcred, CERT_URL, KEY_URL, GNUTLS_X509_FMT_DER); /* Initialize TLS session */ gnutls_init(&session, GNUTLS_CLIENT); /* Use default priorities */ gnutls_priority_set(session, priorities_cache); /* 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_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); } 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_priority_deinit(priorities_cache); gnutls_global_deinit(); return 0; }
/** * gnutls_pkcs12_simple_parse: * @p12: the PKCS12 blob. * @password: optional password used to decrypt PKCS12 blob, bags and keys. * @key: a structure to store the parsed private key. * @chain: the corresponding to key certificate chain (may be %NULL) * @chain_len: will be updated with the number of additional (may be %NULL) * @extra_certs: optional pointer to receive an array of additional * certificates found in the PKCS12 blob (may be %NULL). * @extra_certs_len: will be updated with the number of additional * certs (may be %NULL). * @crl: an optional structure to store the parsed CRL (may be %NULL). * @flags: should be zero or one of GNUTLS_PKCS12_SP_* * * This function parses a PKCS12 blob in @p12blob and extracts the * private key, the corresponding certificate chain, and any additional * certificates and a CRL. * * The @extra_certs_ret and @extra_certs_len parameters are optional * and both may be set to %NULL. If either is non-%NULL, then both must * be set. * * Encrypted PKCS12 bags and PKCS8 private keys are supported. However, * only password based security, and the same password for all * operations, are supported. * * A PKCS12 file may contain many keys and/or certificates, and there * is no way to identify which key/certificate pair you want. You * should make sure the PKCS12 file only contain one key/certificate * pair and/or one CRL. * * It is believed that the limitations of this function are acceptable * for common usage, and that any more flexibility would introduce * complexity that would make it harder to use this functionality at * all. * * If the provided structure has encrypted fields but no password * is provided then this function returns %GNUTLS_E_DECRYPTION_FAILED. * * Note that normally the chain constructed does not include self signed * certificates, to comply with TLS' requirements. If, however, the flag * %GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED is specified then * self signed certificates will be included in the chain. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.1 **/ int gnutls_pkcs12_simple_parse(gnutls_pkcs12_t p12, const char *password, gnutls_x509_privkey_t * key, gnutls_x509_crt_t ** chain, unsigned int *chain_len, gnutls_x509_crt_t ** extra_certs, unsigned int *extra_certs_len, gnutls_x509_crl_t * crl, unsigned int flags) { gnutls_pkcs12_bag_t bag = NULL; gnutls_x509_crt_t *_extra_certs = NULL; unsigned int _extra_certs_len = 0; gnutls_x509_crt_t *_chain = NULL; unsigned int _chain_len = 0; int idx = 0; int ret; size_t cert_id_size = 0; size_t key_id_size = 0; uint8_t cert_id[20]; uint8_t key_id[20]; int privkey_ok = 0; unsigned int i; *key = NULL; if (crl) *crl = NULL; /* find the first private key */ for (;;) { int elements_in_bag; int i; ret = gnutls_pkcs12_bag_init(&bag); if (ret < 0) { bag = NULL; gnutls_assert(); goto done; } ret = gnutls_pkcs12_get_bag(p12, idx, bag); if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) break; if (ret < 0) { gnutls_assert(); goto done; } ret = gnutls_pkcs12_bag_get_type(bag, 0); if (ret < 0) { gnutls_assert(); goto done; } if (ret == GNUTLS_BAG_ENCRYPTED) { if (password == NULL) { ret = gnutls_assert_val (GNUTLS_E_DECRYPTION_FAILED); goto done; } ret = gnutls_pkcs12_bag_decrypt(bag, password); if (ret < 0) { gnutls_assert(); goto done; } } elements_in_bag = gnutls_pkcs12_bag_get_count(bag); if (elements_in_bag < 0) { gnutls_assert(); goto done; } for (i = 0; i < elements_in_bag; i++) { int type; gnutls_datum_t data; type = gnutls_pkcs12_bag_get_type(bag, i); if (type < 0) { gnutls_assert(); goto done; } ret = gnutls_pkcs12_bag_get_data(bag, i, &data); if (ret < 0) { gnutls_assert(); goto done; } switch (type) { case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY: if (password == NULL) { ret = gnutls_assert_val (GNUTLS_E_DECRYPTION_FAILED); goto done; } case GNUTLS_BAG_PKCS8_KEY: if (*key != NULL) { /* too simple to continue */ gnutls_assert(); break; } ret = gnutls_x509_privkey_init(key); if (ret < 0) { gnutls_assert(); goto done; } ret = gnutls_x509_privkey_import_pkcs8 (*key, &data, GNUTLS_X509_FMT_DER, password, type == GNUTLS_BAG_PKCS8_KEY ? GNUTLS_PKCS_PLAIN : 0); if (ret < 0) { gnutls_assert(); gnutls_x509_privkey_deinit(*key); goto done; } key_id_size = sizeof(key_id); ret = gnutls_x509_privkey_get_key_id(*key, 0, key_id, &key_id_size); if (ret < 0) { gnutls_assert(); gnutls_x509_privkey_deinit(*key); goto done; } privkey_ok = 1; /* break */ break; default: break; } } idx++; gnutls_pkcs12_bag_deinit(bag); if (privkey_ok != 0) /* private key was found */ break; } if (privkey_ok == 0) { /* no private key */ gnutls_assert(); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } /* now find the corresponding certificate */ idx = 0; bag = NULL; for (;;) { int elements_in_bag; int i; ret = gnutls_pkcs12_bag_init(&bag); if (ret < 0) { bag = NULL; gnutls_assert(); goto done; } ret = gnutls_pkcs12_get_bag(p12, idx, bag); if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) break; if (ret < 0) { gnutls_assert(); goto done; } ret = gnutls_pkcs12_bag_get_type(bag, 0); if (ret < 0) { gnutls_assert(); goto done; } if (ret == GNUTLS_BAG_ENCRYPTED) { ret = gnutls_pkcs12_bag_decrypt(bag, password); if (ret < 0) { gnutls_assert(); goto done; } } elements_in_bag = gnutls_pkcs12_bag_get_count(bag); if (elements_in_bag < 0) { gnutls_assert(); goto done; } for (i = 0; i < elements_in_bag; i++) { int type; gnutls_datum_t data; gnutls_x509_crt_t this_cert; type = gnutls_pkcs12_bag_get_type(bag, i); if (type < 0) { gnutls_assert(); goto done; } ret = gnutls_pkcs12_bag_get_data(bag, i, &data); if (ret < 0) { gnutls_assert(); goto done; } switch (type) { case GNUTLS_BAG_CERTIFICATE: ret = gnutls_x509_crt_init(&this_cert); if (ret < 0) { gnutls_assert(); goto done; } ret = gnutls_x509_crt_import(this_cert, &data, GNUTLS_X509_FMT_DER); if (ret < 0) { gnutls_assert(); gnutls_x509_crt_deinit(this_cert); goto done; } /* check if the key id match */ cert_id_size = sizeof(cert_id); ret = gnutls_x509_crt_get_key_id(this_cert, 0, cert_id, &cert_id_size); if (ret < 0) { gnutls_assert(); gnutls_x509_crt_deinit(this_cert); goto done; } if (memcmp(cert_id, key_id, cert_id_size) != 0) { /* they don't match - skip the certificate */ if (extra_certs) { _extra_certs = gnutls_realloc_fast (_extra_certs, sizeof(_extra_certs [0]) * ++_extra_certs_len); if (!_extra_certs) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto done; } _extra_certs [_extra_certs_len - 1] = this_cert; this_cert = NULL; } else { gnutls_x509_crt_deinit (this_cert); } } else { if (chain && _chain_len == 0) { _chain = gnutls_malloc(sizeof (_chain [0]) * (++_chain_len)); if (!_chain) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto done; } _chain[_chain_len - 1] = this_cert; this_cert = NULL; } else { gnutls_x509_crt_deinit (this_cert); } } break; case GNUTLS_BAG_CRL: if (crl == NULL || *crl != NULL) { gnutls_assert(); break; } ret = gnutls_x509_crl_init(crl); if (ret < 0) { gnutls_assert(); goto done; } ret = gnutls_x509_crl_import(*crl, &data, GNUTLS_X509_FMT_DER); if (ret < 0) { gnutls_assert(); gnutls_x509_crl_deinit(*crl); goto done; } break; case GNUTLS_BAG_ENCRYPTED: /* XXX Bother to recurse one level down? Unlikely to use the same password anyway. */ case GNUTLS_BAG_EMPTY: default: break; } } idx++; gnutls_pkcs12_bag_deinit(bag); } if (chain != NULL) { if (_chain_len != 1) { ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto done; } ret = make_chain(&_chain, &_chain_len, &_extra_certs, &_extra_certs_len, flags); if (ret < 0) { gnutls_assert(); goto done; } } ret = 0; done: if (bag) gnutls_pkcs12_bag_deinit(bag); if (ret < 0) { if (*key) gnutls_x509_privkey_deinit(*key); if (_extra_certs_len && _extra_certs != NULL) { for (i = 0; i < _extra_certs_len; i++) gnutls_x509_crt_deinit(_extra_certs[i]); gnutls_free(_extra_certs); } if (_chain_len && _chain != NULL) { for (i = 0; i < _chain_len; i++) gnutls_x509_crt_deinit(_chain[i]); gnutls_free(_chain); } return ret; } if (extra_certs && _extra_certs_len > 0) { *extra_certs = _extra_certs; *extra_certs_len = _extra_certs_len; } else { if (extra_certs) { *extra_certs = NULL; *extra_certs_len = 0; } for (i = 0; i < _extra_certs_len; i++) gnutls_x509_crt_deinit(_extra_certs[i]); gnutls_free(_extra_certs); } if (chain != NULL) { *chain = _chain; *chain_len = _chain_len; } return ret; }
static void print_dh_info (gnutls_session_t session, const char *str) { printf ("- %sDiffie-Hellman parameters\n", str); printf (" - Using prime: %d bits\n", gnutls_dh_get_prime_bits (session)); printf (" - Secret key: %d bits\n", gnutls_dh_get_secret_bits (session)); printf (" - Peer's public key: %d bits\n", gnutls_dh_get_peers_public_bits (session)); if (print_cert) { int ret; gnutls_datum_t raw_gen = { NULL, 0 }; gnutls_datum_t raw_prime = { NULL, 0 }; gnutls_dh_params_t dh_params = NULL; unsigned char *params_data = NULL; size_t params_data_size = 0; ret = gnutls_dh_get_group (session, &raw_gen, &raw_prime); if (ret) { fprintf (stderr, "gnutls_dh_get_group %d\n", ret); goto out; } ret = gnutls_dh_params_init (&dh_params); if (ret) { fprintf (stderr, "gnutls_dh_params_init %d\n", ret); goto out; } ret = gnutls_dh_params_import_raw (dh_params, &raw_prime, &raw_gen); if (ret) { fprintf (stderr, "gnutls_dh_params_import_raw %d\n", ret); goto out; } ret = gnutls_dh_params_export_pkcs3 (dh_params, GNUTLS_X509_FMT_PEM, params_data, ¶ms_data_size); if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { fprintf (stderr, "gnutls_dh_params_export_pkcs3 %d\n", ret); goto out; } params_data = gnutls_malloc (params_data_size); if (!params_data) { fprintf (stderr, "gnutls_malloc %d\n", ret); goto out; } ret = gnutls_dh_params_export_pkcs3 (dh_params, GNUTLS_X509_FMT_PEM, params_data, ¶ms_data_size); if (ret) { fprintf (stderr, "gnutls_dh_params_export_pkcs3-2 %d\n", ret); goto out; } printf (" - PKCS#3 format:\n\n%.*s\n", (int) params_data_size, params_data); out: gnutls_free (params_data); gnutls_free (raw_prime.data); gnutls_free (raw_gen.data); gnutls_dh_params_deinit (dh_params); } }
static void print_x509_info (gnutls_session_t session, const char *hostname, int insecure) { gnutls_x509_crt_t crt; const gnutls_datum_t *cert_list; unsigned int cert_list_size = 0, j; int hostname_ok = 0; int ret; cert_list = gnutls_certificate_get_peers (session, &cert_list_size); if (cert_list_size == 0) { fprintf (stderr, "No certificates found!\n"); return; } printf (" - Got a certificate list of %d certificates.\n", cert_list_size); for (j = 0; j < cert_list_size; j++) { gnutls_datum_t cinfo; gnutls_x509_crt_init (&crt); ret = gnutls_x509_crt_import (crt, &cert_list[j], GNUTLS_X509_FMT_DER); if (ret < 0) { fprintf (stderr, "Decoding error: %s\n", gnutls_strerror (ret)); return; } printf (" - Certificate[%d] info:\n - ", j); if (verbose) ret = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_FULL, &cinfo); else ret = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_ONELINE, &cinfo); if (ret == 0) { printf ("%s\n", cinfo.data); gnutls_free (cinfo.data); } if (print_cert) { size_t size = 0; char *p = NULL; ret = gnutls_x509_crt_export (crt, GNUTLS_X509_FMT_PEM, p, &size); if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { p = malloc (size); if (!p) { fprintf (stderr, "gnutls_malloc\n"); exit (1); } ret = gnutls_x509_crt_export (crt, GNUTLS_X509_FMT_PEM, p, &size); } if (ret < 0) { fprintf (stderr, "Encoding error: %s\n", gnutls_strerror (ret)); return; } fputs ("\n", stdout); fputs (p, stdout); fputs ("\n", stdout); gnutls_free (p); } if (j == 0 && hostname != NULL) { /* Check the hostname of the first certificate if it matches * the name of the host we connected to. */ if (gnutls_x509_crt_check_hostname (crt, hostname) == 0) hostname_ok = 1; else hostname_ok = 2; } gnutls_x509_crt_deinit (crt); } if (hostname_ok == 1) { printf ("- The hostname in the certificate does NOT match '%s'\n", hostname); if (!insecure) exit (1); } else if (hostname_ok == 2) { printf ("- The hostname in the certificate matches '%s'.\n", hostname); } }
/* Run an HMAC using the key above on the library binary data. * Returns true on success and false on error. */ static unsigned check_binary_integrity(const char* libname, const char* symbol) { int ret; unsigned prev; char mac_file[GNUTLS_PATH_MAX]; char file[GNUTLS_PATH_MAX]; uint8_t hmac[HMAC_SIZE]; uint8_t new_hmac[HMAC_SIZE]; size_t hmac_size; gnutls_datum_t data; ret = get_library_path(libname, symbol, file, sizeof(file)); if (ret < 0) { _gnutls_debug_log("Could not get path for library %s\n", libname); return 0; } _gnutls_debug_log("Loading: %s\n", file); ret = gnutls_load_file(file, &data); if (ret < 0) { _gnutls_debug_log("Could not load: %s\n", file); return gnutls_assert_val(0); } prev = _gnutls_get_lib_state(); _gnutls_switch_lib_state(LIB_STATE_OPERATIONAL); ret = gnutls_hmac_fast(HMAC_ALGO, FIPS_KEY, sizeof(FIPS_KEY)-1, data.data, data.size, new_hmac); _gnutls_switch_lib_state(prev); gnutls_free(data.data); if (ret < 0) return gnutls_assert_val(0); /* now open the .hmac file and compare */ get_hmac_file(mac_file, sizeof(mac_file), file); ret = gnutls_load_file(mac_file, &data); if (ret < 0) { get_hmac_file2(mac_file, sizeof(mac_file), file); ret = gnutls_load_file(mac_file, &data); if (ret < 0) { _gnutls_debug_log("Could not open %s for MAC testing: %s\n", mac_file, gnutls_strerror(ret)); return gnutls_assert_val(0); } } hmac_size = hex_data_size(data.size); ret = gnutls_hex_decode(&data, hmac, &hmac_size); gnutls_free(data.data); if (ret < 0) { _gnutls_debug_log("Could not convert hex data to binary for MAC testing for %s.\n", libname); return gnutls_assert_val(0); } if (hmac_size != sizeof(hmac) || memcmp(hmac, new_hmac, sizeof(hmac)) != 0) { _gnutls_debug_log("Calculated MAC for %s does not match\n", libname); return gnutls_assert_val(0); } _gnutls_debug_log("Successfully verified MAC for %s (%s)\n", mac_file, libname); return 1; }
static void print_openpgp_info (gnutls_session_t session, const char *hostname, int insecure) { gnutls_openpgp_crt_t crt; const gnutls_datum_t *cert_list; int cert_list_size = 0; int hostname_ok = 0; int ret; cert_list = gnutls_certificate_get_peers (session, &cert_list_size); if (cert_list_size > 0) { gnutls_datum_t cinfo; gnutls_openpgp_crt_init (&crt); ret = gnutls_openpgp_crt_import (crt, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW); if (ret < 0) { fprintf (stderr, "Decoding error: %s\n", gnutls_strerror (ret)); return; } if (verbose) ret = gnutls_openpgp_crt_print (crt, GNUTLS_CRT_PRINT_FULL, &cinfo); else ret = gnutls_openpgp_crt_print (crt, GNUTLS_CRT_PRINT_ONELINE, &cinfo); if (ret == 0) { printf (" - %s\n", cinfo.data); gnutls_free (cinfo.data); } if (print_cert) { size_t size = 0; char *p = NULL; ret = gnutls_openpgp_crt_export (crt, GNUTLS_OPENPGP_FMT_BASE64, p, &size); if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { p = malloc (size); if (!p) { fprintf (stderr, "gnutls_malloc\n"); exit (1); } ret = gnutls_openpgp_crt_export (crt, GNUTLS_OPENPGP_FMT_BASE64, p, &size); } if (ret < 0) { fprintf (stderr, "Encoding error: %s\n", gnutls_strerror (ret)); return; } fputs (p, stdout); fputs ("\n", stdout); gnutls_free (p); } if (hostname != NULL) { /* Check the hostname of the first certificate if it matches * the name of the host we connected to. */ if (gnutls_openpgp_crt_check_hostname (crt, hostname) == 0) hostname_ok = 1; else hostname_ok = 2; } gnutls_openpgp_crt_deinit (crt); } if (hostname_ok == 1) { printf ("- The hostname in the certificate does NOT match '%s'\n", hostname); if (!insecure) exit (1); } else if (hostname_ok == 2) { printf ("- The hostname in the certificate matches '%s'.\n", hostname); } }
/* Loads a x509 private key list */ gnutls_x509_privkey_t *load_privkey_list(int mand, size_t * privkey_size, common_info_st * info) { static gnutls_x509_privkey_t key[MAX_KEYS]; char *ptr; int ret, i; gnutls_datum_t dat, file_data; int ptr_size; unsigned int flags = 0; const char *pass; *privkey_size = 0; fprintf(stderr, "Loading private key list...\n"); if (info->privkey == NULL) { if (mand) { fprintf(stderr, "missing --load-privkey"); exit(1); } else return NULL; } ret = gnutls_load_file(info->privkey, &file_data); if (ret < 0) { fprintf(stderr, "%s", info->privkey); exit(1); } ptr = (void *) file_data.data; ptr_size = file_data.size; for (i = 0; i < MAX_KEYS; i++) { ret = gnutls_x509_privkey_init(&key[i]); if (ret < 0) { fprintf(stderr, "privkey_init: %s", gnutls_strerror(ret)); exit(1); } dat.data = (void *) ptr; dat.size = ptr_size; ret = gnutls_x509_privkey_import2(key[i], &dat, info->incert_format, NULL, 0); if (ret == GNUTLS_E_DECRYPTION_FAILED) { pass = get_password(info, &flags, 0); ret = gnutls_x509_privkey_import2(key[i], &dat, info-> incert_format, pass, flags); } if (ret < 0 && *privkey_size > 0) break; if (ret < 0) { fprintf(stderr, "privkey_import: %s", gnutls_strerror(ret)); exit(1); } (*privkey_size)++; if (info->incert_format != GNUTLS_X509_FMT_PEM) break; ptr = strstr(ptr, "---END"); if (ptr == NULL) break; ptr++; ptr_size = file_data.size; ptr_size -= (unsigned int) ((unsigned char *) ptr - (unsigned char *) buffer); if (ptr_size < 0) break; } gnutls_free(file_data.data); fprintf(stderr, "Loaded %d private keys.\n", (int) *privkey_size); return key; }
/* This function behaves exactly like write(). The only difference is * that it accepts, the gnutls_session_t and the content_type_t of data to * send (if called by the user the Content is specific) * It is intended to transfer data, under the current session. * * Oct 30 2001: Removed capability to send data more than MAX_RECORD_SIZE. * This makes the function much easier to read, and more error resistant * (there were cases were the old function could mess everything up). * --nmav * * This function may accept a NULL pointer for data, and 0 for size, if * and only if the previous send was interrupted for some reason. * */ ssize_t _gnutls_send_int (gnutls_session_t session, content_type_t type, gnutls_handshake_description_t htype, const void *_data, size_t sizeofdata) { uint8_t *cipher; int cipher_size; int retval, ret; int data2send_size; uint8_t headers[5]; const uint8_t *data = _data; int erecord_size = 0; opaque *erecord = NULL; /* Do not allow null pointer if the send buffer is empty. * If the previous send was interrupted then a null pointer is * ok, and means to resume. */ if (session->internals.record_send_buffer.length == 0 && (sizeofdata == 0 && _data == NULL)) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (type != GNUTLS_ALERT) /* alert messages are sent anyway */ if (session_is_valid (session) || session->internals.may_not_write != 0) { gnutls_assert (); return GNUTLS_E_INVALID_SESSION; } headers[0] = type; /* Use the default record version, if it is * set. */ copy_record_version (session, htype, &headers[1]); _gnutls_record_log ("REC[%x]: Sending Packet[%d] %s(%d) with length: %d\n", session, (int) _gnutls_uint64touint32 (&session->connection_state. write_sequence_number), _gnutls_packet2str (type), type, sizeofdata); if (sizeofdata > MAX_RECORD_SEND_SIZE) data2send_size = MAX_RECORD_SEND_SIZE; else data2send_size = sizeofdata; /* Only encrypt if we don't have data to send * from the previous run. - probably interrupted. */ if (session->internals.record_send_buffer.length > 0) { ret = _gnutls_io_write_flush (session); if (ret > 0) cipher_size = ret; else cipher_size = 0; cipher = NULL; retval = session->internals.record_send_buffer_user_size; } else { /* now proceed to packet encryption */ cipher_size = data2send_size + MAX_RECORD_OVERHEAD; cipher = gnutls_malloc (cipher_size); if (cipher == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } cipher_size = _gnutls_encrypt (session, headers, RECORD_HEADER_SIZE, data, data2send_size, cipher, cipher_size, type, 1); if (cipher_size <= 0) { gnutls_assert (); if (cipher_size == 0) cipher_size = GNUTLS_E_ENCRYPTION_FAILED; gnutls_afree (erecord); gnutls_free (cipher); return cipher_size; /* error */ } retval = data2send_size; session->internals.record_send_buffer_user_size = data2send_size; /* increase sequence number */ if (_gnutls_uint64pp (&session->connection_state.write_sequence_number) != 0) { session_invalidate (session); gnutls_assert (); gnutls_afree (erecord); gnutls_free (cipher); return GNUTLS_E_RECORD_LIMIT_REACHED; } ret = _gnutls_io_write_buffered2 (session, erecord, erecord_size, cipher, cipher_size); gnutls_afree (erecord); gnutls_free (cipher); } if (ret != cipher_size + erecord_size) { if (ret < 0 && gnutls_error_is_fatal (ret) == 0) { /* If we have sent any data then just return * the error value. Do not invalidate the session. */ gnutls_assert (); return ret; } if (ret > 0) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; } session_unresumable (session); session->internals.may_not_write = 1; gnutls_assert (); return ret; } session->internals.record_send_buffer_user_size = 0; _gnutls_record_log ("REC[%x]: Sent Packet[%d] %s(%d) with length: %d\n", session, (int) _gnutls_uint64touint32 (&session-> connection_state. write_sequence_number), _gnutls_packet2str (type), type, cipher_size); return retval; }
static void client (int sds[], struct params_res *params) { int ret, ii; gnutls_session_t session; char buffer[MAX_BUF + 1]; gnutls_anon_client_credentials_t anoncred; /* Need to enable anonymous KX specifically. */ /* variables used in session resuming */ int t; gnutls_datum_t session_data; if (debug) { gnutls_global_set_log_function (tls_log_func); gnutls_global_set_log_level (2); } global_init (); gnutls_anon_allocate_client_credentials (&anoncred); for (t = 0; t < SESSIONS; t++) { int sd = sds[t]; /* Initialize TLS session */ gnutls_init (&session, GNUTLS_CLIENT|GNUTLS_NO_EXTENSIONS); /* Use default priorities */ gnutls_priority_set_direct (session, "NONE:+VERS-TLS-ALL:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL); /* put the anonymous credentials to the current session */ gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred); if (params->enable_session_ticket_client) gnutls_session_ticket_enable_client (session); if (t > 0) { /* if this is not the first time we connect */ gnutls_session_set_data (session, session_data.data, session_data.size); gnutls_free (session_data.data); } gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); /* Perform the TLS handshake */ ret = gnutls_handshake (session); if (ret < 0) { fail ("client: Handshake failed\n"); gnutls_perror (ret); goto end; } else { if (debug) success ("client: Handshake was completed\n"); } if (t == 0) { /* the first time we connect */ /* get the session data size */ ret = gnutls_session_get_data2 (session, &session_data); if (ret < 0) fail ("Getting resume data failed\n"); } else { /* the second time we connect */ /* check if we actually resumed the previous session */ if (gnutls_session_is_resumed (session) != 0) { if (params->expect_resume) { if (debug) success ("- Previous session was resumed\n"); } else fail ("- Previous session was resumed\n"); } else { if (params->expect_resume) { fail ("*** Previous session was NOT resumed\n"); } else { if (debug) success ("*** Previous session was NOT resumed (expected)\n"); } } } gnutls_record_send (session, MSG, strlen (MSG)); ret = gnutls_record_recv (session, buffer, MAX_BUF); if (ret == 0) { if (debug) success ("client: Peer has closed the TLS connection\n"); goto end; } else if (ret < 0) { fail ("client: Error: %s\n", gnutls_strerror (ret)); goto end; } if (debug ) { printf ("- Received %d bytes: ", ret); for (ii = 0; ii < ret; ii++) { fputc (buffer[ii], stdout); } fputs ("\n", stdout); } gnutls_bye (session, GNUTLS_SHUT_RDWR); close (sd); gnutls_deinit (session); } end: gnutls_anon_free_client_credentials (anoncred); }
static int get_win_urls(const CERT_CONTEXT *cert, char **cert_url, char **key_url, char **label, gnutls_datum_t *der) { BOOL r; int ret; DWORD tl_size; gnutls_datum_t tmp_label = {NULL, 0}; char name[MAX_CN*2]; char hex[MAX_WID_SIZE*2+1]; gnutls_buffer_st str; #ifdef WORDS_BIGENDIAN const unsigned bigendian = 1; #else const unsigned bigendian = 0; #endif if (cert == NULL) return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); if (der) { der->data = gnutls_malloc(cert->cbCertEncoded); if (der->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); memcpy(der->data, cert->pbCertEncoded, cert->cbCertEncoded); der->size = cert->cbCertEncoded; } _gnutls_buffer_init(&str); if (label) *label = NULL; if (key_url) *key_url = NULL; if (cert_url) *cert_url = NULL; tl_size = sizeof(name); r = CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, name, &tl_size); if (r != 0) { /* optional */ ret = _gnutls_ucs2_to_utf8(name, tl_size, &tmp_label, bigendian); if (ret < 0) { gnutls_assert(); goto fail; } if (label) *label = (char*)tmp_label.data; } tl_size = sizeof(name); r = CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, name, &tl_size); if (r == 0) { gnutls_assert(); ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto fail; } if (_gnutls_bin2hex(name, tl_size, hex, sizeof(hex), 0) == NULL) { ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR); goto fail; } ret = _gnutls_buffer_append_printf(&str, WIN_URL"id=%s;type=cert", hex); if (ret < 0) { gnutls_assert(); goto fail; } if (tmp_label.data) { ret = _gnutls_buffer_append_str(&str, ";name="); if (ret < 0) { gnutls_assert(); goto fail; } ret = _gnutls_buffer_append_escape(&str, tmp_label.data, tmp_label.size, " "); if (ret < 0) { gnutls_assert(); goto fail; } } ret = _gnutls_buffer_append_data(&str, "\x00", 1); if (ret < 0) { gnutls_assert(); goto fail; } if (cert_url) *cert_url = (char*)str.data; _gnutls_buffer_init(&str); ret = _gnutls_buffer_append_printf(&str, WIN_URL"id=%s;type=privkey", hex); if (ret < 0) { gnutls_assert(); goto fail; } if (tmp_label.data) { ret = _gnutls_buffer_append_str(&str, ";name="); if (ret < 0) { gnutls_assert(); goto fail; } ret = _gnutls_buffer_append_escape(&str, tmp_label.data, tmp_label.size, " "); if (ret < 0) { gnutls_assert(); goto fail; } } ret = _gnutls_buffer_append_data(&str, "\x00", 1); if (ret < 0) { gnutls_assert(); goto fail; } if (key_url) *key_url = (char*)str.data; _gnutls_buffer_init(&str); ret = 0; goto cleanup; fail: if (der) gnutls_free(der->data); if (cert_url) gnutls_free(*cert_url); if (key_url) gnutls_free(*key_url); if (label) gnutls_free(*label); cleanup: _gnutls_buffer_clear(&str); return ret; }
/* This function transmits the flight that has been previously * buffered. * * This function is called from the handshake layer and calls the * record layer. */ int _dtls_transmit (gnutls_session_t session) { int ret; uint8_t* buf = NULL; unsigned int timeout; /* PREPARING -> SENDING state transition */ mbuffer_head_st *const send_buffer = &session->internals.handshake_send_buffer; mbuffer_st *cur; gnutls_handshake_description_t last_type = 0; unsigned int diff; struct timespec now; gettime(&now); /* If we have already sent a flight and we are operating in a * non blocking way, check if it is time to retransmit or just * return. */ if (session->internals.dtls.flight_init != 0 && session->internals.dtls.blocking == 0) { /* just in case previous run was interrupted */ ret = _gnutls_io_write_flush (session); if (ret < 0) { gnutls_assert(); goto cleanup; } if (session->internals.dtls.last_flight == 0 || !_dtls_is_async(session)) { /* check for ACK */ ret = _gnutls_io_check_recv(session, 0); if (ret == GNUTLS_E_TIMEDOUT) { /* if no retransmission is required yet just return */ if (_dtls_timespec_sub_ms(&now, &session->internals.dtls.last_retransmit) < TIMER_WINDOW) { gnutls_assert(); goto nb_timeout; } } else /* received something */ { if (ret == 0) { ret = is_next_hpacket_expected(session); if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) goto nb_timeout; if (ret < 0 && ret != GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET) { gnutls_assert(); goto cleanup; } if (ret == 0) goto end_flight; /* if ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET retransmit */ } else goto nb_timeout; } } } do { timeout = TIMER_WINDOW; diff = _dtls_timespec_sub_ms(&now, &session->internals.dtls.handshake_start_time); if (diff >= session->internals.dtls.total_timeout_ms) { _gnutls_dtls_log("Session timeout: %u ms\n", diff); ret = gnutls_assert_val(GNUTLS_E_TIMEDOUT); goto end_flight; } diff = _dtls_timespec_sub_ms(&now, &session->internals.dtls.last_retransmit); if (session->internals.dtls.flight_init == 0 || diff >= TIMER_WINDOW) { _gnutls_dtls_log ("DTLS[%p]: %sStart of flight transmission.\n", session, (session->internals.dtls.flight_init == 0)?"":"re-"); for (cur = send_buffer->head; cur != NULL; cur = cur->next) { ret = transmit_message (session, cur, &buf); if (ret < 0) { gnutls_assert(); goto end_flight; } last_type = cur->htype; } gettime(&session->internals.dtls.last_retransmit); if (session->internals.dtls.flight_init == 0) { session->internals.dtls.flight_init = 1; RESET_TIMER; timeout = TIMER_WINDOW; if (last_type == GNUTLS_HANDSHAKE_FINISHED) { /* On the last flight we cannot ensure retransmission * from here. _dtls_wait_and_retransmit() is being called * by handshake. */ session->internals.dtls.last_flight = 1; } else session->internals.dtls.last_flight = 0; } else { UPDATE_TIMER; } } ret = _gnutls_io_write_flush (session); if (ret < 0) { ret = gnutls_assert_val(ret); goto cleanup; } /* last message in handshake -> no ack */ if (session->internals.dtls.last_flight != 0) { /* we don't wait here. We just return 0 and * if a retransmission occurs because peer didn't receive it * we rely on the record or handshake * layer calling this function again. */ ret = 0; goto cleanup; } else /* all other messages -> implicit ack (receive of next flight) */ { if (session->internals.dtls.blocking != 0) ret = _gnutls_io_check_recv(session, timeout); else { ret = _gnutls_io_check_recv(session, 0); if (ret == GNUTLS_E_TIMEDOUT) { goto nb_timeout; } } if (ret == 0) { ret = is_next_hpacket_expected(session); if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) goto nb_timeout; if (ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET) { ret = GNUTLS_E_TIMEDOUT; goto keep_up; } if (ret < 0) { gnutls_assert(); goto cleanup; } goto end_flight; } } keep_up: gettime(&now); } while(ret == GNUTLS_E_TIMEDOUT); if (ret < 0) { ret = gnutls_assert_val(ret); goto end_flight; } ret = 0; end_flight: _gnutls_dtls_log ("DTLS[%p]: End of flight transmission.\n", session); _dtls_reset_hsk_state(session); cleanup: if (buf != NULL) gnutls_free(buf); /* SENDING -> WAITING state transition */ return ret; nb_timeout: if (buf != NULL) gnutls_free(buf); RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, ret); }
/** * gnutls_system_key_add_x509: * @crt: the certificate to be added * @privkey: the key to be added * @label: the friendly name to describe the key * @cert_url: if non-NULL it will contain an allocated value with the certificate URL * @key_url: if non-NULL it will contain an allocated value with the key URL * * This function will added the given key and certificate pair, * to the system list. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.4.0 **/ int gnutls_system_key_add_x509(gnutls_x509_crt_t crt, gnutls_x509_privkey_t privkey, const char *label, char **cert_url, char **key_url) { HCERTSTORE store = NULL; CRYPT_DATA_BLOB pfx; gnutls_datum_t _pfx = {NULL, 0}; gnutls_pkcs12_t p12 = NULL; gnutls_pkcs12_bag_t bag1 = NULL, bag2 = NULL; uint8_t id[MAX_WID_SIZE]; size_t id_size; gnutls_datum_t kid; int ret; if (ncrypt_init == 0) return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); if (label == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); id_size = sizeof(id); ret = gnutls_x509_crt_get_key_id(crt, 0, id, &id_size); if (ret < 0) return gnutls_assert_val(ret); kid.data = id; kid.size = id_size; /* the idea: import the cert and private key into PKCS #12 * format, export it into pfx, and import it into store */ ret = gnutls_pkcs12_init(&p12); if (ret < 0) return gnutls_assert_val(ret); ret = gnutls_pkcs12_bag_init(&bag1); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pkcs12_bag_set_crt(bag1, crt); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pkcs12_bag_set_key_id(bag1, 0, &kid); if (ret < 0) { gnutls_assert(); goto cleanup; } if (label) gnutls_pkcs12_bag_set_friendly_name(bag1, 0, label); ret = gnutls_pkcs12_bag_init(&bag2); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pkcs12_bag_set_privkey(bag2, privkey, NULL, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pkcs12_bag_set_key_id(bag2, 0, &kid); if (ret < 0) { gnutls_assert(); goto cleanup; } if (label) gnutls_pkcs12_bag_set_friendly_name(bag2, 0, label); ret = gnutls_pkcs12_set_bag(p12, bag1); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pkcs12_set_bag(p12, bag2); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pkcs12_generate_mac(p12, "123456"); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pkcs12_export2(p12, GNUTLS_X509_FMT_DER, &_pfx); if (ret < 0) { gnutls_assert(); goto cleanup; } pfx.cbData = _pfx.size; pfx.pbData = _pfx.data; store = PFXImportCertStore(&pfx, L"123456", 0); if (store == NULL) { gnutls_assert(); ret = GNUTLS_E_INVALID_REQUEST; goto cleanup; } if (cert_url || key_url) { unsigned char sha[20]; CRYPT_HASH_BLOB blob; const CERT_CONTEXT *cert = NULL; gnutls_datum_t data; ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &data); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, data.data, data.size, sha); gnutls_free(data.data); if (ret < 0) { gnutls_assert(); goto cleanup; } blob.cbData = sizeof(sha); blob.pbData = sha; cert = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0, CERT_FIND_SHA1_HASH, &blob, NULL); if (cert == NULL) { gnutls_assert(); ret = GNUTLS_E_KEY_IMPORT_FAILED; goto cleanup; } ret = get_win_urls(cert, cert_url, key_url, NULL, NULL); if (ret < 0) { gnutls_assert(); goto cleanup; } } ret = 0; cleanup: if (p12 != NULL) gnutls_pkcs12_deinit(p12); if (bag1 != NULL) gnutls_pkcs12_bag_deinit(bag1); if (bag2 != NULL) gnutls_pkcs12_bag_deinit(bag2); if (store != NULL) CertCloseStore(store, 0); gnutls_free(_pfx.data); return ret; }
int main(void) { int ret, sd, ii; gnutls_session_t session; char buffer[MAX_BUF + 1]; const char *err; gnutls_psk_client_credentials_t pskcred; const gnutls_datum_t key = { (void *) "DEADBEEF", 8 }; gnutls_global_init(); gnutls_psk_allocate_client_credentials(&pskcred); gnutls_psk_set_client_credentials(pskcred, "test", &key, GNUTLS_PSK_KEY_HEX); /* Initialize TLS session */ gnutls_init(&session, GNUTLS_CLIENT); /* Use default priorities */ ret = gnutls_priority_set_direct(session, "PERFORMANCE:+ECDHE-PSK:+DHE-PSK:+PSK", &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_PSK, pskcred); /* connect to the peer */ sd = tcp_connect(); gnutls_transport_set_int(session, sd); gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); /* 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 { char *desc; desc = gnutls_session_get_desc(session); printf("- Session info: %s\n", desc); gnutls_free(desc); } 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 && gnutls_error_is_fatal(ret) == 0) { fprintf(stderr, "*** Warning: %s\n", gnutls_strerror(ret)); } else if (ret < 0) { fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret)); goto end; } if (ret > 0) { 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_psk_free_client_credentials(pskcred); gnutls_global_deinit(); return 0; }
static int write_attributes(gnutls_pkcs12_bag_t bag, int elem, ASN1_TYPE c2, const char *where) { int result; char root[128]; /* If the bag attributes are empty, then write * nothing to the attribute field. */ if (bag->element[elem].friendly_name == NULL && bag->element[elem].local_key_id.data == NULL) { /* no attributes */ result = asn1_write_value(c2, where, NULL, 0); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } return 0; } if (bag->element[elem].local_key_id.data != NULL) { /* Add a new Attribute */ result = asn1_write_value(c2, where, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } _gnutls_str_cpy(root, sizeof(root), where); _gnutls_str_cat(root, sizeof(root), ".?LAST"); result = _gnutls_x509_encode_and_write_attribute(KEY_ID_OID, c2, root, bag->element [elem]. local_key_id.data, bag->element [elem]. local_key_id.size, 1); if (result < 0) { gnutls_assert(); return result; } } if (bag->element[elem].friendly_name != NULL) { uint8_t *name; int size, i; const char *p; /* Add a new Attribute */ result = asn1_write_value(c2, where, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } /* convert name to BMPString */ size = strlen(bag->element[elem].friendly_name) * 2; name = gnutls_malloc(size); if (name == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } p = bag->element[elem].friendly_name; for (i = 0; i < size; i += 2) { name[i] = 0; name[i + 1] = *p; p++; } _gnutls_str_cpy(root, sizeof(root), where); _gnutls_str_cat(root, sizeof(root), ".?LAST"); result = _gnutls_x509_encode_and_write_attribute (FRIENDLY_NAME_OID, c2, root, name, size, 1); gnutls_free(name); if (result < 0) { gnutls_assert(); return result; } } return 0; }
static int pgp_crt_to_raw_pubkey(const gnutls_datum_t * cert, gnutls_datum_t * rpubkey) { #ifdef ENABLE_OPENPGP gnutls_openpgp_crt_t crt = NULL; gnutls_pubkey_t pubkey = NULL; size_t size; int ret; ret = gnutls_openpgp_crt_init(&crt); if (ret < 0) return gnutls_assert_val(ret); ret = gnutls_pubkey_init(&pubkey); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_openpgp_crt_import(crt, cert, GNUTLS_OPENPGP_FMT_RAW); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pubkey_import_openpgp(pubkey, crt, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } size = 0; ret = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, NULL, &size); if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { gnutls_assert(); goto cleanup; } rpubkey->data = gnutls_malloc(size); if (rpubkey->data == NULL) if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { ret = GNUTLS_E_MEMORY_ERROR; gnutls_assert(); goto cleanup; } ret = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, rpubkey->data, &size); if (ret < 0) { gnutls_free(rpubkey->data); gnutls_assert(); goto cleanup; } rpubkey->size = size; ret = 0; cleanup: gnutls_openpgp_crt_deinit(crt); gnutls_pubkey_deinit(pubkey); return ret; #else return GNUTLS_E_UNIMPLEMENTED_FEATURE; #endif }
static void test_sig(gnutls_pk_algorithm_t pk, unsigned hash, unsigned bits) { gnutls_pubkey_t pubkey; gnutls_privkey_t privkey; gnutls_sign_algorithm_t sign_algo; gnutls_datum_t signature; const gnutls_datum_t *hash_data; int ret; unsigned j; if (hash == GNUTLS_DIG_SHA1) hash_data = &sha1_data; else if (hash == GNUTLS_DIG_SHA256) hash_data = &sha256_data; else abort(); sign_algo = gnutls_pk_to_sign(pk, hash); for (j = 0; j < 100; j++) { ret = gnutls_pubkey_init(&pubkey); if (ret < 0) ERR(__LINE__); ret = gnutls_privkey_init(&privkey); if (ret < 0) ERR(__LINE__); ret = gnutls_privkey_generate(privkey, pk, bits, 0); if (ret < 0) ERR(__LINE__); ret = gnutls_privkey_sign_hash(privkey, hash, 0, hash_data, &signature); if (ret < 0) ERR(__LINE__); ret = gnutls_pubkey_import_privkey(pubkey, privkey, GNUTLS_KEY_DIGITAL_SIGNATURE, 0); if (ret < 0) ERR(__LINE__); ret = gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0, hash_data, &signature); if (ret < 0) ERR(__LINE__); /* should fail */ ret = gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0, &invalid_hash_data, &signature); if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED) ERR(__LINE__); sign_algo = gnutls_pk_to_sign(gnutls_pubkey_get_pk_algorithm (pubkey, NULL), hash); ret = gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0, hash_data, &signature); if (ret < 0) ERR(__LINE__); /* should fail */ ret = gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0, &invalid_hash_data, &signature); if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED) ERR(__LINE__); /* test the raw interface */ gnutls_free(signature.data); signature.data = NULL; if (pk == GNUTLS_PK_RSA) { ret = gnutls_privkey_sign_hash(privkey, hash, GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA, hash_data, &signature); if (ret < 0) ERR(__LINE__); sign_algo = gnutls_pk_to_sign (gnutls_pubkey_get_pk_algorithm (pubkey, NULL), hash); ret = gnutls_pubkey_verify_hash2(pubkey, sign_algo, GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA, hash_data, &signature); if (ret < 0) ERR(__LINE__); } gnutls_free(signature.data); gnutls_privkey_deinit(privkey); gnutls_pubkey_deinit(pubkey); } }
/** * gnutls_tdb_deinit: * @tdb: The structure to be deinitialized * * This function will deinitialize a public key trust storage structure. **/ void gnutls_tdb_deinit(gnutls_tdb_t tdb) { gnutls_free(tdb); }
int TLSTransaction::verify_certificate () const { if (_trust == TLSServer::allow_all) return 0; // This verification function uses the trusted CAs in the credentials // structure. So you must have installed one or more CA certificates. unsigned int status = 0; #if GNUTLS_VERSION_NUMBER >= 0x030104 int ret = gnutls_certificate_verify_peers3 (_session, NULL, &status); if (ret < 0) { if (_debug) std::cout << "s: ERROR Certificate verification peers3 failed. " << gnutls_strerror (ret) << "\n"; return GNUTLS_E_CERTIFICATE_ERROR; } #else int ret = gnutls_certificate_verify_peers2 (_session, &status); if (ret < 0) { if (_debug) std::cout << "s: ERROR Certificate verification peers2 failed. " << gnutls_strerror (ret) << "\n"; return GNUTLS_E_CERTIFICATE_ERROR; } if (status == 0) { if (gnutls_certificate_type_get (_session) == GNUTLS_CRT_X509) { const gnutls_datum* cert_list; unsigned int cert_list_size; gnutls_x509_crt cert; cert_list = gnutls_certificate_get_peers (_session, &cert_list_size); if (cert_list_size == 0) { if (_debug) std::cout << "s: ERROR Certificate get peers failed. " << gnutls_strerror (ret) << "\n"; return GNUTLS_E_CERTIFICATE_ERROR; } ret = gnutls_x509_crt_init (&cert); if (ret < 0) { if (_debug) std::cout << "s: ERROR x509 init failed. " << gnutls_strerror (ret) << "\n"; return GNUTLS_E_CERTIFICATE_ERROR; } ret = gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER); if (ret < 0) { if (_debug) std::cout << "s: ERROR x509 cert import. " << gnutls_strerror (ret) << "\n"; gnutls_x509_crt_deinit(cert); status = GNUTLS_E_CERTIFICATE_ERROR; } } else return GNUTLS_E_CERTIFICATE_ERROR; } #endif if (ret < 0) return GNUTLS_E_CERTIFICATE_ERROR; #if GNUTLS_VERSION_NUMBER >= 0x030105 gnutls_certificate_type_t type = gnutls_certificate_type_get (_session); gnutls_datum_t out; ret = gnutls_certificate_verification_status_print (status, type, &out, 0); if (ret < 0) { if (_debug) std::cout << "s: ERROR certificate verification status. " << gnutls_strerror (ret) << "\n"; return GNUTLS_E_CERTIFICATE_ERROR; } gnutls_free (out.data); #endif if (status != 0) return GNUTLS_E_CERTIFICATE_ERROR; // Continue handshake. return 0; }
bigint_t _gnutls_mpi_randomize (bigint_t r, unsigned int bits, gnutls_rnd_level_t level) { size_t size = 1 + (bits / 8); int ret; int rem, i; bigint_t tmp; char tmpbuf[512]; opaque *buf; int buf_release = 0; if (size < sizeof (tmpbuf)) { buf = tmpbuf; } else { buf = gnutls_malloc (size); if (buf == NULL) { gnutls_assert (); goto cleanup; } buf_release = 1; } ret = _gnutls_rnd (level, buf, size); if (ret < 0) { gnutls_assert (); goto cleanup; } /* mask the bits that weren't requested */ rem = bits % 8; if (rem == 0) { buf[0] = 0; } else { for (i = 8; i >= rem; i--) buf[0] = clearbit (buf[0], i); } ret = _gnutls_mpi_scan (&tmp, buf, size); if (ret < 0) { gnutls_assert (); goto cleanup; } if (buf_release != 0) { gnutls_free (buf); buf = NULL; } if (r != NULL) { _gnutls_mpi_set (r, tmp); _gnutls_mpi_release (&tmp); return r; } return tmp; cleanup: if (buf_release != 0) gnutls_free (buf); return NULL; }
void _gnutls_mpi_log(const char *prefix, bigint_t a) { size_t binlen = 0; void *binbuf; size_t hexlen; char *hexbuf; int res; if (_gnutls_log_level < 2) return; res = _gnutls_mpi_print(a, NULL, &binlen); if (res < 0 && res != GNUTLS_E_SHORT_MEMORY_BUFFER) { gnutls_assert(); _gnutls_hard_log("MPI: %s can't print value (%d/%d)\n", prefix, res, (int) binlen); return; } if (binlen > 1024 * 1024) { gnutls_assert(); _gnutls_hard_log("MPI: %s too large mpi (%d)\n", prefix, (int) binlen); return; } binbuf = gnutls_malloc(binlen); if (!binbuf) { gnutls_assert(); _gnutls_hard_log("MPI: %s out of memory (%d)\n", prefix, (int) binlen); return; } res = _gnutls_mpi_print(a, binbuf, &binlen); if (res != 0) { gnutls_assert(); _gnutls_hard_log("MPI: %s can't print value (%d/%d)\n", prefix, res, (int) binlen); gnutls_free(binbuf); return; } hexlen = 2 * binlen + 1; hexbuf = gnutls_malloc(hexlen); if (!hexbuf) { gnutls_assert(); _gnutls_hard_log("MPI: %s out of memory (hex %d)\n", prefix, (int) hexlen); gnutls_free(binbuf); return; } _gnutls_bin2hex(binbuf, binlen, hexbuf, hexlen, NULL); _gnutls_hard_log("MPI: length: %d\n\t%s%s\n", (int) binlen, prefix, hexbuf); gnutls_free(hexbuf); gnutls_free(binbuf); }
static int cng_sign(gnutls_privkey_t key, void *userdata, const gnutls_datum_t *raw_data, gnutls_datum_t *signature) { priv_st *priv = userdata; BCRYPT_PKCS1_PADDING_INFO _info; void *info = NULL; DWORD ret_sig = 0; int ret; DWORD flags = 0; gnutls_datum_t data = {raw_data->data, raw_data->size}; uint8_t digest[MAX_HASH_SIZE]; unsigned int digest_size; gnutls_digest_algorithm_t algo; SECURITY_STATUS r; signature->data = NULL; signature->size = 0; if (priv->pk == GNUTLS_PK_RSA) { flags = BCRYPT_PAD_PKCS1; info = &_info; if (raw_data->size == 36) { /* TLS 1.0 MD5+SHA1 */ _info.pszAlgId = NULL; } else { digest_size = sizeof(digest); ret = decode_ber_digest_info(raw_data, &algo, digest, &digest_size); if (ret < 0) return gnutls_assert_val(ret); switch(algo) { case GNUTLS_DIG_SHA1: _info.pszAlgId = NCRYPT_SHA1_ALGORITHM; break; #ifdef NCRYPT_SHA224_ALGORITHM case GNUTLS_DIG_SHA224: _info.pszAlgId = NCRYPT_SHA224_ALGORITHM; break; #endif case GNUTLS_DIG_SHA256: _info.pszAlgId = NCRYPT_SHA256_ALGORITHM; break; case GNUTLS_DIG_SHA384: _info.pszAlgId = NCRYPT_SHA384_ALGORITHM; break; case GNUTLS_DIG_SHA512: _info.pszAlgId = NCRYPT_SHA512_ALGORITHM; break; default: return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM); } data.data = digest; data.size = digest_size; } } r = pNCryptSignHash(priv->nc, info, data.data, data.size, NULL, 0, &ret_sig, flags); if (FAILED(r)) { gnutls_assert(); _gnutls_debug_log("error in pre-signing: %d\n", (int)GetLastError()); ret = GNUTLS_E_PK_SIGN_FAILED; goto fail; } signature->size = ret_sig; signature->data = gnutls_malloc(signature->size); if (signature->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); r = pNCryptSignHash(priv->nc, info, data.data, data.size, signature->data, signature->size, &ret_sig, flags); if (FAILED(r)) { gnutls_assert(); _gnutls_debug_log("error in signing: %d\n", (int)GetLastError()); ret = GNUTLS_E_PK_SIGN_FAILED; goto fail; } signature->size = ret_sig; return 0; fail: gnutls_free(signature->data); return ret; }
static int wrap_nettle_cipher_init (gnutls_cipher_algorithm_t algo, void **_ctx, int enc) { struct nettle_cipher_ctx *ctx; ctx = gnutls_calloc (1, sizeof (*ctx)); if (ctx == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } ctx->algo = algo; ctx->enc = enc; switch (algo) { case GNUTLS_CIPHER_AES_128_GCM: case GNUTLS_CIPHER_AES_256_GCM: ctx->encrypt = _gcm_encrypt; ctx->decrypt = _gcm_decrypt; ctx->i_encrypt = (nettle_crypt_func*) aes_encrypt; ctx->auth = (auth_func)gcm_aes_update; ctx->tag = (tag_func)gcm_aes_digest; ctx->ctx_ptr = &ctx->ctx.aes_gcm; ctx->block_size = AES_BLOCK_SIZE; break; case GNUTLS_CIPHER_CAMELLIA_128_CBC: case GNUTLS_CIPHER_CAMELLIA_192_CBC: case GNUTLS_CIPHER_CAMELLIA_256_CBC: ctx->encrypt = cbc_encrypt; ctx->decrypt = cbc_decrypt; ctx->i_encrypt = (nettle_crypt_func*)camellia_crypt; ctx->i_decrypt = (nettle_crypt_func*)camellia_crypt; ctx->ctx_ptr = &ctx->ctx.camellia; ctx->block_size = CAMELLIA_BLOCK_SIZE; break; case GNUTLS_CIPHER_AES_128_CBC: case GNUTLS_CIPHER_AES_192_CBC: case GNUTLS_CIPHER_AES_256_CBC: ctx->encrypt = cbc_encrypt; ctx->decrypt = cbc_decrypt; ctx->i_encrypt = (nettle_crypt_func*)aes_encrypt; ctx->i_decrypt = (nettle_crypt_func*)aes_decrypt; ctx->ctx_ptr = &ctx->ctx.aes; ctx->block_size = AES_BLOCK_SIZE; break; case GNUTLS_CIPHER_3DES_CBC: ctx->encrypt = cbc_encrypt; ctx->decrypt = cbc_decrypt; ctx->i_encrypt = (nettle_crypt_func *) des3_encrypt; ctx->i_decrypt = (nettle_crypt_func *) des3_decrypt; ctx->ctx_ptr = &ctx->ctx.des3; ctx->block_size = DES3_BLOCK_SIZE; break; case GNUTLS_CIPHER_DES_CBC: ctx->encrypt = cbc_encrypt; ctx->decrypt = cbc_decrypt; ctx->i_encrypt = (nettle_crypt_func *) des_encrypt; ctx->i_decrypt = (nettle_crypt_func *) des_decrypt; ctx->ctx_ptr = &ctx->ctx.des; ctx->block_size = DES_BLOCK_SIZE; break; case GNUTLS_CIPHER_ARCFOUR_128: case GNUTLS_CIPHER_ARCFOUR_40: ctx->encrypt = stream_encrypt; ctx->decrypt = stream_encrypt; ctx->i_encrypt = (nettle_crypt_func *) arcfour_crypt; ctx->i_decrypt = (nettle_crypt_func *) arcfour_crypt; ctx->ctx_ptr = &ctx->ctx.arcfour; ctx->block_size = 1; break; case GNUTLS_CIPHER_SALSA20_256: ctx->encrypt = stream_encrypt; ctx->decrypt = stream_encrypt; ctx->i_encrypt = (nettle_crypt_func *) salsa20_crypt; ctx->i_decrypt = (nettle_crypt_func *) salsa20_crypt; ctx->ctx_ptr = &ctx->ctx.salsa20; ctx->block_size = 1; break; case GNUTLS_CIPHER_ESTREAM_SALSA20_256: ctx->encrypt = stream_encrypt; ctx->decrypt = stream_encrypt; ctx->i_encrypt = (nettle_crypt_func *) salsa20r12_crypt; ctx->i_decrypt = (nettle_crypt_func *) salsa20r12_crypt; ctx->ctx_ptr = &ctx->ctx.salsa20; ctx->block_size = 1; break; case GNUTLS_CIPHER_RC2_40_CBC: ctx->encrypt = cbc_encrypt; ctx->decrypt = cbc_decrypt; ctx->i_encrypt = (nettle_crypt_func *) arctwo_encrypt; ctx->i_decrypt = (nettle_crypt_func *) arctwo_decrypt; ctx->ctx_ptr = &ctx->ctx.arctwo; ctx->block_size = ARCTWO_BLOCK_SIZE; break; default: gnutls_assert (); gnutls_free(ctx); return GNUTLS_E_INVALID_REQUEST; } *_ctx = ctx; return 0; }
/*- * _gnutls_privkey_import_system: * @pkey: The private key * @url: The URL of the key * * This function will import the given private key to the abstract * #gnutls_privkey_t type. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.4.0 * -*/ int _gnutls_privkey_import_system_url(gnutls_privkey_t pkey, const char *url) { uint8_t id[MAX_WID_SIZE]; HCERTSTORE store = NULL; size_t id_size; const CERT_CONTEXT *cert = NULL; CRYPT_HASH_BLOB blob; CRYPT_KEY_PROV_INFO *kpi = NULL; NCRYPT_KEY_HANDLE nc = NULL; NCRYPT_PROV_HANDLE sctx = NULL; DWORD kpi_size; SECURITY_STATUS r; int ret, enc_too = 0; WCHAR algo_str[64]; DWORD algo_str_size = 0; priv_st *priv; if (ncrypt_init == 0) return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); if (url == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); priv = gnutls_calloc(1, sizeof(*priv)); if (priv == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); id_size = sizeof(id); ret = get_id(url, id, &id_size, 0); if (ret < 0) return gnutls_assert_val(ret); blob.cbData = id_size; blob.pbData = id; store = CertOpenSystemStore(0, "MY"); if (store == NULL) { gnutls_assert(); ret = GNUTLS_E_FILE_ERROR; goto cleanup; } cert = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0, CERT_FIND_KEY_IDENTIFIER, &blob, NULL); if (cert == NULL) { char buf[64]; _gnutls_debug_log("cannot find ID: %s from %s\n", _gnutls_bin2hex(id, id_size, buf, sizeof(buf), NULL), url); ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); goto cleanup; } kpi_size = 0; r = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &kpi_size); if (r == 0) { _gnutls_debug_log("error in getting context: %d from %s\n", (int)GetLastError(), url); ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); goto cleanup; } kpi = gnutls_malloc(kpi_size); if (kpi == NULL) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } r = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, kpi, &kpi_size); if (r == 0) { _gnutls_debug_log("error in getting context: %d from %s\n", (int)GetLastError(), url); ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); goto cleanup; } r = pNCryptOpenStorageProvider(&sctx, kpi->pwszProvName, 0); if (FAILED(r)) { ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); goto cleanup; } r = pNCryptOpenKey(sctx, &nc, kpi->pwszContainerName, 0, 0); if (FAILED(r)) { ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); goto cleanup; } r = pNCryptGetProperty(nc, NCRYPT_ALGORITHM_PROPERTY, (BYTE*)algo_str, sizeof(algo_str), &algo_str_size, 0); if (FAILED(r)) { ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); goto cleanup; } if (StrCmpW(algo_str, BCRYPT_RSA_ALGORITHM) == 0) { priv->pk = GNUTLS_PK_RSA; priv->sign_algo = GNUTLS_SIGN_RSA_SHA256; enc_too = 1; } else if (StrCmpW(algo_str, BCRYPT_DSA_ALGORITHM) == 0) { priv->pk = GNUTLS_PK_DSA; priv->sign_algo = GNUTLS_SIGN_DSA_SHA1; } else if (StrCmpW(algo_str, BCRYPT_ECDSA_P256_ALGORITHM) == 0) { priv->pk = GNUTLS_PK_EC; priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA256; } else if (StrCmpW(algo_str, BCRYPT_ECDSA_P384_ALGORITHM) == 0) { priv->pk = GNUTLS_PK_EC; priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA384; } else if (StrCmpW(algo_str, BCRYPT_ECDSA_P521_ALGORITHM) == 0) { priv->pk = GNUTLS_PK_EC; priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA512; } else { _gnutls_debug_log("unknown key algorithm: %ls\n", algo_str); ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM); goto cleanup; } priv->nc = nc; ret = gnutls_privkey_import_ext3(pkey, priv, cng_sign, (enc_too!=0)?cng_decrypt:NULL, cng_deinit, cng_info, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = 0; cleanup: if (ret < 0) { if (nc != 0) pNCryptFreeObject(nc); gnutls_free(priv); } if (sctx != 0) pNCryptFreeObject(sctx); gnutls_free(kpi); CertCloseStore(store, 0); return ret; }
static void server (struct params_res *params) { size_t t; /* this must be called once in the program, it is mostly for the server. */ if (debug) { gnutls_global_set_log_function (tls_log_func); gnutls_global_set_log_level (2); } gnutls_global_init (); gnutls_anon_allocate_server_credentials (&anoncred); if (debug) success ("Launched, generating DH parameters...\n"); generate_dh_params (); gnutls_anon_set_server_dh_params (anoncred, dh_params); if (params->enable_db) { wrap_db_init (); } #ifdef ENABLE_SESSION_TICKET if (params->enable_session_ticket_server) gnutls_session_ticket_key_generate (&session_ticket_key); #endif for (t = 0; t < 2; t++) { client_len = sizeof (sa_cli); session = initialize_tls_session (params); sd = accept (listen_sd, (SA *) & sa_cli, &client_len); if (debug) success ("server: connection from %s, port %d\n", inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf, sizeof (topbuf)), ntohs (sa_cli.sin_port)); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); ret = gnutls_handshake (session); if (ret < 0) { close (sd); gnutls_deinit (session); fail ("server: Handshake has failed (%s)\n\n", gnutls_strerror (ret)); return; } if (debug) success ("server: Handshake was completed\n"); /* see the Getting peer's information example */ /* print_info(session); */ i = 0; for (;;) { memset (buffer, 0, MAX_BUF + 1); ret = gnutls_record_recv (session, buffer, MAX_BUF); if (ret == 0) { if (debug) success ("server: Peer has closed the GnuTLS connection\n"); break; } else if (ret < 0) { fail ("server: Received corrupted data(%d). Closing...\n", ret); break; } else if (ret > 0) { /* echo data back to the client */ gnutls_record_send (session, buffer, strlen (buffer)); } } /* do not wait for the peer to close the connection. */ gnutls_bye (session, GNUTLS_SHUT_WR); close (sd); gnutls_deinit (session); } close (listen_sd); if (params->enable_db) { wrap_db_deinit (); } gnutls_free (session_ticket_key.data); session_ticket_key.data = NULL; if (debug) success ("server: finished\n"); }
/* Decodes the PKCS #7 signed data, and returns an ASN1_TYPE, * which holds them. If raw is non null then the raw decoded * data are copied (they are locally allocated) there. */ static int _decode_pkcs7_signed_data(ASN1_TYPE pkcs7, ASN1_TYPE * sdata, gnutls_datum_t * raw) { char oid[MAX_OID_SIZE]; ASN1_TYPE c2; uint8_t *tmp = NULL; int tmp_size, len, result; len = sizeof(oid) - 1; result = asn1_read_value(pkcs7, "contentType", oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } if (strcmp(oid, SIGNED_DATA_OID) != 0) { gnutls_assert(); _gnutls_debug_log("Unknown PKCS7 Content OID '%s'\n", oid); return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE; } if ((result = asn1_create_element (_gnutls_get_pkix(), "PKIX1.pkcs-7-SignedData", &c2)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } /* the Signed-data has been created, so * decode them. */ tmp_size = 0; result = asn1_read_value(pkcs7, "content", NULL, &tmp_size); if (result != ASN1_MEM_ERROR) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } tmp = gnutls_malloc(tmp_size); if (tmp == NULL) { gnutls_assert(); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } result = asn1_read_value(pkcs7, "content", tmp, &tmp_size); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* tmp, tmp_size hold the data and the size of the CertificateSet structure * actually the ANY stuff. */ /* Step 1. In case of a signed structure extract certificate set. */ result = asn1_der_decoding(&c2, tmp, tmp_size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (raw == NULL) { gnutls_free(tmp); } else { raw->data = tmp; raw->size = tmp_size; } *sdata = c2; return 0; cleanup: if (c2) asn1_delete_structure(&c2); gnutls_free(tmp); return result; }