Most MACs other than GMAC (and Poly1305?) are not parallelizable. Examples include CMAC and HMAC.
Could these be securely parallelized by computing multiple MACs in parallel and then combining the result? This is sort of academic, just curious though.
Let's say you have a message being that you split into four parts such that M==M1|M2|M3|M4
. You then compute CMAC on each of these and then a final CMAC on the results.
T=CMAC(CMAC(M1)|CMAC(M2)|CMAC(M3)|CMAC(M4))
The advantage is that this could be implemented in a way that exploits instruction-level parallelism. Instead of splitting the message into four chunks you could implement this by computing four CMACs in parallel with a stride of 4*B where B is the block size of the cipher (e.g. 128-bit for AES). The final CMAC could also be done sort of in parallel with the last block of each component CMAC.
You could also potentially use those crazy 4X parallel AES instructions on CPUs that support AVX-512 to do four CMACs in true parallel.
Obviously, the result would be different from CMAC(M), but would the security be equivalent? This is basically a hash list so I'm thinking yes, but the MAC use case is different from ordinary hash use cases.
Edit: an even bolder thing would be to just compute four CMACs and XOR them, but since XOR is commutative that makes me think it would be vulnerable to chosen-plaintext attacks.
Edit #2: it appears the XOR case may be secure if each MAC is independently keyed, but I'd want to look into it more.
Edit #3: alternatively it seems like CMAC(M1|CMAC(M2)|CMAC(M3)|CMAC(M4))
should be secure if the above is secure. This can be done in parallel by computing CMAC on all four parts (or stripes) of the message and then doing three more blocks of the first CMAC to incorporate the siblings.
Edit #4: thinking about this more, I think the fastest algorithm would be to do N parallel HMACs/CMACs with different keys and then XOR them together. This is secure as long as the MACs are secure. You can't swap anything because the keys are different and so e.g. CMAC[k1](M1) XOR CMAC[k2](M2)
!= CMAC[k1](M2) XOR CMAC[k2](M1)
. On an AVX2 enabled machine you could use _mm512_aesenc_epi128 to do four CMACs at once with different keys in true parallel. Even without that instruction level parallelism would kick in if the CPU does it.
So you would have something like (pseudocode, using CMAC-AES with 16-byte blocks):
K1 = KDF(K,1)
K2 = KDF(K,2)
K3 = KDF(K,3)
K4 = KDF(K,4)
while (remaining >= 64) {
CMAC_BLOCK(K1,input)
CMAC_BLOCK(K2,input + 16)
CMAC_BLOCK(K3,input + 32)
CMAC_BLOCK(K4,input + 48)
remaining -= 64
input += 64
}
// ... do final blocks with padding ...
MAC = CMAC_FINAL(K1) XOR CMAC_FINAL(K2) XOR ...
A highly optimized implementation would interpolate the instructions for each AES round to allow ILP to work or use SIMD AES like _mm512_aesenc_epi128 if available.