/* Parses the Signature Algorithm structure and stores data into * session->security_parameters.extensions. */ int _gnutls_sign_algorithm_parse_data (gnutls_session_t session, const opaque * data, size_t data_size) { int sig, i; session->security_parameters.extensions.sign_algorithms_size = 0; for (i = 0; i < data_size; i += 2) { sign_algorithm_st aid; aid.hash_algorithm = data[i]; aid.sign_algorithm = data[i + 1]; sig = _gnutls_tls_aid_to_sign (&aid); if (sig != GNUTLS_SIGN_UNKNOWN) { session->security_parameters.extensions.sign_algorithms[session-> security_parameters. extensions.sign_algorithms_size++] = sig; if (session->security_parameters.extensions.sign_algorithms_size == MAX_SIGNATURE_ALGORITHMS) break; } } return 0; }
/* Parses the Signature Algorithm structure and stores data into * session->security_parameters.extensions. */ int _gnutls_sign_algorithm_parse_data(gnutls_session_t session, const uint8_t * data, size_t data_size) { unsigned int sig, i; sig_ext_st *priv; extension_priv_data_t epriv; if (data_size % 2 != 0) return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); priv = gnutls_calloc(1, sizeof(*priv)); if (priv == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } for (i = 0; i < data_size; i += 2) { sign_algorithm_st aid; aid.hash_algorithm = data[i]; aid.sign_algorithm = data[i + 1]; sig = _gnutls_tls_aid_to_sign(&aid); _gnutls_handshake_log ("EXT[%p]: rcvd signature algo (%d.%d) %s\n", session, aid.hash_algorithm, aid.sign_algorithm, gnutls_sign_get_name(sig)); if (sig != GNUTLS_SIGN_UNKNOWN) { priv->sign_algorithms[priv-> sign_algorithms_size++] = sig; if (priv->sign_algorithms_size == MAX_SIGNATURE_ALGORITHMS) break; } } epriv = priv; _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, epriv); return 0; }
/* Parses the Signature Algorithm structure and stores data into * session->security_parameters.extensions. */ int _gnutls_sign_algorithm_parse_data (gnutls_session_t session, const opaque * data, size_t data_size) { int sig, i; sig_ext_st *priv; extension_priv_data_t epriv; priv = gnutls_calloc (1, sizeof (*priv)); if (priv == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } for (i = 0; i < data_size; i += 2) { sign_algorithm_st aid; aid.hash_algorithm = data[i]; aid.sign_algorithm = data[i + 1]; sig = _gnutls_tls_aid_to_sign (&aid); if (sig != GNUTLS_SIGN_UNKNOWN) { priv->sign_algorithms[priv->sign_algorithms_size++] = sig; if (priv->sign_algorithms_size == MAX_SIGNATURE_ALGORITHMS) break; } } epriv.ptr = priv; _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, epriv); return 0; }
static int proc_dhe_server_kx (gnutls_session_t session, opaque * data, 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) { gnutls_assert (); /* we need this in order to get peer's certificate */ return GNUTLS_E_INTERNAL_ERROR; } ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size, 0); if (ret < 0) { gnutls_assert (); return ret; } /* VERIFY SIGNATURE */ 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_UNSUPPORTED_SIGNATURE_ALGORITHM; } } DECR_LEN (data_size, 2); sigsize = _gnutls_read_uint16 (sigdata); sigdata += 2; DECR_LEN (data_size, sigsize); signature.data = sigdata; signature.size = sigsize; if ((ret = _gnutls_get_auth_info_gcert (&peer_cert, session->security_parameters.cert_type, info, CERT_NO_COPY)) < 0) { gnutls_assert (); return ret; } ret = _gnutls_handshake_verify_data (session, &peer_cert, &vparams, &signature, sign_algo); _gnutls_gcert_deinit (&peer_cert); if (ret < 0) { gnutls_assert (); return ret; } return ret; }
static int proc_srp_cert_server_kx(gnutls_session_t session, uint8_t * data, size_t _data_size) { ssize_t ret; int sigsize; gnutls_datum_t vparams, signature; ssize_t data_size; cert_auth_info_t info; gnutls_pcert_st peer_cert; uint8_t *p; gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN; const version_entry_st *ver = get_version(session); if (unlikely(ver == NULL)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); ret = _gnutls_proc_srp_server_kx(session, data, _data_size); if (ret < 0) return ret; data_size = _data_size - ret; info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); if (info == NULL || info->ncerts == 0) { gnutls_assert(); /* we need this in order to get peer's certificate */ return GNUTLS_E_INTERNAL_ERROR; } /* VERIFY SIGNATURE */ vparams.size = ret; /* all the data minus the signature */ vparams.data = data; p = &data[vparams.size]; if (_gnutls_version_has_selectable_sighash(ver)) { sign_algorithm_st aid; DECR_LEN(data_size, 1); aid.hash_algorithm = *p++; DECR_LEN(data_size, 1); aid.sign_algorithm = *p++; sign_algo = _gnutls_tls_aid_to_sign(&aid); if (sign_algo == GNUTLS_SIGN_UNKNOWN) { _gnutls_debug_log("unknown signature %d.%d\n", aid.sign_algorithm, aid.hash_algorithm); gnutls_assert(); return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM; } } DECR_LEN(data_size, 2); sigsize = _gnutls_read_uint16(p); DECR_LEN(data_size, sigsize); signature.data = &p[2]; signature.size = sigsize; ret = _gnutls_get_auth_info_pcert(&peer_cert, session->security_parameters. cert_type, info); if (ret < 0) { gnutls_assert(); return ret; } ret = _gnutls_handshake_verify_data(session, &peer_cert, &vparams, &signature, sign_algo); gnutls_pcert_deinit(&peer_cert); if (ret < 0) { gnutls_assert(); return ret; } return 0; }