size_t _data_size)
{
int sigsize;
+ opaque *sigdata;
gnutls_datum_t vparams, signature;
int ret;
cert_auth_info_t info = _gnutls_get_auth_info (session);
ssize_t data_size = _data_size;
gnutls_cert peer_cert;
+ gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN;
+ gnutls_protocol_t ver = gnutls_protocol_get_version (session);
if (info == NULL || info->ncerts == 0)
{
vparams.size = ret;
vparams.data = data;
+ sigdata = &data[vparams.size];
+ if (_gnutls_version_has_selectable_sighash (ver))
+ {
+ sign_algorithm_st aid;
+
+ DECR_LEN(data_size, 1);
+ aid.hash_algorithm = *sigdata++;
+ DECR_LEN(data_size, 1);
+ aid.sign_algorithm = *sigdata++;
+ sign_algo = _gnutls_tls_aid_to_sign (aid);
+ if (sign_algo == GNUTLS_SIGN_UNKNOWN)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
+ }
+ }
DECR_LEN (data_size, 2);
- sigsize = _gnutls_read_uint16 (&data[vparams.size]);
+ sigsize = _gnutls_read_uint16 (sigdata);
+ sigdata += 2;
DECR_LEN (data_size, sigsize);
- signature.data = &data[vparams.size + 2];
+ signature.data = sigdata;
signature.size = sigsize;
if ((ret =
return ret;
}
- ret = _gnutls_verify_sig_params (session, &peer_cert, &vparams, &signature);
+ ret = _gnutls_verify_sig_params (session, &peer_cert, &vparams, &signature,
+ sign_algo);
_gnutls_gcert_deinit (&peer_cert);
if (ret < 0)
return ret;
}
- ret = _gnutls_verify_sig_params (session, &peer_cert, &vparams, &signature);
+ ret = _gnutls_verify_sig_params (session, &peer_cert, &vparams, &signature,
+ GNUTLS_SIGN_UNKNOWN);
_gnutls_gcert_deinit (&peer_cert);
if (ret < 0)
return ret;
}
- ret = _gnutls_verify_sig_params (session, &peer_cert, &vparams, &signature);
+ ret = _gnutls_verify_sig_params (session, &peer_cert, &vparams, &signature,
+ GNUTLS_SIGN_UNKNOWN);
_gnutls_gcert_deinit (&peer_cert);
if (ret < 0)
static int
_gnutls_verify_sig (gnutls_cert * cert,
const gnutls_datum_t * hash_concat,
- gnutls_datum_t * signature, size_t sha1pos)
+ gnutls_datum_t * signature, size_t sha1pos,
+ gnutls_pk_algorithm_t pk_algo)
{
int ret;
gnutls_datum_t vdata;
return GNUTLS_E_KEY_USAGE_VIOLATION;
}
- switch (cert->subject_pk_algorithm)
+ if (pk_algo == GNUTLS_PK_UNKNOWN)
+ pk_algo = cert->subject_pk_algorithm;
+ switch (pk_algo)
{
case GNUTLS_PK_RSA:
case GNUTLS_PK_DSA:
vdata.data = &hash_concat->data[sha1pos];
- vdata.size = 20; /* sha1 */
+ vdata.size = hash_concat->size - sha1pos;
/* verify signature */
if ((ret = _gnutls_dsa_verify (&vdata, signature, cert->params,
dconcat.data = concat;
dconcat.size = 20 + 16; /* md5+ sha */
- ret = _gnutls_verify_sig (cert, &dconcat, signature, 16);
+ ret = _gnutls_verify_sig (cert, &dconcat, signature, 16, GNUTLS_SIGN_UNKNOWN);
if (ret < 0)
{
gnutls_assert ();
int
_gnutls_verify_sig_params (gnutls_session_t session, gnutls_cert * cert,
const gnutls_datum_t * params,
- gnutls_datum_t * signature)
+ gnutls_datum_t * signature,
+ gnutls_sign_algorithm_t algo)
{
gnutls_datum_t dconcat;
int ret;
digest_hd_st td_sha;
opaque concat[36];
gnutls_protocol_t ver = gnutls_protocol_get_version (session);
+ gnutls_mac_algorithm_t mac_algo = GNUTLS_MAC_SHA1;
if (!_gnutls_version_has_selectable_prf (ver))
{
_gnutls_hash (&td_md5, params->data, params->size);
}
- ret = _gnutls_hash_init (&td_sha, GNUTLS_MAC_SHA1);
+ if (algo != GNUTLS_SIGN_UNKNOWN)
+ mac_algo = _gnutls_sign_get_mac_algorithm (algo);
+ ret = _gnutls_hash_init (&td_sha, mac_algo);
if (ret < 0)
{
gnutls_assert ();
dconcat.data = concat;
- ret = _gnutls_verify_sig (cert, &dconcat, signature, dconcat.size - 20);
+ ret = _gnutls_verify_sig (cert, &dconcat, signature,
+ dconcat.size - _gnutls_hash_get_algo_len (mac_algo),
+ _gnutls_sign_get_pk_algorithm (algo));
if (ret < 0)
{
gnutls_assert ();
int _gnutls_verify_sig_params (gnutls_session_t session,
gnutls_cert * cert,
const gnutls_datum_t * params,
- gnutls_datum_t * signature);
+ gnutls_datum_t * signature,
+ gnutls_sign_algorithm_t algo);
int _gnutls_sign (gnutls_pk_algorithm_t algo,
bigint_t * params, int params_size,