/* the same as _gnutls_handshake_sign_cert_vrfy except that it is made for TLS 1.2 */ static int _gnutls_handshake_sign_cert_vrfy12 (gnutls_session_t session, gnutls_pcert_st* cert, gnutls_privkey_t pkey, gnutls_datum_t * signature) { gnutls_datum_t dconcat; int ret; opaque concat[MAX_SIG_SIZE]; digest_hd_st td; gnutls_sign_algorithm_t sign_algo; gnutls_digest_algorithm_t hash_algo; digest_hd_st *handshake_td; sign_algo = _gnutls_session_get_sign_algo (session, cert); if (sign_algo == GNUTLS_SIGN_UNKNOWN) { gnutls_assert (); return GNUTLS_E_UNKNOWN_PK_ALGORITHM; } hash_algo = _gnutls_sign_get_hash_algorithm (sign_algo); _gnutls_debug_log ("sign handshake cert vrfy: picked %s with %s\n", gnutls_sign_algorithm_get_name (sign_algo), gnutls_mac_get_name (hash_algo)); if ((gnutls_mac_algorithm_t)hash_algo == session->internals.handshake_mac_handle.tls12.sha1.algorithm) handshake_td = &session->internals.handshake_mac_handle.tls12.sha1; else if ((gnutls_mac_algorithm_t)hash_algo == session->internals.handshake_mac_handle.tls12.sha256.algorithm) handshake_td = &session->internals.handshake_mac_handle.tls12.sha256; else return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); /* too bad we only support SHA1 and SHA256 */ ret = _gnutls_hash_copy (&td, handshake_td); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash_deinit (&td, concat); dconcat.data = concat; dconcat.size = _gnutls_hash_get_algo_len (hash_algo); ret = sign_tls_hash (session, hash_algo, cert, pkey, &dconcat, signature); if (ret < 0) { gnutls_assert (); return ret; } return sign_algo; }
/* the same as _gnutls_handshake_sign_crt_vrfy except that it is made for TLS 1.2 */ static int _gnutls_handshake_sign_crt_vrfy12(gnutls_session_t session, gnutls_pcert_st * cert, gnutls_privkey_t pkey, gnutls_datum_t * signature) { gnutls_datum_t dconcat; int ret; uint8_t concat[MAX_SIG_SIZE]; gnutls_sign_algorithm_t sign_algo; const mac_entry_st *me; sign_algo = _gnutls_session_get_sign_algo(session, cert); if (sign_algo == GNUTLS_SIGN_UNKNOWN) { gnutls_assert(); return GNUTLS_E_UNKNOWN_PK_ALGORITHM; } gnutls_sign_algorithm_set_client(session, sign_algo); me = hash_to_entry(gnutls_sign_get_hash_algorithm(sign_algo)); _gnutls_debug_log("sign handshake cert vrfy: picked %s with %s\n", gnutls_sign_algorithm_get_name(sign_algo), _gnutls_mac_get_name(me)); ret = _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id, session->internals.handshake_hash_buffer. data, session->internals.handshake_hash_buffer. length, concat); if (ret < 0) return gnutls_assert_val(ret); dconcat.data = concat; dconcat.size = _gnutls_hash_get_algo_len(me); ret = sign_tls_hash(session, me, cert, pkey, &dconcat, signature); if (ret < 0) { gnutls_assert(); return ret; } return sign_algo; }
/* Generates a signature of all the random data and the parameters. * Used in DHE_* ciphersuites. */ int _gnutls_handshake_sign_data(gnutls_session_t session, gnutls_pcert_st * cert, gnutls_privkey_t pkey, gnutls_datum_t * params, gnutls_datum_t * signature, gnutls_sign_algorithm_t * sign_algo) { gnutls_datum_t dconcat; int ret; digest_hd_st td_sha; uint8_t concat[MAX_SIG_SIZE]; const version_entry_st *ver = get_version(session); const mac_entry_st *hash_algo; *sign_algo = _gnutls_session_get_sign_algo(session, cert); if (*sign_algo == GNUTLS_SIGN_UNKNOWN) { gnutls_assert(); return GNUTLS_E_UNKNOWN_PK_ALGORITHM; } gnutls_sign_algorithm_set_server(session, *sign_algo); hash_algo = hash_to_entry(gnutls_sign_get_hash_algorithm(*sign_algo)); if (hash_algo == NULL) return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM); _gnutls_handshake_log ("HSK[%p]: signing handshake data: using %s\n", session, gnutls_sign_algorithm_get_name(*sign_algo)); ret = _gnutls_hash_init(&td_sha, hash_algo); if (ret < 0) { gnutls_assert(); return ret; } _gnutls_hash(&td_sha, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); _gnutls_hash(&td_sha, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); _gnutls_hash(&td_sha, params->data, params->size); switch (gnutls_privkey_get_pk_algorithm(pkey, NULL)) { case GNUTLS_PK_RSA: if (!_gnutls_version_has_selectable_sighash(ver)) { digest_hd_st td_md5; ret = _gnutls_hash_init(&td_md5, hash_to_entry (GNUTLS_DIG_MD5)); if (ret < 0) { gnutls_assert(); return ret; } _gnutls_hash(&td_md5, session->security_parameters. client_random, GNUTLS_RANDOM_SIZE); _gnutls_hash(&td_md5, session->security_parameters. server_random, GNUTLS_RANDOM_SIZE); _gnutls_hash(&td_md5, params->data, params->size); _gnutls_hash_deinit(&td_md5, concat); _gnutls_hash_deinit(&td_sha, &concat[16]); dconcat.data = concat; dconcat.size = 36; } else { /* TLS 1.2 way */ _gnutls_hash_deinit(&td_sha, concat); dconcat.data = concat; dconcat.size = _gnutls_hash_get_algo_len(hash_algo); } break; case GNUTLS_PK_DSA: case GNUTLS_PK_EC: _gnutls_hash_deinit(&td_sha, concat); if (!IS_SHA((gnutls_digest_algorithm_t)hash_algo->id)) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } dconcat.data = concat; dconcat.size = _gnutls_hash_get_algo_len(hash_algo); break; default: gnutls_assert(); _gnutls_hash_deinit(&td_sha, NULL); return GNUTLS_E_INTERNAL_ERROR; } ret = sign_tls_hash(session, hash_algo, cert, pkey, &dconcat, signature); if (ret < 0) { gnutls_assert(); } return ret; }
/* Generates a signature of all the random data and the parameters. * Used in DHE_* ciphersuites. */ int _gnutls_handshake_sign_data (gnutls_session_t session, gnutls_cert * cert, gnutls_privkey * pkey, gnutls_datum_t * params, gnutls_datum_t * signature, gnutls_sign_algorithm_t * sign_algo) { gnutls_datum_t dconcat; int ret; digest_hd_st td_sha; opaque concat[MAX_SIG_SIZE]; gnutls_protocol_t ver = gnutls_protocol_get_version (session); gnutls_digest_algorithm_t hash_algo; *sign_algo = _gnutls_session_get_sign_algo (session, cert->subject_pk_algorithm, &hash_algo); if (*sign_algo == GNUTLS_SIGN_UNKNOWN) { gnutls_assert (); return GNUTLS_E_UNKNOWN_PK_ALGORITHM; } ret = _gnutls_hash_init (&td_sha, hash_algo); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash (&td_sha, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_sha, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_sha, params->data, params->size); switch (cert->subject_pk_algorithm) { case GNUTLS_PK_RSA: if (!_gnutls_version_has_selectable_prf (ver)) { digest_hd_st td_md5; ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash (&td_md5, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_md5, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_md5, params->data, params->size); _gnutls_hash_deinit (&td_md5, concat); _gnutls_hash_deinit (&td_sha, &concat[16]); dconcat.data = concat; dconcat.size = 36; } else { /* TLS 1.2 way */ gnutls_datum_t hash; _gnutls_hash_deinit (&td_sha, concat); hash.data = concat; hash.size = _gnutls_hash_get_algo_len (hash_algo); dconcat.data = concat; dconcat.size = sizeof concat; _gnutls_rsa_encode_sig (hash_algo, &hash, &dconcat); } break; case GNUTLS_PK_DSA: _gnutls_hash_deinit (&td_sha, concat); if (hash_algo != GNUTLS_DIG_SHA1) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } dconcat.data = concat; dconcat.size = 20; break; default: gnutls_assert (); _gnutls_hash_deinit (&td_sha, NULL); return GNUTLS_E_INTERNAL_ERROR; } ret = _gnutls_tls_sign (session, cert, pkey, &dconcat, signature); if (ret < 0) { gnutls_assert (); } return ret; }
/* Generates a signature of all the random data and the parameters. * Used in DHE_* ciphersuites. */ int _gnutls_handshake_sign_data (gnutls_session_t session, gnutls_pcert_st* cert, gnutls_privkey_t pkey, gnutls_datum_t * params, gnutls_datum_t * signature, gnutls_sign_algorithm_t * sign_algo) { gnutls_datum_t dconcat; int ret; digest_hd_st td_sha; opaque concat[MAX_SIG_SIZE]; gnutls_protocol_t ver = gnutls_protocol_get_version (session); gnutls_digest_algorithm_t hash_algo; *sign_algo = _gnutls_session_get_sign_algo (session, cert); if (*sign_algo == GNUTLS_SIGN_UNKNOWN) { gnutls_assert (); return GNUTLS_E_UNKNOWN_PK_ALGORITHM; } hash_algo = _gnutls_sign_get_hash_algorithm (*sign_algo); _gnutls_handshake_log ("HSK[%p]: signing handshake data: using %s\n", session, gnutls_sign_algorithm_get_name (*sign_algo)); ret = _gnutls_hash_init (&td_sha, hash_algo); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash (&td_sha, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_sha, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_sha, params->data, params->size); switch (gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL)) { case GNUTLS_PK_RSA: if (!_gnutls_version_has_selectable_sighash (ver)) { digest_hd_st td_md5; ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash (&td_md5, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_md5, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_md5, params->data, params->size); _gnutls_hash_deinit (&td_md5, concat); _gnutls_hash_deinit (&td_sha, &concat[16]); dconcat.data = concat; dconcat.size = 36; } else { /* TLS 1.2 way */ _gnutls_hash_deinit (&td_sha, concat); dconcat.data = concat; dconcat.size = _gnutls_hash_get_algo_len (hash_algo); } break; case GNUTLS_PK_DSA: _gnutls_hash_deinit (&td_sha, concat); if ((hash_algo != GNUTLS_DIG_SHA1) && (hash_algo != GNUTLS_DIG_SHA224) && (hash_algo != GNUTLS_DIG_SHA256)) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } dconcat.data = concat; dconcat.size = _gnutls_hash_get_algo_len (hash_algo); break; default: gnutls_assert (); _gnutls_hash_deinit (&td_sha, NULL); return GNUTLS_E_INTERNAL_ERROR; } ret = sign_tls_hash (session, hash_algo, cert, pkey, &dconcat, signature); if (ret < 0) { gnutls_assert (); } return ret; }