/** * gnutls_hex_encode - convert raw data to hex encoded * @data: contain the raw data * @result: the place where hex data will be copied * @result_size: holds the size of the result * * This function will convert the given data to printable data, using * the hex encoding, as used in the PSK password files. * * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not * long enough, or 0 on success. **/ int gnutls_hex_encode (const gnutls_datum_t * data, char *result, size_t * result_size) { size_t res = data->size + data->size + 1; if (*result_size < res) { gnutls_assert (); return GNUTLS_E_SHORT_MEMORY_BUFFER; } _gnutls_bin2hex (data->data, data->size, result, *result_size); *result_size = res; return 0; }
/* Converts a data string to an LDAP rfc2253 hex string * something like '#01020304' */ int _gnutls_x509_data2hex (const opaque * data, size_t data_size, opaque * out, size_t * sizeof_out) { char *res; char escaped[MAX_STRING_LEN]; if (2 * data_size + 1 > MAX_STRING_LEN) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } res = _gnutls_bin2hex (data, data_size, escaped, sizeof (escaped)); if (res) { unsigned int size = strlen (res) + 1; if (size + 1 > *sizeof_out) { *sizeof_out = size; return GNUTLS_E_SHORT_MEMORY_BUFFER; } *sizeof_out = size; /* -1 for the null +1 for the '#' */ if (out) { strcpy (out, "#"); strcat (out, res); } return 0; } else { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } return 0; }
/* Converts a data string to an LDAP rfc2253 hex string * something like '#01020304' */ static int data2hex(const void *data, size_t data_size, void *_out, size_t * sizeof_out) { char *res; char escaped[MAX_STRING_LEN]; unsigned int size, res_size; char *out = _out; if (2 * data_size + 1 > MAX_STRING_LEN) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } res = _gnutls_bin2hex(data, data_size, escaped, sizeof(escaped), NULL); if (!res) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } res_size = strlen(res); size = res_size + 1; /* +1 for the '#' */ if (size + 1 > *sizeof_out) { *sizeof_out = size + 1; return GNUTLS_E_SHORT_MEMORY_BUFFER; } *sizeof_out = size; /* -1 for the null +1 for the '#' */ if (out) { out[0] = '#'; memcpy(&out[1], res, res_size); out[size] = 0; } return 0; }
static int store_commitment(const char* db_name, const char* host, const char* service, time_t expiration, gnutls_digest_algorithm_t hash_algo, const gnutls_datum_t* hash) { FILE* fd; char buffer[MAX_HASH_SIZE*2+1]; fd = fopen(db_name, "ab+"); if (fd == NULL) return gnutls_assert_val(GNUTLS_E_FILE_ERROR); if (service == NULL) service = "*"; if (host == NULL) host = "*"; fprintf(fd, "|c0|%s|%s|%lu|%u|%s\n", host, service, (unsigned long)expiration, (unsigned)hash_algo, _gnutls_bin2hex(hash->data, hash->size, buffer, sizeof(buffer), NULL)); fclose(fd); return 0; }
static int generate_normal_master (gnutls_session_t session, int keep_premaster) { int ret = 0; char buf[512]; _gnutls_hard_log ("INT: PREMASTER SECRET[%d]: %s\n", PREMASTER.size, _gnutls_bin2hex (PREMASTER.data, PREMASTER.size, buf, sizeof (buf), NULL)); _gnutls_hard_log ("INT: CLIENT RANDOM[%d]: %s\n", 32, _gnutls_bin2hex (session-> security_parameters.client_random, 32, buf, sizeof (buf), NULL)); _gnutls_hard_log ("INT: SERVER RANDOM[%d]: %s\n", 32, _gnutls_bin2hex (session-> security_parameters.server_random, 32, buf, sizeof (buf), NULL)); if (gnutls_protocol_get_version (session) == GNUTLS_SSL3) { opaque rnd[2 * GNUTLS_RANDOM_SIZE + 1]; memcpy (rnd, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy (&rnd[GNUTLS_RANDOM_SIZE], session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); ret = _gnutls_ssl3_generate_random (PREMASTER.data, PREMASTER.size, rnd, 2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE, session-> security_parameters.master_secret); } else { opaque rnd[2 * GNUTLS_RANDOM_SIZE + 1]; memcpy (rnd, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy (&rnd[GNUTLS_RANDOM_SIZE], session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); ret = _gnutls_PRF (session, PREMASTER.data, PREMASTER.size, MASTER_SECRET, MASTER_SECRET_SIZE, rnd, 2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE, session->security_parameters.master_secret); } if (!keep_premaster) _gnutls_free_datum (&PREMASTER); if (ret < 0) return ret; _gnutls_hard_log ("INT: MASTER SECRET: %s\n", _gnutls_bin2hex (session-> security_parameters.master_secret, GNUTLS_MASTER_SIZE, buf, sizeof (buf), NULL)); return ret; }
static int parse_commitment_line(char* line, const char* host, size_t host_len, const char* service, size_t service_len, time_t now, const gnutls_datum_t *skey) { char* p, *kp; char* savep = NULL; size_t kp_len, phash_size; time_t expiration; int ret; gnutls_digest_algorithm_t hash_algo; uint8_t phash[MAX_HASH_SIZE]; uint8_t hphash[MAX_HASH_SIZE*2+1]; /* read host */ p = strtok_r(line, "|", &savep); if (p == NULL) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); if (p[0] != '*' && strcmp(p, host) != 0) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); /* read service */ p = strtok_r(NULL, "|", &savep); if (p == NULL) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); if (p[0] != '*' && strcmp(p, service) != 0) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); /* read expiration */ p = strtok_r(NULL, "|", &savep); if (p == NULL) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); expiration = (time_t)atol(p); if (expiration > 0 && now > expiration) return gnutls_assert_val(GNUTLS_E_EXPIRED); /* read hash algorithm */ p = strtok_r(NULL, "|", &savep); if (p == NULL) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); hash_algo = (time_t)atol(p); if (_gnutls_digest_get_name(hash_algo) == NULL) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); /* read hash */ kp = strtok_r(NULL, "|", &savep); if (kp == NULL) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); p = strpbrk(kp, "\n \r\t|"); if (p != NULL) *p = 0; /* hash and hex encode */ ret = _gnutls_hash_fast (hash_algo, skey->data, skey->size, phash); if (ret < 0) return gnutls_assert_val(ret); phash_size = _gnutls_hash_get_algo_len(hash_algo); p = _gnutls_bin2hex (phash, phash_size,(void*) hphash, sizeof(hphash), NULL); if (p == NULL) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); kp_len = strlen(kp); if (kp_len != phash_size*2) return gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH); if (memcmp(kp, hphash, kp_len) != 0) return gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH); /* key found and matches */ return 0; }
/* This function is to be called after handshake, when master_secret, * client_random and server_random have been initialized. * This function creates the keys and stores them into pending session. * (session->cipher_specs) */ static int _gnutls_set_keys (gnutls_session_t session, record_parameters_st * params, int hash_size, int IV_size, int key_size, int export_flag) { /* FIXME: This function is too long */ opaque rnd[2 * GNUTLS_RANDOM_SIZE]; opaque rrnd[2 * GNUTLS_RANDOM_SIZE]; int pos, ret; int block_size; char buf[65]; /* avoid using malloc */ opaque key_block[2 * MAX_HASH_SIZE + 2 * MAX_CIPHER_KEY_SIZE + 2 * MAX_CIPHER_BLOCK_SIZE]; record_state_st *client_write, *server_write; client_write = session->security_parameters.entity == GNUTLS_CLIENT ? ¶ms->write : ¶ms->read; server_write = session->security_parameters.entity == GNUTLS_SERVER ? ¶ms->write : ¶ms->read; block_size = 2 * hash_size + 2 * key_size; if (export_flag == 0) block_size += 2 * IV_size; memcpy (rnd, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); memcpy (&rnd[GNUTLS_RANDOM_SIZE], session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy (rrnd, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy (&rrnd[GNUTLS_RANDOM_SIZE], session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); if (session->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ ret = _gnutls_ssl3_generate_random (session->security_parameters.master_secret, GNUTLS_MASTER_SIZE, rnd, 2 * GNUTLS_RANDOM_SIZE, block_size, key_block); } else { /* TLS 1.0 */ ret = _gnutls_PRF (session, session->security_parameters.master_secret, GNUTLS_MASTER_SIZE, keyexp, keyexp_length, rnd, 2 * GNUTLS_RANDOM_SIZE, block_size, key_block); } if (ret < 0) return gnutls_assert_val (ret); _gnutls_hard_log ("INT: KEY BLOCK[%d]: %s\n", block_size, _gnutls_bin2hex (key_block, block_size, buf, sizeof (buf), NULL)); pos = 0; if (hash_size > 0) { if (_gnutls_sset_datum (&client_write->mac_secret, &key_block[pos], hash_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); pos += hash_size; if (_gnutls_sset_datum (&server_write->mac_secret, &key_block[pos], hash_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); pos += hash_size; } if (key_size > 0) { opaque key1[EXPORT_FINAL_KEY_SIZE]; opaque key2[EXPORT_FINAL_KEY_SIZE]; opaque *client_write_key, *server_write_key; int client_write_key_size, server_write_key_size; if (export_flag == 0) { client_write_key = &key_block[pos]; client_write_key_size = key_size; pos += key_size; server_write_key = &key_block[pos]; server_write_key_size = key_size; pos += key_size; } else { /* export */ client_write_key = key1; server_write_key = key2; /* generate the final keys */ if (session->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ ret = _gnutls_ssl3_hash_md5 (&key_block[pos], key_size, rrnd, 2 * GNUTLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, client_write_key); } else { /* TLS 1.0 */ ret = _gnutls_PRF (session, &key_block[pos], key_size, cliwrite, cliwrite_length, rrnd, 2 * GNUTLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, client_write_key); } if (ret < 0) return gnutls_assert_val (ret); client_write_key_size = EXPORT_FINAL_KEY_SIZE; pos += key_size; if (session->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ ret = _gnutls_ssl3_hash_md5 (&key_block[pos], key_size, rnd, 2 * GNUTLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, server_write_key); } else { /* TLS 1.0 */ ret = _gnutls_PRF (session, &key_block[pos], key_size, servwrite, servwrite_length, rrnd, 2 * GNUTLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, server_write_key); } if (ret < 0) return gnutls_assert_val (ret); server_write_key_size = EXPORT_FINAL_KEY_SIZE; pos += key_size; } if (_gnutls_sset_datum (&client_write->key, client_write_key, client_write_key_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); _gnutls_hard_log ("INT: CLIENT WRITE KEY [%d]: %s\n", client_write_key_size, _gnutls_bin2hex (client_write_key, client_write_key_size, buf, sizeof (buf), NULL)); if (_gnutls_sset_datum (&server_write->key, server_write_key, server_write_key_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); _gnutls_hard_log ("INT: SERVER WRITE KEY [%d]: %s\n", server_write_key_size, _gnutls_bin2hex (server_write_key, server_write_key_size, buf, sizeof (buf), NULL)); } /* IV generation in export and non export ciphers. */ if (IV_size > 0 && export_flag == 0) { if (_gnutls_sset_datum (&client_write->IV, &key_block[pos], IV_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); pos += IV_size; if (_gnutls_sset_datum (&server_write->IV, &key_block[pos], IV_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); pos += IV_size; } else if (IV_size > 0 && export_flag != 0) { opaque iv_block[MAX_CIPHER_BLOCK_SIZE * 2]; if (session->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ ret = _gnutls_ssl3_hash_md5 ("", 0, rrnd, GNUTLS_RANDOM_SIZE * 2, IV_size, iv_block); if (ret < 0) return gnutls_assert_val (ret); ret = _gnutls_ssl3_hash_md5 ("", 0, rnd, GNUTLS_RANDOM_SIZE * 2, IV_size, &iv_block[IV_size]); } else { /* TLS 1.0 */ ret = _gnutls_PRF (session, "", 0, ivblock, ivblock_length, rrnd, 2 * GNUTLS_RANDOM_SIZE, IV_size * 2, iv_block); } if (ret < 0) return gnutls_assert_val (ret); if (_gnutls_sset_datum (&client_write->IV, iv_block, IV_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); if (_gnutls_sset_datum (&server_write->IV, &iv_block[IV_size], IV_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); } return 0; }
/* Converts a parsed gnutls_openpgp_crt_t to a gnutls_cert structure. */ int _gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert) { int ret; gnutls_openpgp_keyid_t keyid; char err_buf[33]; memset (gcert, 0, sizeof (gnutls_cert)); gcert->cert_type = GNUTLS_CRT_OPENPGP; gcert->version = gnutls_openpgp_crt_get_version (cert); gcert->params_size = MAX_PUBLIC_PARAMS_SIZE; ret = gnutls_openpgp_crt_get_preferred_key_id (cert, keyid); if (ret == 0) { int idx; uint32_t kid32[2]; _gnutls_debug_log ("Importing Openpgp cert and using openpgp sub key: %s\n", _gnutls_bin2hex (keyid, sizeof (keyid), err_buf, sizeof (err_buf))); KEYID_IMPORT (kid32, keyid); idx = gnutls_openpgp_crt_get_subkey_idx (cert, keyid); if (idx < 0) { gnutls_assert (); return idx; } gcert->subject_pk_algorithm = gnutls_openpgp_crt_get_subkey_pk_algorithm (cert, idx, NULL); gnutls_openpgp_crt_get_subkey_usage (cert, idx, &gcert->key_usage); gcert->use_subkey = 1; memcpy (gcert->subkey_id, keyid, sizeof (keyid)); ret = _gnutls_openpgp_crt_get_mpis (cert, kid32, gcert->params, &gcert->params_size); } else { _gnutls_debug_log ("Importing Openpgp cert and using main openpgp key\n"); gcert->subject_pk_algorithm = gnutls_openpgp_crt_get_pk_algorithm (cert, NULL); gnutls_openpgp_crt_get_key_usage (cert, &gcert->key_usage); ret = _gnutls_openpgp_crt_get_mpis (cert, NULL, gcert->params, &gcert->params_size); gcert->use_subkey = 0; } if (ret < 0) { gnutls_assert (); return ret; } { /* copy the raw certificate */ #define SMALL_RAW 512 opaque *raw; size_t raw_size = SMALL_RAW; /* initially allocate a bogus size, just in case the certificate * fits in it. That way we minimize the DER encodings performed. */ raw = gnutls_malloc (raw_size); if (raw == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } ret = gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, raw, &raw_size); if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { gnutls_assert (); gnutls_free (raw); return ret; } if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { raw = gnutls_realloc (raw, raw_size); if (raw == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } ret = gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, raw, &raw_size); if (ret < 0) { gnutls_assert (); gnutls_free (raw); return ret; } } gcert->raw.data = raw; gcert->raw.size = raw_size; } return 0; }
/* Send the first key exchange message ( g, n, s) and append the verifier algorithm number * Data is allocated by the caller, and should have data_size size. */ int _gnutls_gen_srp_server_kx (gnutls_session_t session, opaque ** data) { int ret; uint8_t *data_n, *data_s; uint8_t *data_g; char *username; SRP_PWD_ENTRY *pwd_entry; srp_server_auth_info_t info; ssize_t data_size; size_t n_b, tmp_size; char buf[64]; uint8_t *data_b; if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_SRP, sizeof (srp_server_auth_info_st), 1)) < 0) { gnutls_assert (); return ret; } info = _gnutls_get_auth_info (session); username = info->username; _gnutls_str_cpy (username, MAX_SRP_USERNAME, session->security_parameters.extensions.srp_username); ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry); if (ret < 0) { gnutls_assert (); return ret; } /* copy from pwd_entry to local variables (actually in session) */ tmp_size = pwd_entry->g.size; if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } tmp_size = pwd_entry->n.size; if (_gnutls_mpi_scan_nz (&N, pwd_entry->n.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } tmp_size = pwd_entry->v.size; if (_gnutls_mpi_scan_nz (&V, pwd_entry->v.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* Calculate: B = (k*v + g^b) % N */ B = _gnutls_calc_srp_B (&_b, G, N, V); if (B == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } if (_gnutls_mpi_print (NULL, &n_b, B) != 0) { gnutls_assert (); return GNUTLS_E_MPI_PRINT_FAILED; } /* Allocate size to hold the N, g, s, B */ data_size = (pwd_entry->n.size + 2 + pwd_entry->g.size + 2 + pwd_entry->salt.size + 1) + (n_b + 2); (*data) = gnutls_malloc (data_size); if ((*data) == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* copy N (mod n) */ data_n = *data; _gnutls_write_datum16 (data_n, pwd_entry->n); /* copy G (generator) to data */ data_g = &data_n[2 + pwd_entry->n.size]; _gnutls_write_datum16 (data_g, pwd_entry->g); /* copy the salt */ data_s = &data_g[2 + pwd_entry->g.size]; _gnutls_write_datum8 (data_s, pwd_entry->salt); /* Copy the B value */ data_b = &data_s[1 + pwd_entry->salt.size]; if (_gnutls_mpi_print (&data_b[2], &n_b, B) != 0) { gnutls_assert(); return GNUTLS_E_MPI_PRINT_FAILED; } _gnutls_write_uint16 (n_b, data_b); _gnutls_hard_log ("INT: SRP B[%d]: %s\n", n_b, _gnutls_bin2hex (&data_b[2], n_b, buf, sizeof (buf))); _gnutls_srp_entry_free (pwd_entry); return data_size; }
void doit (void) { int rc, i, j, x; char key[32]; char tmp[1024]; gnutls_global_init (); gnutls_global_set_log_function (tls_log_func); if (debug) gnutls_global_set_log_level (99); x = 0; for (i = 1; i < 4; i++) { for (j = 0; j < 3; j++) { rc = _gnutls_pkcs12_string_to_key (i, salt[j], strlen (salt[j]), j + i + 15, pw[j], sizeof (key), key); if (rc < 0) fail ("_gnutls_pkcs12_string_to_key failed[0]: %d\n", rc); if (strcmp (_gnutls_bin2hex (key, sizeof (key), tmp, sizeof (tmp), NULL), values[x]) != 0) fail ("_gnutls_pkcs12_string_to_key failed[1]\n"); if (debug) printf ("ij: %d.%d: %s\n", i, j, _gnutls_bin2hex (key, sizeof (key), tmp, sizeof (tmp), NULL)); x++; } } if (debug) printf ("\n"); for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) { rc = _gnutls_pkcs12_string_to_key (tv[i].id, tv[i].salt, 8, tv[i].iter, tv[i].password, tv[i].keylen, key); if (rc < 0) fail ("_gnutls_pkcs12_string_to_key failed[2]: %d\n", rc); if (memcmp (_gnutls_bin2hex (key, tv[i].keylen, tmp, sizeof (tmp), NULL), tv[i].key, tv[i].keylen) != 0) fail ("_gnutls_pkcs12_string_to_key failed[3]\n"); if (debug) printf ("tv[%d]: %s\n", i, _gnutls_bin2hex (key, tv[i].keylen, tmp, sizeof (tmp), NULL)); } if (debug) printf ("\n"); gnutls_global_deinit (); if (debug) success ("_gnutls_pkcs12_string_to_key ok\n"); }
static int append_elements(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, gnutls_buffer_st *str, int k1, unsigned last) { int k2, result, max_k2; int len; uint8_t value[MAX_STRING_LEN]; char tmpbuffer1[ASN1_MAX_NAME_SIZE]; char tmpbuffer2[ASN1_MAX_NAME_SIZE]; char tmpbuffer3[ASN1_MAX_NAME_SIZE]; const char *ldap_desc; char oid[MAX_OID_SIZE]; gnutls_datum_t td = { NULL, 0 }; gnutls_datum_t tvd = { NULL, 0 }; /* create a string like "tbsCertList.issuer.rdnSequence.?1" */ if (asn1_rdn_name[0] != 0) snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u", asn1_rdn_name, k1); else snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u", k1); len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len); if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */ gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } k2 = 0; result = asn1_number_of_elements(asn1_struct, tmpbuffer1, &max_k2); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } do { /* Move to the attibute type and values */ k2++; if (tmpbuffer1[0] != 0) snprintf(tmpbuffer2, sizeof(tmpbuffer2), "%s.?%u", tmpbuffer1, k2); else snprintf(tmpbuffer2, sizeof(tmpbuffer2), "?%u", k2); /* Try to read the RelativeDistinguishedName attributes. */ len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer2, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */ gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the OID */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type"); len = sizeof(oid) - 1; result = asn1_read_value(asn1_struct, tmpbuffer3, oid, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; else if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the Value */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".value"); len = 0; result = _gnutls_x509_read_value(asn1_struct, tmpbuffer3, &tvd); if (result < 0) { gnutls_assert(); goto cleanup; } #define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( str, y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } #define DATA_APPEND(x,y) if ((result=_gnutls_buffer_append_data( str, x,y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } /* The encodings of adjoining RelativeDistinguishedNames are separated * by a comma character (',' ASCII 44). */ ldap_desc = gnutls_x509_dn_oid_name(oid, GNUTLS_X509_DN_OID_RETURN_OID); STR_APPEND(ldap_desc); STR_APPEND("="); result = _gnutls_x509_dn_to_string(oid, tvd.data, tvd.size, &td); if (result < 0) { gnutls_assert(); _gnutls_debug_log ("Cannot parse OID: '%s' with value '%s'\n", oid, _gnutls_bin2hex(tvd.data, tvd.size, tmpbuffer3, sizeof (tmpbuffer3), NULL)); goto cleanup; } DATA_APPEND(td.data, td.size); _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); /* Where there is a multi-valued RDN, the outputs from adjoining * AttributeTypeAndValues are separated by a plus ('+' ASCII 43) * character. */ if (k2 < max_k2) { STR_APPEND("+"); } else if (!last) { STR_APPEND(","); } } while (1); result = 0; cleanup: _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); return result; }
/** * gnutls_openpgp_privkey_sign_hash: * @key: Holds the key * @hash: holds the data to be signed * @signature: will contain newly allocated signature * * This function will sign the given hash using the private key. You * should use gnutls_openpgp_privkey_set_preferred_key_id() before * calling this function to set the subkey to use. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Deprecated: Use gnutls_privkey_sign_hash() instead. */ int gnutls_openpgp_privkey_sign_hash(gnutls_openpgp_privkey_t key, const gnutls_datum_t * hash, gnutls_datum_t * signature) { int result; gnutls_pk_params_st params; int pk_algorithm; uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; char buf[2 * GNUTLS_OPENPGP_KEYID_SIZE + 1]; if (key == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } result = gnutls_openpgp_privkey_get_preferred_key_id(key, keyid); if (result == 0) { uint32_t kid[2]; int idx; KEYID_IMPORT(kid, keyid); _gnutls_hard_log("Signing using PGP key ID %s\n", _gnutls_bin2hex(keyid, GNUTLS_OPENPGP_KEYID_SIZE, buf, sizeof(buf), NULL)); idx = gnutls_openpgp_privkey_get_subkey_idx(key, keyid); pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm(key, idx, NULL); result = _gnutls_openpgp_privkey_get_mpis(key, kid, ¶ms); } else { _gnutls_hard_log("Signing using master PGP key\n"); pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm(key, NULL); result = _gnutls_openpgp_privkey_get_mpis(key, NULL, ¶ms); } if (result < 0) { gnutls_assert(); return result; } result = _gnutls_pk_sign(pk_algorithm, signature, hash, ¶ms); gnutls_pk_params_clear(¶ms); gnutls_pk_params_release(¶ms); if (result < 0) { gnutls_assert(); return result; } return 0; }
/* This function is to be called after handshake, when master_secret, * client_random and server_random have been initialized. * This function creates the keys and stores them into pending session. * (session->cipher_specs) */ int _gnutls_set_keys (gnutls_session_t session, int hash_size, int IV_size, int key_size, int export_flag) { /* FIXME: This function is too long */ opaque *key_block; opaque rnd[2 * TLS_RANDOM_SIZE]; opaque rrnd[2 * TLS_RANDOM_SIZE]; int pos, ret; int block_size; char buf[65]; if (session->cipher_specs.generated_keys != 0) { /* keys have already been generated. * reset generated_keys and exit normally. */ session->cipher_specs.generated_keys = 0; return 0; } block_size = 2 * hash_size + 2 * key_size; if (export_flag == 0) block_size += 2 * IV_size; key_block = gnutls_secure_malloc (block_size); if (key_block == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } memcpy (rnd, session->security_parameters.server_random, TLS_RANDOM_SIZE); memcpy (&rnd[TLS_RANDOM_SIZE], session->security_parameters.client_random, TLS_RANDOM_SIZE); memcpy (rrnd, session->security_parameters.client_random, TLS_RANDOM_SIZE); memcpy (&rrnd[TLS_RANDOM_SIZE], session->security_parameters.server_random, TLS_RANDOM_SIZE); if (session->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ ret = _gnutls_ssl3_generate_random (session-> security_parameters. master_secret, TLS_MASTER_SIZE, rnd, 2 * TLS_RANDOM_SIZE, block_size, key_block); } else { /* TLS 1.0 */ ret = _gnutls_PRF (session, session->security_parameters.master_secret, TLS_MASTER_SIZE, keyexp, keyexp_length, rnd, 2 * TLS_RANDOM_SIZE, block_size, key_block); } if (ret < 0) { gnutls_assert (); gnutls_free (key_block); return ret; } _gnutls_hard_log ("INT: KEY BLOCK[%d]: %s\n", block_size, _gnutls_bin2hex (key_block, block_size, buf, sizeof (buf))); pos = 0; if (hash_size > 0) { if (_gnutls_sset_datum (&session->cipher_specs.client_write_mac_secret, &key_block[pos], hash_size) < 0) { gnutls_free (key_block); return GNUTLS_E_MEMORY_ERROR; } pos += hash_size; if (_gnutls_sset_datum (&session->cipher_specs.server_write_mac_secret, &key_block[pos], hash_size) < 0) { gnutls_free (key_block); return GNUTLS_E_MEMORY_ERROR; } pos += hash_size; } if (key_size > 0) { opaque *client_write_key, *server_write_key; int client_write_key_size, server_write_key_size; int free_keys = 0; if (export_flag == 0) { client_write_key = &key_block[pos]; client_write_key_size = key_size; pos += key_size; server_write_key = &key_block[pos]; server_write_key_size = key_size; pos += key_size; } else { /* export */ free_keys = 1; client_write_key = gnutls_secure_malloc (EXPORT_FINAL_KEY_SIZE); if (client_write_key == NULL) { gnutls_assert (); gnutls_free (key_block); return GNUTLS_E_MEMORY_ERROR; } server_write_key = gnutls_secure_malloc (EXPORT_FINAL_KEY_SIZE); if (server_write_key == NULL) { gnutls_assert (); gnutls_free (key_block); gnutls_free (client_write_key); return GNUTLS_E_MEMORY_ERROR; } /* generate the final keys */ if (session->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ ret = _gnutls_ssl3_hash_md5 (&key_block[pos], key_size, rrnd, 2 * TLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, client_write_key); } else { /* TLS 1.0 */ ret = _gnutls_PRF (session, &key_block[pos], key_size, cliwrite, cliwrite_length, rrnd, 2 * TLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, client_write_key); } if (ret < 0) { gnutls_assert (); gnutls_free (key_block); gnutls_free (server_write_key); gnutls_free (client_write_key); return ret; } client_write_key_size = EXPORT_FINAL_KEY_SIZE; pos += key_size; if (session->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ ret = _gnutls_ssl3_hash_md5 (&key_block[pos], key_size, rnd, 2 * TLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, server_write_key); } else { /* TLS 1.0 */ ret = _gnutls_PRF (session, &key_block[pos], key_size, servwrite, servwrite_length, rrnd, 2 * TLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, server_write_key); } if (ret < 0) { gnutls_assert (); gnutls_free (key_block); gnutls_free (server_write_key); gnutls_free (client_write_key); return ret; } server_write_key_size = EXPORT_FINAL_KEY_SIZE; pos += key_size; } if (_gnutls_sset_datum (&session->cipher_specs.client_write_key, client_write_key, client_write_key_size) < 0) { gnutls_free (key_block); gnutls_free (server_write_key); gnutls_free (client_write_key); return GNUTLS_E_MEMORY_ERROR; } _gnutls_hard_log ("INT: CLIENT WRITE KEY [%d]: %s\n", client_write_key_size, _gnutls_bin2hex (client_write_key, client_write_key_size, buf, sizeof (buf))); if (_gnutls_sset_datum (&session->cipher_specs.server_write_key, server_write_key, server_write_key_size) < 0) { gnutls_free (key_block); gnutls_free (server_write_key); gnutls_free (client_write_key); return GNUTLS_E_MEMORY_ERROR; } _gnutls_hard_log ("INT: SERVER WRITE KEY [%d]: %s\n", server_write_key_size, _gnutls_bin2hex (server_write_key, server_write_key_size, buf, sizeof (buf))); if (free_keys != 0) { gnutls_free (server_write_key); gnutls_free (client_write_key); } } /* IV generation in export and non export ciphers. */ if (IV_size > 0 && export_flag == 0) { if (_gnutls_sset_datum (&session->cipher_specs.client_write_IV, &key_block[pos], IV_size) < 0) { gnutls_free (key_block); return GNUTLS_E_MEMORY_ERROR; } pos += IV_size; if (_gnutls_sset_datum (&session->cipher_specs.server_write_IV, &key_block[pos], IV_size) < 0) { gnutls_free (key_block); return GNUTLS_E_MEMORY_ERROR; } pos += IV_size; } else if (IV_size > 0 && export_flag != 0) { opaque *iv_block = gnutls_alloca (IV_size * 2); if (iv_block == NULL) { gnutls_assert (); gnutls_free (key_block); return GNUTLS_E_MEMORY_ERROR; } if (session->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ ret = _gnutls_ssl3_hash_md5 ("", 0, rrnd, TLS_RANDOM_SIZE * 2, IV_size, iv_block); if (ret < 0) { gnutls_assert (); gnutls_free (key_block); gnutls_afree (iv_block); return ret; } ret = _gnutls_ssl3_hash_md5 ("", 0, rnd, TLS_RANDOM_SIZE * 2, IV_size, &iv_block[IV_size]); } else { /* TLS 1.0 */ ret = _gnutls_PRF (session, "", 0, ivblock, ivblock_length, rrnd, 2 * TLS_RANDOM_SIZE, IV_size * 2, iv_block); } if (ret < 0) { gnutls_assert (); gnutls_afree (iv_block); gnutls_free (key_block); return ret; } if (_gnutls_sset_datum (&session->cipher_specs.client_write_IV, iv_block, IV_size) < 0) { gnutls_afree (iv_block); gnutls_free (key_block); return GNUTLS_E_MEMORY_ERROR; } if (_gnutls_sset_datum (&session->cipher_specs.server_write_IV, &iv_block[IV_size], IV_size) < 0) { gnutls_afree (iv_block); gnutls_free (key_block); return GNUTLS_E_MEMORY_ERROR; } gnutls_afree (iv_block); } gnutls_free (key_block); session->cipher_specs.generated_keys = 1; return 0; }
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; }
/*- * _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) { #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); #else 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; HCRYPTPROV hCryptProv = 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; DWORD i, dwErrCode = 0; 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 = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, L"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)) { /* if this works carry on with CNG */ 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; } } else { /* this should be CAPI */ _gnutls_debug_log ("error in opening CNG keystore: %x from %ls\n", (int)r, kpi->pwszProvName); if (CryptAcquireContextW(&hCryptProv, kpi->pwszContainerName, kpi->pwszProvName, kpi->dwProvType, kpi->dwFlags)) { for (i = 0; i < kpi->cProvParam; i++) if (!CryptSetProvParam(hCryptProv, kpi->rgProvParam[i]. dwParam, kpi->rgProvParam[i]. pbData, kpi->rgProvParam[i]. dwFlags)) { dwErrCode = GetLastError(); break; }; } else { dwErrCode = GetLastError(); } if (ERROR_SUCCESS != dwErrCode) { _gnutls_debug_log ("error in getting cryptprov: %d from %s\n", (int)GetLastError(), url); ret = gnutls_assert_val (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); goto cleanup; } { BYTE buf[100 + sizeof(PROV_ENUMALGS_EX) * 2]; PROV_ENUMALGS_EX *pAlgo = (PROV_ENUMALGS_EX *) buf; DWORD len = sizeof(buf); if (CryptGetProvParam (hCryptProv, PP_ENUMALGS_EX, buf, &len, CRYPT_FIRST)) { DWORD hash = 0; do { switch (pAlgo->aiAlgid) { case CALG_RSA_SIGN: priv->pk = GNUTLS_PK_RSA; enc_too = 1; break; case CALG_DSS_SIGN: priv->pk = priv->pk == GNUTLS_PK_RSA ? GNUTLS_PK_RSA : GNUTLS_PK_DSA; break; case CALG_SHA1: hash = 1; break; case CALG_SHA_256: hash = 256; break; default: break; } len = sizeof(buf); // reset the buffer size } while (CryptGetProvParam (hCryptProv, PP_ENUMALGS_EX, buf, &len, CRYPT_NEXT)); if (priv->pk == GNUTLS_PK_DSA) priv->sign_algo = GNUTLS_SIGN_DSA_SHA1; else priv->sign_algo = (hash > 1) ? GNUTLS_SIGN_RSA_SHA256 : GNUTLS_SIGN_RSA_SHA1; } } priv->hCryptProv = hCryptProv; priv->dwKeySpec = kpi->dwKeySpec; ret = gnutls_privkey_import_ext3(pkey, priv, capi_sign, (enc_too != 0) ? capi_decrypt : NULL, capi_deinit, capi_info, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } } ret = 0; cleanup: if (ret < 0) { if (nc != 0) pNCryptFreeObject(nc); if (hCryptProv != 0) CryptReleaseContext(hCryptProv, 0); gnutls_free(priv); } if (sctx != 0) pNCryptFreeObject(sctx); gnutls_free(kpi); if (cert != 0) CertFreeCertificateContext(cert); CertCloseStore(store, 0); return ret; #endif }
/*- * _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; }
/* This function is to be called after handshake, when master_secret, * client_random and server_random have been initialized. * This function creates the keys and stores them into pending session. * (session->cipher_specs) */ static int _gnutls_set_keys(gnutls_session_t session, record_parameters_st * params, int hash_size, int IV_size, int key_size) { /* FIXME: This function is too long */ uint8_t rnd[2 * GNUTLS_RANDOM_SIZE]; uint8_t rrnd[2 * GNUTLS_RANDOM_SIZE]; int pos, ret; int block_size; char buf[65]; /* avoid using malloc */ uint8_t key_block[2 * MAX_HASH_SIZE + 2 * MAX_CIPHER_KEY_SIZE + 2 * MAX_CIPHER_BLOCK_SIZE]; record_state_st *client_write, *server_write; if (session->security_parameters.entity == GNUTLS_CLIENT) { client_write = ¶ms->write; server_write = ¶ms->read; } else { client_write = ¶ms->read; server_write = ¶ms->write; } block_size = 2 * hash_size + 2 * key_size; block_size += 2 * IV_size; memcpy(rnd, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); memcpy(&rnd[GNUTLS_RANDOM_SIZE], session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy(rrnd, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy(&rrnd[GNUTLS_RANDOM_SIZE], session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); if (get_num_version(session) == GNUTLS_SSL3) { /* SSL 3 */ ret = _gnutls_ssl3_generate_random (session->security_parameters.master_secret, GNUTLS_MASTER_SIZE, rnd, 2 * GNUTLS_RANDOM_SIZE, block_size, key_block); } else { /* TLS 1.0 */ ret = _gnutls_PRF(session, session->security_parameters.master_secret, GNUTLS_MASTER_SIZE, keyexp, keyexp_length, rnd, 2 * GNUTLS_RANDOM_SIZE, block_size, key_block); } if (ret < 0) return gnutls_assert_val(ret); _gnutls_hard_log("INT: KEY BLOCK[%d]: %s\n", block_size, _gnutls_bin2hex(key_block, block_size, buf, sizeof(buf), NULL)); pos = 0; if (hash_size > 0) { if (_gnutls_set_datum (&client_write->mac_secret, &key_block[pos], hash_size) < 0) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); pos += hash_size; if (_gnutls_set_datum (&server_write->mac_secret, &key_block[pos], hash_size) < 0) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); pos += hash_size; } if (key_size > 0) { uint8_t *client_write_key, *server_write_key; int client_write_key_size, server_write_key_size; client_write_key = &key_block[pos]; client_write_key_size = key_size; pos += key_size; server_write_key = &key_block[pos]; server_write_key_size = key_size; pos += key_size; if (_gnutls_set_datum (&client_write->key, client_write_key, client_write_key_size) < 0) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); _gnutls_hard_log("INT: CLIENT WRITE KEY [%d]: %s\n", client_write_key_size, _gnutls_bin2hex(client_write_key, client_write_key_size, buf, sizeof(buf), NULL)); if (_gnutls_set_datum (&server_write->key, server_write_key, server_write_key_size) < 0) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); _gnutls_hard_log("INT: SERVER WRITE KEY [%d]: %s\n", server_write_key_size, _gnutls_bin2hex(server_write_key, server_write_key_size, buf, sizeof(buf), NULL)); } /* IV generation in export and non export ciphers. */ if (IV_size > 0) { if (_gnutls_set_datum (&client_write->IV, &key_block[pos], IV_size) < 0) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); pos += IV_size; if (_gnutls_set_datum (&server_write->IV, &key_block[pos], IV_size) < 0) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); _gnutls_hard_log("INT: CLIENT WRITE IV [%d]: %s\n", client_write->IV.size, _gnutls_bin2hex(client_write->IV.data, client_write->IV.size, buf, sizeof(buf), NULL)); _gnutls_hard_log("INT: SERVER WRITE IV [%d]: %s\n", server_write->IV.size, _gnutls_bin2hex(server_write->IV.data, server_write->IV.size, buf, sizeof(buf), NULL)); } return 0; }
/*- * _gnutls_openpgp_privkey_decrypt_data: * @key: Holds the key * @flags: (0) for now * @ciphertext: holds the data to be decrypted * @plaintext: will contain newly allocated plaintext * * This function will sign the given hash using the private key. You * should use gnutls_openpgp_privkey_set_preferred_key_id() before * calling this function to set the subkey to use. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. -*/ int _gnutls_openpgp_privkey_decrypt_data(gnutls_openpgp_privkey_t key, unsigned int flags, const gnutls_datum_t * ciphertext, gnutls_datum_t * plaintext) { int result, i; gnutls_pk_params_st params; int pk_algorithm; uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; char buf[2 * GNUTLS_OPENPGP_KEYID_SIZE + 1]; if (key == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } result = gnutls_openpgp_privkey_get_preferred_key_id(key, keyid); if (result == 0) { uint32_t kid[2]; KEYID_IMPORT(kid, keyid); _gnutls_hard_log("Decrypting using PGP key ID %s\n", _gnutls_bin2hex(keyid, GNUTLS_OPENPGP_KEYID_SIZE, buf, sizeof(buf), NULL)); result = _gnutls_openpgp_privkey_get_mpis(key, kid, ¶ms); i = gnutls_openpgp_privkey_get_subkey_idx(key, keyid); pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm(key, i, NULL); } else { _gnutls_hard_log("Decrypting using master PGP key\n"); pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm(key, NULL); result = _gnutls_openpgp_privkey_get_mpis(key, NULL, ¶ms); } if (result < 0) { gnutls_assert(); return result; } result = _gnutls_pk_decrypt(pk_algorithm, plaintext, ciphertext, ¶ms); gnutls_pk_params_clear(¶ms); gnutls_pk_params_release(¶ms); if (result < 0) return gnutls_assert_val(result); return 0; }
/* here we generate the TLS Master secret. */ static int generate_normal_master(gnutls_session_t session, gnutls_datum_t * premaster, int keep_premaster) { int ret = 0; char buf[512]; _gnutls_hard_log("INT: PREMASTER SECRET[%d]: %s\n", premaster->size, _gnutls_bin2hex(premaster->data, premaster->size, buf, sizeof(buf), NULL)); _gnutls_hard_log("INT: CLIENT RANDOM[%d]: %s\n", 32, _gnutls_bin2hex(session->security_parameters. client_random, 32, buf, sizeof(buf), NULL)); _gnutls_hard_log("INT: SERVER RANDOM[%d]: %s\n", 32, _gnutls_bin2hex(session->security_parameters. server_random, 32, buf, sizeof(buf), NULL)); if (session->security_parameters.ext_master_secret == 0) { uint8_t rnd[2 * GNUTLS_RANDOM_SIZE + 1]; memcpy(rnd, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy(&rnd[GNUTLS_RANDOM_SIZE], session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); #ifdef ENABLE_SSL3 if (get_num_version(session) == GNUTLS_SSL3) { ret = _gnutls_ssl3_generate_random(premaster->data, premaster->size, rnd, 2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE, session->security_parameters. master_secret); } else #endif ret = _gnutls_PRF(session, premaster->data, premaster->size, MASTER_SECRET, MASTER_SECRET_SIZE, rnd, 2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE, session->security_parameters. master_secret); } else { gnutls_datum_t shash = {NULL, 0}; /* draft-ietf-tls-session-hash-02 */ ret = _gnutls_handshake_get_session_hash(session, &shash); if (ret < 0) return gnutls_assert_val(ret); #ifdef ENABLE_SSL3 if (get_num_version(session) == GNUTLS_SSL3) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); #endif ret = _gnutls_PRF(session, premaster->data, premaster->size, EXT_MASTER_SECRET, EXT_MASTER_SECRET_SIZE, shash.data, shash.size, GNUTLS_MASTER_SIZE, session->security_parameters. master_secret); gnutls_free(shash.data); } write_nss_key_log(session, premaster); if (!keep_premaster) _gnutls_free_temp_key_datum(premaster); if (ret < 0) return ret; _gnutls_hard_log("INT: MASTER SECRET: %s\n", _gnutls_bin2hex(session->security_parameters. master_secret, GNUTLS_MASTER_SIZE, buf, sizeof(buf), NULL)); return ret; }
/* return A = g^a % N */ int _gnutls_gen_srp_client_kx (gnutls_session_t session, opaque ** data) { size_t n_a; int ret; uint8_t *data_a; char *username, *password; char buf[64]; gnutls_srp_client_credentials_t cred; cred = (gnutls_srp_client_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (session->internals.srp_username == NULL) { username = cred->username; password = cred->password; } else { username = session->internals.srp_username; password = session->internals.srp_password; } if (username == NULL || password == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } /* calc A = g^a % N */ if (G == NULL || N == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } A = _gnutls_calc_srp_A (&_a, G, N); if (A == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* Rest of SRP calculations */ /* calculate u */ session->key->u = _gnutls_calc_srp_u (A, B, N); if (session->key->u == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_dump_mpi ("SRP U: ", session->key->u); /* S = (B - g^x) ^ (a + u * x) % N */ S = _gnutls_calc_srp_S2 (B, G, session->key->x, _a, session->key->u, N); if (S == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_dump_mpi ("SRP B: ", B); _gnutls_mpi_release (&_b); _gnutls_mpi_release (&V); _gnutls_mpi_release (&session->key->u); _gnutls_mpi_release (&B); ret = _gnutls_mpi_dprint (&session->key->key, session->key->KEY); _gnutls_mpi_release (&S); if (ret < 0) { gnutls_assert(); return ret; } if (_gnutls_mpi_print (NULL, &n_a, A) != 0) { gnutls_assert (); return GNUTLS_E_MPI_PRINT_FAILED; } (*data) = gnutls_malloc (n_a + 2); if ((*data) == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* copy A */ data_a = (*data); if (_gnutls_mpi_print (&data_a[2], &n_a, A) != 0) { gnutls_free (*data); return GNUTLS_E_MPI_PRINT_FAILED; } _gnutls_hard_log ("INT: SRP A[%d]: %s\n", n_a, _gnutls_bin2hex (&data_a[2], n_a, buf, sizeof (buf))); _gnutls_mpi_release (&A); _gnutls_write_uint16 (n_a, data_a); return n_a + 2; }
/* Parses an X509 DN in the asn1_struct, and puts the output into * the string buf. The output is an LDAP encoded DN. * * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence". * That is to point in the rndSequence. */ int _gnutls_x509_parse_dn (ASN1_TYPE asn1_struct, const char *asn1_rdn_name, char *buf, size_t * sizeof_buf) { gnutls_string out_str; int k2, k1, result; char tmpbuffer1[MAX_NAME_SIZE]; char tmpbuffer2[MAX_NAME_SIZE]; char tmpbuffer3[MAX_NAME_SIZE]; opaque value[MAX_STRING_LEN], *value2 = NULL; char *escaped = NULL; const char *ldap_desc; char oid[128]; int len, printable; char *string = NULL; size_t sizeof_string, sizeof_escaped; if (sizeof_buf == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (buf) buf[0] = 0; else *sizeof_buf = 0; _gnutls_string_init (&out_str, gnutls_malloc, gnutls_realloc, gnutls_free); k1 = 0; do { k1++; /* create a string like "tbsCertList.issuer.rdnSequence.?1" */ if (asn1_rdn_name[0]!=0) snprintf( tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", asn1_rdn_name, k1); else snprintf( tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1); len = sizeof (value) - 1; result = asn1_read_value (asn1_struct, tmpbuffer1, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { break; } if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } k2 = 0; do { /* Move to the attibute type and values */ k2++; if (tmpbuffer1[0] != 0) snprintf( tmpbuffer2, sizeof (tmpbuffer2), "%s.?%u", tmpbuffer1, k2); else snprintf( tmpbuffer2, sizeof (tmpbuffer2), "?%u", k2); /* Try to read the RelativeDistinguishedName attributes. */ len = sizeof (value) - 1; result = asn1_read_value (asn1_struct, tmpbuffer2, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Read the OID */ _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2); _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type"); len = sizeof (oid) - 1; result = asn1_read_value (asn1_struct, tmpbuffer3, oid, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; else if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Read the Value */ _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2); _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".value"); len = 0; result = asn1_read_value (asn1_struct, tmpbuffer3, NULL, &len); value2 = gnutls_malloc (len); if (value2 == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } result = asn1_read_value (asn1_struct, tmpbuffer3, value2, &len); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } #define STR_APPEND(y) if ((result=_gnutls_string_append_str( &out_str, y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } /* The encodings of adjoining RelativeDistinguishedNames are separated * by a comma character (',' ASCII 44). */ /* Where there is a multi-valued RDN, the outputs from adjoining * AttributeTypeAndValues are separated by a plus ('+' ASCII 43) * character. */ if (k1 != 1) { /* the first time do not append a comma */ if (k2 != 1) { /* adjoining multi-value RDN */ STR_APPEND ("+"); } else { STR_APPEND (","); } } ldap_desc = oid2ldap_string (oid); printable = _gnutls_x509_oid_data_printable (oid); sizeof_escaped = 2 * len + 1; escaped = gnutls_malloc (sizeof_escaped); if (escaped == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } sizeof_string = 2 * len + 2; /* in case it is not printable */ string = gnutls_malloc (sizeof_string); if (string == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } STR_APPEND (ldap_desc); STR_APPEND ("="); if (printable) result = _gnutls_x509_oid_data2string (oid, value2, len, string, &sizeof_string); else result = _gnutls_x509_data2hex (value2, len, string, &sizeof_string); if (result < 0) { gnutls_assert (); _gnutls_x509_log ("Found OID: '%s' with value '%s'\n", oid, _gnutls_bin2hex (value2, len, escaped, sizeof_escaped)); goto cleanup; } STR_APPEND (str_escape (string, escaped, sizeof_escaped)); gnutls_free (string); string = NULL; gnutls_free (escaped); escaped = NULL; gnutls_free (value2); value2 = NULL; } while (1); } while (1); if (out_str.length >= (unsigned int) *sizeof_buf) { gnutls_assert (); *sizeof_buf = out_str.length + 1; result = GNUTLS_E_SHORT_MEMORY_BUFFER; goto cleanup; } if (buf) { memcpy (buf, out_str.data, out_str.length); buf[out_str.length] = 0; } *sizeof_buf = out_str.length; result = 0; cleanup: gnutls_free (value2); gnutls_free (string); gnutls_free (escaped); _gnutls_string_clear (&out_str); return result; }
static int generate_normal_master (gnutls_session_t session, int keep_premaster) { int ret = 0; char buf[512]; _gnutls_hard_log ("INT: PREMASTER SECRET[%d]: %s\n", PREMASTER.size, _gnutls_bin2hex (PREMASTER.data, PREMASTER.size, buf, sizeof (buf))); _gnutls_hard_log ("INT: CLIENT RANDOM[%d]: %s\n", 32, _gnutls_bin2hex (session-> security_parameters.client_random, 32, buf, sizeof (buf))); _gnutls_hard_log ("INT: SERVER RANDOM[%d]: %s\n", 32, _gnutls_bin2hex (session-> security_parameters.server_random, 32, buf, sizeof (buf))); if (gnutls_protocol_get_version (session) == GNUTLS_SSL3) { opaque rnd[2 * GNUTLS_RANDOM_SIZE + 1]; memcpy (rnd, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy (&rnd[GNUTLS_RANDOM_SIZE], session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); ret = _gnutls_ssl3_generate_random (PREMASTER.data, PREMASTER.size, rnd, 2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE, session-> security_parameters.master_secret); } else if (session->security_parameters.extensions.oprfi_client_len > 0 && session->security_parameters.extensions.oprfi_server_len > 0) { opaque *rnd; size_t rndlen = 2 * GNUTLS_RANDOM_SIZE; rndlen += session->security_parameters.extensions.oprfi_client_len; rndlen += session->security_parameters.extensions.oprfi_server_len; rnd = gnutls_malloc (rndlen + 1); if (!rnd) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_hard_log ("INT: CLIENT OPRFI[%d]: %s\n", session->security_parameters.extensions. oprfi_server_len, _gnutls_bin2hex (session-> security_parameters.extensions. oprfi_client, session-> security_parameters.extensions. oprfi_client_len, buf, sizeof (buf))); _gnutls_hard_log ("INT: SERVER OPRFI[%d]: %s\n", session->security_parameters.extensions. oprfi_server_len, _gnutls_bin2hex (session-> security_parameters.extensions. oprfi_server, session-> security_parameters.extensions. oprfi_server_len, buf, sizeof (buf))); memcpy (rnd, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy (rnd + GNUTLS_RANDOM_SIZE, session->security_parameters.extensions.oprfi_client, session->security_parameters.extensions.oprfi_client_len); memcpy (rnd + GNUTLS_RANDOM_SIZE + session->security_parameters.extensions.oprfi_client_len, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); memcpy (rnd + GNUTLS_RANDOM_SIZE + session->security_parameters.extensions.oprfi_client_len + GNUTLS_RANDOM_SIZE, session->security_parameters.extensions.oprfi_server, session->security_parameters.extensions.oprfi_server_len); ret = _gnutls_PRF (session, PREMASTER.data, PREMASTER.size, MASTER_SECRET, strlen (MASTER_SECRET), rnd, rndlen, GNUTLS_MASTER_SIZE, session->security_parameters.master_secret); gnutls_free (rnd); } else { opaque rnd[2 * GNUTLS_RANDOM_SIZE + 1]; memcpy (rnd, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy (&rnd[GNUTLS_RANDOM_SIZE], session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); ret = _gnutls_PRF (session, PREMASTER.data, PREMASTER.size, MASTER_SECRET, strlen (MASTER_SECRET), rnd, 2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE, session->security_parameters.master_secret); } /* TLS/IA inner secret is derived from the master secret. */ memcpy (session->security_parameters.inner_secret, session->security_parameters.master_secret, GNUTLS_MASTER_SIZE); if (!keep_premaster) _gnutls_free_datum (&PREMASTER); if (ret < 0) return ret; _gnutls_hard_log ("INT: MASTER SECRET: %s\n", _gnutls_bin2hex (session-> security_parameters.master_secret, GNUTLS_MASTER_SIZE, buf, sizeof (buf))); return ret; }
int _gnutls_x509_get_dn(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, gnutls_datum_t * dn) { gnutls_buffer_st out_str; int k2, k1, result; char tmpbuffer1[ASN1_MAX_NAME_SIZE]; char tmpbuffer2[ASN1_MAX_NAME_SIZE]; char tmpbuffer3[ASN1_MAX_NAME_SIZE]; uint8_t value[MAX_STRING_LEN]; gnutls_datum_t td = { NULL, 0 }, tvd = { NULL, 0}; const char *ldap_desc; char oid[MAX_OID_SIZE]; int len; _gnutls_buffer_init(&out_str); k1 = 0; do { k1++; /* create a string like "tbsCertList.issuer.rdnSequence.?1" */ if (asn1_rdn_name[0] != 0) snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u", asn1_rdn_name, k1); else snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u", k1); len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { if (k1 == 1) { gnutls_assert(); result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto cleanup; } break; } if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } k2 = 0; do { /* Move to the attibute type and values */ k2++; if (tmpbuffer1[0] != 0) snprintf(tmpbuffer2, sizeof(tmpbuffer2), "%s.?%u", tmpbuffer1, k2); else snprintf(tmpbuffer2, sizeof(tmpbuffer2), "?%u", k2); /* Try to read the RelativeDistinguishedName attributes. */ len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer2, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the OID */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type"); len = sizeof(oid) - 1; result = asn1_read_value(asn1_struct, tmpbuffer3, oid, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; else if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the Value */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".value"); len = 0; result = _gnutls_x509_read_value(asn1_struct, tmpbuffer3, &tvd); if (result < 0) { gnutls_assert(); goto cleanup; } #define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( &out_str, y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } #define DATA_APPEND(x,y) if ((result=_gnutls_buffer_append_data( &out_str, x,y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } /* The encodings of adjoining RelativeDistinguishedNames are separated * by a comma character (',' ASCII 44). */ /* Where there is a multi-valued RDN, the outputs from adjoining * AttributeTypeAndValues are separated by a plus ('+' ASCII 43) * character. */ if (k1 != 1) { /* the first time do not append a comma */ if (k2 != 1) { /* adjoining multi-value RDN */ STR_APPEND("+"); } else { STR_APPEND(","); } } ldap_desc = gnutls_x509_dn_oid_name(oid, GNUTLS_X509_DN_OID_RETURN_OID); STR_APPEND(ldap_desc); STR_APPEND("="); result = _gnutls_x509_dn_to_string(oid, tvd.data, tvd.size, &td); if (result < 0) { gnutls_assert(); _gnutls_debug_log ("Cannot parse OID: '%s' with value '%s'\n", oid, _gnutls_bin2hex(tvd.data, tvd.size, tmpbuffer3, sizeof (tmpbuffer3), NULL)); goto cleanup; } DATA_APPEND(td.data, td.size); _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); } while (1); } while (1); result = _gnutls_buffer_to_datum(&out_str, dn, 1); if (result < 0) gnutls_assert(); goto cleanup1; cleanup: _gnutls_buffer_clear(&out_str); cleanup1: _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); return result; }
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); }
/* Copies a gnutls_openpgp_privkey_t to a gnutls_privkey structure. */ int _gnutls_openpgp_privkey_to_gkey (gnutls_privkey * dest, gnutls_openpgp_privkey_t src) { int ret = 0; gnutls_openpgp_keyid_t keyid; char err_buf[33]; if (dest == NULL || src == NULL) { gnutls_assert (); return GNUTLS_E_CERTIFICATE_ERROR; } dest->params_size = MAX_PRIV_PARAMS_SIZE; ret = gnutls_openpgp_privkey_get_preferred_key_id (src, keyid); if (ret == 0) { int idx; uint32_t kid32[2]; _gnutls_debug_log ("Importing Openpgp key and using openpgp sub key: %s\n", _gnutls_bin2hex (keyid, sizeof (keyid), err_buf, sizeof (err_buf))); KEYID_IMPORT (kid32, keyid); idx = gnutls_openpgp_privkey_get_subkey_idx (src, keyid); if (idx < 0) { gnutls_assert (); return idx; } dest->pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm (src, idx, NULL); ret = _gnutls_openpgp_privkey_get_mpis (src, kid32, dest->params, &dest->params_size); } else { _gnutls_debug_log ("Importing Openpgp key and using main openpgp key.\n"); dest->pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (src, NULL); ret = _gnutls_openpgp_privkey_get_mpis (src, NULL, dest->params, &dest->params_size); } if (ret < 0) { gnutls_assert (); return ret; } return 0; }