How to implement aes{128,256)-gcm at openssh.com.

Jakub Jelen jjelen at redhat.com
Fri Jul 14 10:42:58 CEST 2023


On 7/14/23 08:04, Stef Bon wrote:
> Thanks a lot for answering,
> 
> The tag, can you compare it with the hmac integrity code?

The tag is conceptually same as the hmac, but for GCM it is part of the 
"cipher".

> And, I cannot read that directly from the code from libssh, it is
> placed directly like the hmac code after the encrypted message?

Correct. As visible from 
https://datatracker.ietf.org/doc/html/rfc5647#section-5.2 the Tag is 
placed directly in the mac field at the end of the binary packet.

> The iv, according to the libssh code is like:
> 
> 4B   fixed iv
> 8B   packet counter
> 4B   block counter

Correct. This is what is in the RFC:

https://datatracker.ietf.org/doc/html/rfc5647#section-7.1

> The function gcry_cipher_authenticate adds the blockcounter after the
> first 12 bytes.

I think the AAD used in here is only the packet length. See the RFC, 
under AAD, which is processed by the `gcry_cipher_authenticate` 
function, we have only the packet length (which is different from the 
counters):

https://datatracker.ietf.org/doc/html/rfc5647#section-7.2

> I cannot see the iv is 12 bytes long (and libgcrypt copies it to
> another buffer of 16 bytes) or it is 16 bytes already and libgcrypt
> uses that without copying. Can someone shine a light here?

The GCM has two counters, one invocation counter and one packet counter. 
The libgcrypt is able to handle the block counter in the last 4 bytes, 
but not the packet counter as it does not have any information about the 
packet boundary, so what we do in libssh is:

1) Restore the IV to the saved value (all 16 bytes) using 
gcry_cipher_setiv. This effectively increments the packet counter 
(calculated by previous call unless its the first packet) and resets the 
block counter as required by the rfc:
https://gitlab.com/libssh/libssh-mirror/-/blob/master/src/libgcrypt.c#L325

2) Increment the packet counter for the next iteration with 
uint64_inc(cipher->last_iv + 4); (the +4 is pointer arithmetics to 
reference the buffer as 64b unsigned int):
https://gitlab.com/libssh/libssh-mirror/-/blob/master/src/libgcrypt.c#L335

Hope it helps.

> BTW In the latest version of libgcrypt I see the function gcry_cipher_geniv(..)
> but not on the version installed on my OS (Gentoo, libgcrypt
> 1.10.2-unknown). It's not a problem, I prefer creating this iv on a
> higher level (in the code of my service).
> The aes128-gcm at openssh.com cipher uses its own source file and I can
> implement it there.

Thats what I was referring. This will likely be in the next libgcrypt 
release 1.11.x so for now, the above is probably the only way to 
implement this.

Regards,
-- 
Jakub Jelen
Crypto Team, Security Engineering
Red Hat, Inc.




More information about the Gcrypt-devel mailing list