diff options
Diffstat (limited to 'lib/auth_rsa.c')
-rw-r--r-- | lib/auth_rsa.c | 472 |
1 files changed, 240 insertions, 232 deletions
diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c index 5e6f412b92..f62c7e5684 100644 --- a/lib/auth_rsa.c +++ b/lib/auth_rsa.c @@ -45,140 +45,146 @@ int _gnutls_gen_rsa_client_kx(gnutls_session, opaque **); int _gnutls_proc_rsa_client_kx(gnutls_session, opaque *, size_t); const mod_auth_st rsa_auth_struct = { - "RSA", - _gnutls_gen_cert_server_certificate, - _gnutls_gen_cert_client_certificate, - NULL, /* gen server kx */ - _gnutls_gen_rsa_client_kx, - _gnutls_gen_cert_client_cert_vrfy, /* gen client cert vrfy */ - _gnutls_gen_cert_server_cert_req, /* server cert request */ - - _gnutls_proc_cert_server_certificate, - _gnutls_proc_cert_client_certificate, - NULL, /* proc server kx */ - _gnutls_proc_rsa_client_kx, /* proc client kx */ - _gnutls_proc_cert_client_cert_vrfy, /* proc client cert vrfy */ - _gnutls_proc_cert_cert_req /* proc server cert request */ + "RSA", + _gnutls_gen_cert_server_certificate, + _gnutls_gen_cert_client_certificate, + NULL, /* gen server kx */ + _gnutls_gen_rsa_client_kx, + _gnutls_gen_cert_client_cert_vrfy, /* gen client cert vrfy */ + _gnutls_gen_cert_server_cert_req, /* server cert request */ + + _gnutls_proc_cert_server_certificate, + _gnutls_proc_cert_client_certificate, + NULL, /* proc server kx */ + _gnutls_proc_rsa_client_kx, /* proc client kx */ + _gnutls_proc_cert_client_cert_vrfy, /* proc client cert vrfy */ + _gnutls_proc_cert_cert_req /* proc server cert request */ }; /* This function reads the RSA parameters from peer's certificate; */ -int _gnutls_get_public_rsa_params(gnutls_session session, - mpi_t params[MAX_PUBLIC_PARAMS_SIZE], int* params_len) +int _gnutls_get_public_rsa_params(gnutls_session session, + mpi_t params[MAX_PUBLIC_PARAMS_SIZE], + int *params_len) { -int ret; -cert_auth_info_t info; -gnutls_cert peer_cert; -int i; + int ret; + cert_auth_info_t info; + gnutls_cert peer_cert; + int i; - /* normal non export case */ + /* normal non export case */ - info = _gnutls_get_auth_info( session); + info = _gnutls_get_auth_info(session); - if (info==NULL || info->ncerts==0) { - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; - } - - ret = - _gnutls_raw_cert_to_gcert( &peer_cert, session->security_parameters.cert_type, - &info->raw_certificate_list[0], CERT_ONLY_PUBKEY|CERT_NO_COPY); - - if (ret < 0) { - gnutls_assert(); - return ret; - } + if (info == NULL || info->ncerts == 0) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + ret = + _gnutls_raw_cert_to_gcert(&peer_cert, + session->security_parameters.cert_type, + &info->raw_certificate_list[0], + CERT_ONLY_PUBKEY | CERT_NO_COPY); - /* EXPORT case: */ - if ( _gnutls_cipher_suite_get_kx_algo(&session->security_parameters.current_cipher_suite) - == GNUTLS_KX_RSA_EXPORT && - _gnutls_mpi_get_nbits(peer_cert.params[0]) > 512) { + if (ret < 0) { + gnutls_assert(); + return ret; + } - _gnutls_gcert_deinit( &peer_cert); - if (session->key->rsa[0] == NULL || - session->key->rsa[1] == NULL) { - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; - } + /* EXPORT case: */ + if (_gnutls_cipher_suite_get_kx_algo + (&session->security_parameters.current_cipher_suite) + == GNUTLS_KX_RSA_EXPORT + && _gnutls_mpi_get_nbits(peer_cert.params[0]) > 512) { - if (*params_len < 2) { - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; - } - *params_len = 2; - for (i=0;i<*params_len;i++) { - params[i] = _gnutls_mpi_copy(session->key->rsa[i]); - } + _gnutls_gcert_deinit(&peer_cert); - return 0; + if (session->key->rsa[0] == NULL || session->key->rsa[1] == NULL) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; } - /* end of export case */ - - if (*params_len < peer_cert.params_size) { - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; + if (*params_len < 2) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; } - *params_len = peer_cert.params_size; - - for (i=0;i<*params_len;i++) { - params[i] = _gnutls_mpi_copy(peer_cert.params[i]); + *params_len = 2; + for (i = 0; i < *params_len; i++) { + params[i] = _gnutls_mpi_copy(session->key->rsa[i]); } - _gnutls_gcert_deinit( &peer_cert); return 0; + } + + /* end of export case */ + + if (*params_len < peer_cert.params_size) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + *params_len = peer_cert.params_size; + + for (i = 0; i < *params_len; i++) { + params[i] = _gnutls_mpi_copy(peer_cert.params[i]); + } + _gnutls_gcert_deinit(&peer_cert); + + return 0; } /* This function reads the RSA parameters from the private key */ -int _gnutls_get_private_rsa_params(gnutls_session session, mpi_t **params, int* params_size) +int _gnutls_get_private_rsa_params(gnutls_session session, mpi_t ** params, + int *params_size) { -int bits; -const gnutls_certificate_credentials cred; -gnutls_rsa_params rsa_params; - - cred = _gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL); - if (cred == NULL) { - gnutls_assert(); - return GNUTLS_E_INSUFFICIENT_CREDENTIALS; - } - - if (session->internals.selected_cert_list == NULL) { - gnutls_assert(); - return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + int bits; + const gnutls_certificate_credentials cred; + gnutls_rsa_params rsa_params; + + cred = _gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if (session->internals.selected_cert_list == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + bits = + _gnutls_mpi_get_nbits(session->internals.selected_cert_list[0]. + params[0]); + + if (_gnutls_cipher_suite_get_kx_algo + (&session->security_parameters.current_cipher_suite) + == GNUTLS_KX_RSA_EXPORT && bits > 512) { + + rsa_params = _gnutls_certificate_get_rsa_params(cred, session); + /* EXPORT case: */ + if (rsa_params == NULL) { + gnutls_assert(); + return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS; } - bits = _gnutls_mpi_get_nbits(session->internals.selected_cert_list[0].params[0]); + /* In the export case, we do use temporary RSA params + * of 512 bits size. The params in the certificate are + * used to sign this temporary stuff. + */ + *params_size = RSA_PRIVATE_PARAMS; + *params = rsa_params->params; - if ( _gnutls_cipher_suite_get_kx_algo(&session->security_parameters.current_cipher_suite) - == GNUTLS_KX_RSA_EXPORT && - bits > 512) { + return 0; + } - rsa_params = _gnutls_certificate_get_rsa_params( cred, session); - /* EXPORT case: */ - if (rsa_params == NULL) { - gnutls_assert(); - return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS; - } - - /* In the export case, we do use temporary RSA params - * of 512 bits size. The params in the certificate are - * used to sign this temporary stuff. - */ - *params_size = RSA_PRIVATE_PARAMS; - *params = rsa_params->params; - - return 0; - } + /* non export cipher suites. */ - /* non export cipher suites. */ - - *params_size = session->internals.selected_key->params_size; - *params = session->internals.selected_key->params; + *params_size = session->internals.selected_key->params_size; + *params = session->internals.selected_key->params; - return 0; + return 0; } @@ -190,88 +196,88 @@ gnutls_rsa_params rsa_params; return GNUTLS_E_MEMORY_ERROR; \ } -int _gnutls_proc_rsa_client_kx(gnutls_session session, opaque * data, size_t _data_size) +int _gnutls_proc_rsa_client_kx(gnutls_session session, opaque * data, + size_t _data_size) { - gnutls_datum plaintext; - gnutls_datum ciphertext; - int ret, dsize; - mpi_t *params; - int params_len; - int randomize_key = 0; - ssize_t data_size = _data_size; - - if (gnutls_protocol_get_version(session) == GNUTLS_SSL3) { - /* SSL 3.0 - */ - ciphertext.data = data; - ciphertext.size = data_size; - } else { - /* TLS 1.0 - */ - DECR_LEN( data_size, 2); - ciphertext.data = &data[2]; - dsize = _gnutls_read_uint16(data); - - if (dsize != data_size) { - gnutls_assert(); - return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - } - ciphertext.size = dsize; - } + gnutls_datum plaintext; + gnutls_datum ciphertext; + int ret, dsize; + mpi_t *params; + int params_len; + int randomize_key = 0; + ssize_t data_size = _data_size; + + if (gnutls_protocol_get_version(session) == GNUTLS_SSL3) { + /* SSL 3.0 + */ + ciphertext.data = data; + ciphertext.size = data_size; + } else { + /* TLS 1.0 + */ + DECR_LEN(data_size, 2); + ciphertext.data = &data[2]; + dsize = _gnutls_read_uint16(data); - ret = _gnutls_get_private_rsa_params(session, ¶ms, ¶ms_len); - if (ret < 0) { - gnutls_assert(); - return ret; + if (dsize != data_size) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } + ciphertext.size = dsize; + } - ret = _gnutls_pkcs1_rsa_decrypt(&plaintext, &ciphertext, params, - params_len, 2); /* btype==2 */ - - if (ret < 0 || plaintext.size != TLS_MASTER_SIZE) { - /* In case decryption fails then don't inform - * the peer. Just use a random key. (in order to avoid - * attack against pkcs-1 formating). - */ - gnutls_assert(); - _gnutls_x509_log("auth_rsa: Possible PKCS #1 format attack\n"); - randomize_key = 1; - } else { - /* If the secret was properly formatted, then - * check the version number. - */ - if (_gnutls_get_adv_version_major(session) != plaintext.data[0] - || _gnutls_get_adv_version_minor(session) != plaintext.data[1]) - { - /* No error is returned here, if the version number check - * fails. We proceed normally. - * That is to defend against the attack described in the paper - * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima, - * Ondej Pokorny and Tomas Rosa. - */ - gnutls_assert(); - _gnutls_x509_log("auth_rsa: Possible PKCS #1 version check format attack\n"); - } - } + ret = _gnutls_get_private_rsa_params(session, ¶ms, ¶ms_len); + if (ret < 0) { + gnutls_assert(); + return ret; + } - if (randomize_key != 0) { - /* we do not need strong random numbers here. - */ - RANDOMIZE_KEY(session->key->key, - gnutls_malloc, GNUTLS_WEAK_RANDOM); + ret = _gnutls_pkcs1_rsa_decrypt(&plaintext, &ciphertext, params, params_len, 2); /* btype==2 */ - } else { - session->key->key.data = plaintext.data; - session->key->key.size = plaintext.size; + if (ret < 0 || plaintext.size != TLS_MASTER_SIZE) { + /* In case decryption fails then don't inform + * the peer. Just use a random key. (in order to avoid + * attack against pkcs-1 formating). + */ + gnutls_assert(); + _gnutls_x509_log("auth_rsa: Possible PKCS #1 format attack\n"); + randomize_key = 1; + } else { + /* If the secret was properly formatted, then + * check the version number. + */ + if (_gnutls_get_adv_version_major(session) != plaintext.data[0] + || _gnutls_get_adv_version_minor(session) != plaintext.data[1]) { + /* No error is returned here, if the version number check + * fails. We proceed normally. + * That is to defend against the attack described in the paper + * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima, + * Ondej Pokorny and Tomas Rosa. + */ + gnutls_assert(); + _gnutls_x509_log + ("auth_rsa: Possible PKCS #1 version check format attack\n"); } + } - /* This is here to avoid the version check attack - * discussed above. + if (randomize_key != 0) { + /* we do not need strong random numbers here. */ - session->key->key.data[0] = _gnutls_get_adv_version_major(session); - session->key->key.data[1] = _gnutls_get_adv_version_minor(session); + RANDOMIZE_KEY(session->key->key, + gnutls_malloc, GNUTLS_WEAK_RANDOM); - return 0; + } else { + session->key->key.data = plaintext.data; + session->key->key.size = plaintext.size; + } + + /* This is here to avoid the version check attack + * discussed above. + */ + session->key->key.data[0] = _gnutls_get_adv_version_major(session); + session->key->key.data[1] = _gnutls_get_adv_version_minor(session); + + return 0; } @@ -280,64 +286,66 @@ int _gnutls_proc_rsa_client_kx(gnutls_session session, opaque * data, size_t _da */ int _gnutls_gen_rsa_client_kx(gnutls_session session, opaque ** data) { - cert_auth_info_t auth = session->key->auth_info; - gnutls_datum sdata; /* data to send */ - mpi_t params[MAX_PUBLIC_PARAMS_SIZE]; - int params_len = MAX_PUBLIC_PARAMS_SIZE; - int ret, i; - gnutls_protocol_version ver; - - if (auth == NULL) { - /* this shouldn't have happened. The proc_certificate - * function should have detected that. - */ - gnutls_assert(); - return GNUTLS_E_INSUFFICIENT_CREDENTIALS; - } - RANDOMIZE_KEY(session->key->key, gnutls_secure_malloc, GNUTLS_STRONG_RANDOM); - - 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). + cert_auth_info_t auth = session->key->auth_info; + gnutls_datum sdata; /* data to send */ + mpi_t params[MAX_PUBLIC_PARAMS_SIZE]; + int params_len = MAX_PUBLIC_PARAMS_SIZE; + int ret, i; + gnutls_protocol_version ver; + + if (auth == NULL) { + /* this shouldn't have happened. The proc_certificate + * function should have detected that. */ - 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; + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + RANDOMIZE_KEY(session->key->key, gnutls_secure_malloc, + GNUTLS_STRONG_RANDOM); + + 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; + } } |