If I am able to compare that the session keys and they are the same, can I assume that the connection is secure (no MITM present)?
Yes, baring attack on the extremities. That's a property of the Diffie-Hellman key exchange.
However, it is not satisfactory that the client sends (as envisioned) $\text{ENC}_\text{PK}(\text{Hash}(\text{Sym.Session Key})\mathbin\|\text{Hash}(\text{Password}))$ (without using further encryption with the session key) in order to check that the two ends share the same session key. The security depends on details of the public key encryption used. For example, in some forms of RSA encryption, we would have what's sent equal to $\text{ENC}_\text{PK}(\text{Hash}(\text{Sym.Session Key}))\mathbin\|\text{ENC}_\text{PK}(\text{Hash}(\text{Password}))$, the right term could be extracted by mere passive eavesdropping, then allowing that attacker to authenticate w.r.t. the server.
Also, there's the issue that libhydrogen does not seem to offer public key encryption (at least glancing at the table of content).
The simplest working solution is to send $\text{Hash}(\text{Password})$ within the secret-key authenticated encryption channel, as the first payload, and have the server decipher and check that against the correct value.
A convincing security argument (not proof) that the above is enough for security is that
- In a MitM attack modifying what's exchanged before the packet carrying the above payload, an attacker can't impersonate the server w.r.t. the client. The client will abort before anything related to $\text{Hash}(\text{Password})$ is sent.
- In an attack (passive or active) starting after that, the attacker has no knowledge of the session key, and that key won't be reused in another session. Hence whatever the adversary intercepts that depends on $\text{Hash}(\text{Password})$ does not leak information about that; and (independently) is of no use in later sessions.
- The use of correct authenticated encryption should take care of ensuring that whatever the adversary intercepts that depends on $\text{Hash}(\text{Password})$ is of no use in the current session (in particular, it is necessary that individually authenticated packets can't be replayed; if they could, replay of the packet with $\text{Hash}(\text{Password})$ in the right context could leak information about its plaintext).
However, the above simplest working solution is a tad brittle: if the server's private key leaks, an attacker impersonating the server w.r.t. a client can obtain the hash of the password (which is as good as the password for authentication purposes). And if a session keys leaks, passive eavesdropping allows the same.
Rather (and following the reasoning in the first part), we could send some MAC with key $\text{Hash}(\text{Password})$ and message $\text{Sym.Session Key}$, which the server can check. HMAC-SHA-256 would be suitable. There's an important incentive to further send that MAC thru the secret-key authenticated encryption channel: it prevents an adversary from checking a guess of the password unless s/he has the server's private key.
Note: If password is to be short enough to be conveniently keyed-in, or otherwise low-entropy, then $\text{Hash}(\text{Password})$ should still preferably be with a slow hash intended for passwords.
Note: No matter what, the password should have enough entropy to resist online password guesses, where an adversary attempts to authenticate w.r.t. the server using a dictionary of passwords. Limitation of the number of invalid attempts on the server (perhaps by a mere delay) can help with this.