diff --git a/crypto/openssl/openssl.c b/crypto/openssl/openssl.c index 17320ae9324ca599f0e50934db1b52ae3a8dfe6c..5e6a8493074a8eea23b44aaeadfd3ccd5ef8f721 100644 --- a/crypto/openssl/openssl.c +++ b/crypto/openssl/openssl.c @@ -381,11 +381,13 @@ int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls, rv = ngtcp2_decode_transport_params(¶ms, exttype, tp, tplen); if (rv != 0) { + ngtcp2_conn_set_tls_error(conn, rv); return -1; } rv = ngtcp2_conn_set_remote_transport_params(conn, ¶ms); if (rv != 0) { + ngtcp2_conn_set_tls_error(conn, rv); return -1; } diff --git a/examples/client.cc b/examples/client.cc index 84253fe187e4cc5fbdb0e0a44a4240d35f32748e..d25c54dbee6eebf0ceb997cb5c5a234c4ddb1043 100644 --- a/examples/client.cc +++ b/examples/client.cc @@ -475,6 +475,9 @@ int recv_crypto_data(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level, auto c = static_cast<Client *>(user_data); if (c->recv_crypto_data(crypto_level, data, datalen) != 0) { + if (auto err = ngtcp2_conn_get_tls_error(conn); err) { + return err; + } return NGTCP2_ERR_CRYPTO; } diff --git a/examples/server.cc b/examples/server.cc index 427a3d29af5719dc97ee577373b19edfffec0a9b..8797fe1c7c19840a83d724cb92cc95e6bdda5259 100644 --- a/examples/server.cc +++ b/examples/server.cc @@ -772,6 +772,9 @@ int recv_crypto_data(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level, auto h = static_cast<Handler *>(user_data); if (h->recv_crypto_data(crypto_level, data, datalen) != 0) { + if (auto err = ngtcp2_conn_get_tls_error(conn); err) { + return err; + } return NGTCP2_ERR_CRYPTO; } diff --git a/lib/includes/ngtcp2/ngtcp2.h b/lib/includes/ngtcp2/ngtcp2.h index 917cbb6f227404c138bc7b4a5c02a32016ccc6bb..936b876ef685c3f825b5b1c58e1ec100db1735a7 100644 --- a/lib/includes/ngtcp2/ngtcp2.h +++ b/lib/includes/ngtcp2/ngtcp2.h @@ -1932,6 +1932,27 @@ NGTCP2_EXTERN int ngtcp2_conn_install_key( NGTCP2_EXTERN int ngtcp2_conn_initiate_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts); +/** + * @function + * + * `ngtcp2_conn_set_tls_error` sets the TLS related error in |conn|. + * In general, error code should be propagated via return value, but + * sometimes ngtcp2 API is called inside callback function of TLS + * stack and it does not allow to return ngtcp2 error code directly. + * In this case, implementation can set the error code (e.g., + * NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM) using this function. + */ +NGTCP2_EXTERN void ngtcp2_conn_set_tls_error(ngtcp2_conn *conn, int liberr); + +/** + * @function + * + * `ngtcp2_conn_get_tls_error` returns the value set by + * `ngtcp2_conn_set_tls_error`. If no value is set, this function + * returns 0. + */ +NGTCP2_EXTERN int ngtcp2_conn_get_tls_error(ngtcp2_conn *conn); + /** * @function * diff --git a/lib/ngtcp2_conn.c b/lib/ngtcp2_conn.c index 4daf7914a87b5f4d996054a86b4aa841205e2ebd..bda3fde125d44fae452126ec235ce9375ed72080 100644 --- a/lib/ngtcp2_conn.c +++ b/lib/ngtcp2_conn.c @@ -9261,6 +9261,14 @@ void ngtcp2_conn_get_connection_close_error_code( *ccec = conn->rx.ccec; } +void ngtcp2_conn_set_tls_error(ngtcp2_conn *conn, int liberr) { + conn->crypto.tls_error = liberr; +} + +int ngtcp2_conn_get_tls_error(ngtcp2_conn *conn) { + return conn->crypto.tls_error; +} + void ngtcp2_path_challenge_entry_init(ngtcp2_path_challenge_entry *pcent, const uint8_t *data) { memcpy(pcent->data, data, sizeof(pcent->data)); diff --git a/lib/ngtcp2_conn.h b/lib/ngtcp2_conn.h index ba3a61a8eb799f2b68012320ac1bf7c2e4cff823..3b17a3d230ada7f310ec6ecf486c206e9d41f5d8 100644 --- a/lib/ngtcp2_conn.h +++ b/lib/ngtcp2_conn.h @@ -422,6 +422,8 @@ struct ngtcp2_conn { ngtcp2_vec decrypt_buf; /* retry_aead is AEAD to verify Retry packet integrity. */ ngtcp2_crypto_aead retry_aead; + /* tls_error is TLS related error. */ + int tls_error; } crypto; /* pkt contains the packet intermediate construction data to support diff --git a/lib/ngtcp2_err.c b/lib/ngtcp2_err.c index 10b6ef81d5e15622e8066cc9074877a173fbe20e..ae2edb35ee428fde5b3e4833d7403091748602a9 100644 --- a/lib/ngtcp2_err.c +++ b/lib/ngtcp2_err.c @@ -122,6 +122,7 @@ uint64_t ngtcp2_err_infer_quic_transport_error_code(int liberr) { return NGTCP2_FINAL_SIZE_ERROR; case NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM: case NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM: + case NGTCP2_ERR_TRANSPORT_PARAM: return NGTCP2_TRANSPORT_PARAMETER_ERROR; case NGTCP2_ERR_INVALID_ARGUMENT: return NGTCP2_INTERNAL_ERROR;