/* Generates a signature of all the previous sent packets in the * handshake procedure. (20040227: now it works for SSL 3.0 as well) */ int _gnutls_tls_sign_hdata (gnutls_session_t session, gnutls_cert * cert, gnutls_privkey * pkey, gnutls_datum_t * signature) { gnutls_datum_t dconcat; int ret; opaque concat[36]; digest_hd_st td_md5; digest_hd_st td_sha; gnutls_protocol_t ver = gnutls_protocol_get_version (session); ret = _gnutls_hash_copy (&td_sha, &session->internals.handshake_mac_handle_sha); if (ret < 0) { gnutls_assert (); return ret; } if (ver == GNUTLS_SSL3) { ret = _gnutls_generate_master (session, 1); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_mac_deinit_ssl3_handshake (&td_sha, &concat[16], session->security_parameters. master_secret, GNUTLS_MASTER_SIZE); } else _gnutls_hash_deinit (&td_sha, &concat[16]); switch (cert->subject_pk_algorithm) { case GNUTLS_PK_RSA: ret = _gnutls_hash_copy (&td_md5, &session->internals.handshake_mac_handle_md5); if (ret < 0) { gnutls_assert (); return ret; } if (ver == GNUTLS_SSL3) _gnutls_mac_deinit_ssl3_handshake (&td_md5, concat, session->security_parameters. master_secret, GNUTLS_MASTER_SIZE); else _gnutls_hash_deinit (&td_md5, concat); dconcat.data = concat; dconcat.size = 36; break; case GNUTLS_PK_DSA: dconcat.data = &concat[16]; dconcat.size = 20; break; default: gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } ret = _gnutls_tls_sign (session, cert, pkey, &dconcat, signature); if (ret < 0) { gnutls_assert (); } return ret; }
/* 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_cert * cert, gnutls_privkey * 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; handshake_td = &session->internals.handshake_mac_handle.tls12.sha1; hash_algo = handshake_td->algorithm; sign_algo = _gnutls_x509_pk_to_sign (cert->subject_pk_algorithm, hash_algo); /* The idea here is to try signing with the one of the algorithms * that have been initiated at handshake (SHA1, SHA256). If they * are not requested by peer... tough luck */ ret = _gnutls_session_sign_algo_requested (session, sign_algo); if (sign_algo == GNUTLS_SIGN_UNKNOWN || ret < 0) { handshake_td = &session->internals.handshake_mac_handle.tls12.sha256; hash_algo = handshake_td->algorithm; sign_algo = _gnutls_x509_pk_to_sign (cert->subject_pk_algorithm, hash_algo); if (sign_algo == GNUTLS_SIGN_UNKNOWN) { gnutls_assert (); return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM; } ret = _gnutls_session_sign_algo_requested (session, sign_algo); if (ret < 0) { gnutls_assert (); _gnutls_x509_log ("Server did not allow either '%s' or '%s' for signing\n", gnutls_mac_get_name (hash_algo), gnutls_mac_get_name (session->internals.handshake_mac_handle. tls12.sha1.algorithm)); return ret; } } _gnutls_x509_log ("sign handshake cert vrfy: picked %s with %s\n", gnutls_sign_algorithm_get_name (sign_algo), gnutls_mac_get_name (hash_algo)); 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 = _gnutls_tls_sign (session, 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_tls_sign_params (gnutls_session_t session, gnutls_cert * cert, gnutls_privkey * pkey, gnutls_datum_t * params, gnutls_datum_t * signature) { gnutls_datum_t dconcat; int ret; digest_hd_st td_sha; opaque concat[36]; gnutls_protocol_t ver = gnutls_protocol_get_version (session); ret = _gnutls_hash_init (&td_sha, GNUTLS_MAC_SHA1); 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 (ver < GNUTLS_TLS1_2) { 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.size = 36; } else { #if 1 /* Use NULL parameters. */ memcpy (concat, "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14", 15); _gnutls_hash_deinit (&td_sha, &concat[15]); dconcat.size = 35; #else /* No parameters field. */ memcpy (concat, "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14", 13); _gnutls_hash_deinit (&td_sha, &concat[13]); dconcat.size = 33; #endif } dconcat.data = concat; break; case GNUTLS_PK_DSA: _gnutls_hash_deinit (&td_sha, concat); 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_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; }