/* Encodes the RSA parameters into an ASN.1 RSA private key structure. */ static int _encode_rsa (ASN1_TYPE * c2, mpi_t * params) { int result, i; size_t size[8], total; opaque *m_data, *pube_data, *prie_data; opaque *p1_data, *p2_data, *u_data, *exp1_data, *exp2_data; opaque *all_data = NULL, *p; mpi_t exp1 = NULL, exp2 = NULL, q1 = NULL, p1 = NULL, u = NULL; opaque null = '\0'; /* Read all the sizes */ total = 0; for (i = 0; i < 5; i++) { _gnutls_mpi_print_lz (NULL, &size[i], params[i]); total += size[i]; } /* Now generate exp1 and exp2 */ exp1 = _gnutls_mpi_salloc_like (params[0]); /* like modulus */ if (exp1 == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } exp2 = _gnutls_mpi_salloc_like (params[0]); if (exp2 == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } q1 = _gnutls_mpi_salloc_like (params[4]); if (q1 == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } p1 = _gnutls_mpi_salloc_like (params[3]); if (p1 == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } u = _gnutls_mpi_salloc_like (params[3]); if (u == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } _gnutls_mpi_invm (u, params[4], params[3]); /* inverse of q mod p */ _gnutls_mpi_print_lz (NULL, &size[5], u); total += size[5]; _gnutls_mpi_sub_ui (p1, params[3], 1); _gnutls_mpi_sub_ui (q1, params[4], 1); _gnutls_mpi_mod (exp1, params[2], p1); _gnutls_mpi_mod (exp2, params[2], q1); /* calculate exp's size */ _gnutls_mpi_print_lz (NULL, &size[6], exp1); total += size[6]; _gnutls_mpi_print_lz (NULL, &size[7], exp2); total += size[7]; /* Encoding phase. * allocate data enough to hold everything */ all_data = gnutls_secure_malloc (total); if (all_data == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } p = all_data; m_data = p; p += size[0]; pube_data = p; p += size[1]; prie_data = p; p += size[2]; p1_data = p; p += size[3]; p2_data = p; p += size[4]; u_data = p; p += size[5]; exp1_data = p; p += size[6]; exp2_data = p; _gnutls_mpi_print_lz (m_data, &size[0], params[0]); _gnutls_mpi_print_lz (pube_data, &size[1], params[1]); _gnutls_mpi_print_lz (prie_data, &size[2], params[2]); _gnutls_mpi_print_lz (p1_data, &size[3], params[3]); _gnutls_mpi_print_lz (p2_data, &size[4], params[4]); _gnutls_mpi_print_lz (u_data, &size[5], u); _gnutls_mpi_print_lz (exp1_data, &size[6], exp1); _gnutls_mpi_print_lz (exp2_data, &size[7], exp2); /* Ok. Now we have the data. Create the asn1 structures */ if ((result = asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPrivateKey", c2)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Write PRIME */ if ((result = asn1_write_value (*c2, "modulus", m_data, size[0])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "publicExponent", pube_data, size[1])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "privateExponent", prie_data, size[2])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "prime1", p1_data, size[3])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "prime2", p2_data, size[4])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "exponent1", exp1_data, size[6])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "exponent2", exp2_data, size[7])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "coefficient", u_data, size[5])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } _gnutls_mpi_release (&exp1); _gnutls_mpi_release (&exp2); _gnutls_mpi_release (&q1); _gnutls_mpi_release (&p1); _gnutls_mpi_release (&u); gnutls_free (all_data); if ((result = asn1_write_value (*c2, "otherPrimeInfos", NULL, 0)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "version", &null, 1)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } return 0; cleanup: _gnutls_mpi_release (&u); _gnutls_mpi_release (&exp1); _gnutls_mpi_release (&exp2); _gnutls_mpi_release (&q1); _gnutls_mpi_release (&p1); asn1_delete_structure (c2); gnutls_free (all_data); return result; }
/* 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; }
/* Encodes the DSA parameters into an ASN.1 DSAPrivateKey structure. */ static int _encode_dsa (ASN1_TYPE * c2, mpi_t * params) { int result, i; size_t size[DSA_PRIVATE_PARAMS], total; opaque *p_data, *q_data, *g_data, *x_data, *y_data; opaque *all_data = NULL, *p; opaque null = '\0'; /* Read all the sizes */ total = 0; for (i = 0; i < DSA_PRIVATE_PARAMS; i++) { _gnutls_mpi_print_lz (NULL, &size[i], params[i]); total += size[i]; } /* Encoding phase. * allocate data enough to hold everything */ all_data = gnutls_secure_malloc (total); if (all_data == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } p = all_data; p_data = p; p += size[0]; q_data = p; p += size[1]; g_data = p; p += size[2]; y_data = p; p += size[3]; x_data = p; _gnutls_mpi_print_lz (p_data, &size[0], params[0]); _gnutls_mpi_print_lz (q_data, &size[1], params[1]); _gnutls_mpi_print_lz (g_data, &size[2], params[2]); _gnutls_mpi_print_lz (y_data, &size[3], params[3]); _gnutls_mpi_print_lz (x_data, &size[4], params[4]); /* Ok. Now we have the data. Create the asn1 structures */ if ((result = asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.DSAPrivateKey", c2)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Write PRIME */ if ((result = asn1_write_value (*c2, "p", p_data, size[0])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "q", q_data, size[1])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "g", g_data, size[2])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "Y", y_data, size[3])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "priv", x_data, size[4])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } gnutls_free (all_data); if ((result = asn1_write_value (*c2, "version", &null, 1)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } return 0; cleanup: asn1_delete_structure (c2); gnutls_free (all_data); return result; }
/* return RSA(random) using the peers public key */ int _gnutls_gen_rsa_client_kx (gnutls_session_t session, opaque ** data) { cert_auth_info_t auth = session->key->auth_info; gnutls_datum_t sdata; /* data to send */ bigint_t params[MAX_PUBLIC_PARAMS_SIZE]; int params_len = MAX_PUBLIC_PARAMS_SIZE; int ret, i; gnutls_protocol_t ver; if (auth == NULL) { /* this shouldn't have happened. The proc_certificate * function should have detected that. */ gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } session->key->key.size = GNUTLS_MASTER_SIZE; session->key->key.data = gnutls_secure_malloc (session->key->key.size); if (session->key->key.data == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } ret = _gnutls_rnd (GNUTLS_RND_RANDOM, session->key->key.data, session->key->key.size); if (ret < 0) { gnutls_assert (); return ret; } ver = _gnutls_get_adv_version (session); if (session->internals.rsa_pms_version[0] == 0) { session->key->key.data[0] = _gnutls_version_get_major (ver); session->key->key.data[1] = _gnutls_version_get_minor (ver); } else { /* use the version provided */ session->key->key.data[0] = session->internals.rsa_pms_version[0]; session->key->key.data[1] = session->internals.rsa_pms_version[1]; } /* move RSA parameters to key (session). */ if ((ret = _gnutls_get_public_rsa_params (session, params, ¶ms_len)) < 0) { gnutls_assert (); return ret; } if ((ret = _gnutls_pkcs1_rsa_encrypt (&sdata, &session->key->key, params, params_len, 2)) < 0) { gnutls_assert (); return ret; } for (i = 0; i < params_len; i++) _gnutls_mpi_release (¶ms[i]); if (gnutls_protocol_get_version (session) == GNUTLS_SSL3) { /* SSL 3.0 */ *data = sdata.data; return sdata.size; } else { /* TLS 1 */ *data = gnutls_malloc (sdata.size + 2); if (*data == NULL) { _gnutls_free_datum (&sdata); return GNUTLS_E_MEMORY_ERROR; } _gnutls_write_datum16 (*data, sdata); ret = sdata.size + 2; _gnutls_free_datum (&sdata); return ret; } }