First things first: the passage you quote does not claim that GHASH is slower than AES. What it says is that if you replace AES/CTR with a much faster stream cipher, then the GHASH part will be comparatively expensive.
There are many kinds of implementations, for both AES and GHASH; they have different performance characteristics, and they may be constant-time, or not. I'll use BearSSL here for most measures, because I know how that code works (I wrote it), and I can easily benchmark it. The measure platform here is my laptop (Intel i7-6567U at 3.3 GHz, in 64-bit mode):
AES-128 CTR (big) 170.67 MB/s
AES-128 CTR (ct64) 108.91 MB/s
AES-128 CTR (x86ni) 5307.37 MB/s
GHASH (ctmul) 214.63 MB/s
GHASH (ctmul64) 277.17 MB/s
GHASH (pclmul) 4795.76 MB/s
For the AES implementations:
- "big" is a classic table-based implementation (not constant-time).
- "ct64" is a constant-time bitslice implementation that uses 64-bit registers and computes 4 AES instances in parallel (which works well with CTR mode).
- "x86ni" uses the AES-NI opcodes (it computes four instances in parallel, which maps well to the 4-cycle latency of these opcodes on a Skylake core).
For the GHASH part:
- "ctmul" uses 32x32→64 integer multiplications with masking to avoid trouble with carries. It is constant-time.
- "ctmul64" uses 64x64→64 integer multiplications with masking; it is also constant-time.
- "pclmul" uses the AES-NI opcodes.
The following extra notes apply:
All GHASH implementations in BearSSL are constant-time. It is possible to make non-constant-time GHASH implementations which are faster, by using lookup tables, in particular dynamically generated tables for the specific secret $h$.
There is a constant-time bitslice implementation of AES that leverages SSE2 opcodes, both for extra parallelism (128-bit registers) and more efficient implementation of the linear parts of the algorithm. It would go over 400 MB/s on this machine, and would outperform the constant-time GHASH implementations. Whether it qualifies as "not using special opcodes" is debatable: it is not using the AES-NI opcodes, but not all 64-bit architectures have something similar to SSE2 (it is part of the ABI on 64-bit x86, though).
Combining AES and GHASH may offer speed-ups, if they do not exercise the same compute unit within the CPU. For instance, with the AES-NI opcodes, interleaving the AES/CTR encryption and the GHASH can yield better than the already quite decent 2.5 GB/s that the figures above promise.
An aggregate rule of thumb is that, when using only "basic" operations (i.e. those available in C without inline assembly or compiler intrinsics), you can keep the cost of GHASH to less than half the cost of AES/CTR (if using a non-constant-time AES, it makes more sense to measure against a non-constant-time GHASH).
Now let's compare with ChaCha20 and Poly1305:
ChaCha20 (ct) 407.74 MB/s
ChaCha20 (sse2) 590.59 MB/s
Poly1305 (ctmul) 1248.27 MB/s
Poly1305 (ctmulq) 1936.74 MB/s
The "ct" implementation of ChaCha20 uses only 32-bit integer operations; the "sse2" implementation uses SSE2 intrinsics. For Poly1305, the "ctmul" implementation uses basic 32x32→64 multiplications, while the "ctmulq" implementation uses 64x64→128 multiplications (which require some compiler intrinsics or extensions). All of these are constant-time.
What this says to us is the following:
- Without AES-NI, ChaCha20 outperforms AES. Actually, constant-time ChaCha20 substantially outperforms all AES, even non-constant-time.
- Without AES-NI, Poly1305 is much faster than GHASH.
- If you want to make an hybrid out of ChaCha20 and GHASH (this is the context of the previous question that you want to discuss), then the GHASH part is going to be more expensive than ChaCha20, except if you use the AES-NI opcodes for GHASH; but then, if AES-NI opcodes are available, why would you use that ChaCha20 hybrid instead of standard AES/GCM?