Re: AES-GCM Part 1: AES-GCM implementation

Previous thread: Kill struct dkdriver, redux by Matthew Dempsky on Friday, August 20, 2010 - 9:53 am. (2 messages)

Next thread: pckbc_isa.c cleanup by Alexandr Shadchin on Friday, August 20, 2010 - 11:52 pm. (1 message)
From: Mike Belopuhov
Date: Friday, August 20, 2010 - 11:58 am

Hi,

This is a first diff of a series that brings support for the
Galois/Counter Mode for AES in OpenBSD.

Intro
=====

For those unfamiliar with GCM, I'm going to quote Wikipedia[1]:

  GCM mode (Galois/Counter Mode) is a mode of operation for symmetri
  key cryptographic block ciphers. It is an authenticated encryption
  algorithm designed to provide both authentication and secrecy.
  GCM mode is defined for block ciphers with a block size of 128 bits.
  GMAC is an authentication-only variant of the GCM.

So GCM is an emerging standard for IPsec that is approved by NIST
in the NIST Special Publication 800-38D[2].  It's unencumbered by
patents.

GCM is cryptographically secure as long as underlying cipher is
secure; it heavily relies on uniqueness and non-repeating of the
Initialization Vector.  Also use of IKE is mandatory for GCM.
Quoting RFC 4106[3]:

  Because reusing an nonce/key combination destroys the security
  guarantees of AES-GCM mode, it can be difficult to use this mode
  securely when using statically configured keys.  For safety's sake,
  implementations MUST use an automated key management system, such as
  the Internet Key Exchange (IKE) [RFC2409], to ensure that this
  requirement is met.

"Authentication weaknesses in GCM" by Niels Ferguson[4] describes
some of the potentian issues with GCM in detail.

Implementation details
======================

As this is the first time a combined authentication-encryption
transformation hits OpenBSD kernel, I chose to split to split
it into two parts: encryption transformation and authentication
hash, AES-GCM and AES-GMAC respectively.

AES-GCM part is fairly simple and it reuses AES-CTR code to do
key generation, encryption and decryption.  IV handling is almost
the same, except that GCM spec requires to start counter with 1.

Here I have to note that AES-GCM is a stream cipher hence it has a
block size of "1".

Now GMAC is a bit different to HMAC-style functions.  Highlights:
 - uses one round of ...
From: Mike Belopuhov
Date: Friday, August 20, 2010 - 6:31 pm

I hope this will clarify the text above:

   - requires input date to be split into blocks of 16 bytes with
     the last block padded with zeros, otherwise it yeilds erroneous
     value, i.e.:
       given block C of 16 bytes that is a concatenation of chunks
       A and B (C = A || B), then GMAC(C, Z) =/= GMAC(B, GMAC(A, Z)),
       where GMAC(X, Y) denotes GMAC application to the chunk X and
       state block Y, Z denotes initial zero block.

From: Christian Weisgerber
Date: Sunday, August 22, 2010 - 12:40 pm

\o/


panic: unaligned access
This is exactly the rdate/ntp.c problem again.  You can't assume
that a char array is int32-aligned.

Also, why is this finalization not done for AES_GCM_16 and AES_GMAC?
This doesn't seem right.

AES_GCM_16 and AES_GMAC are missing from swcr_freesession().

AES_GMAC is missing from swcr_process() and swcr_init().

-- 
Christian "naddy" Weisgerber                          naddy@mips.inka.de

From: Mike Belopuhov
Date: Monday, August 23, 2010 - 5:09 am

true!  well, almost.  let me tell you something about GCC:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33594

excerpt:

The cause of the change in alignment seems to be the following:
- gcc 4.x allocates stack in cfgexpand.c, function expand_one_stack_var()
- this calls get_decl_align_unit(), also in cfgexpand.c
- the alignment is then read using macro DECL_ALIGN, which returns the
alignment of the type
- a further revision is made using macro LOCAL_ALIGNMENT
- however, LOCAL_ALIGNMENT is not defined for the sparc architecture (in
gcc/config/sparc.h), causing the alignment to remain as default

This was fixed in 4.3:
http://gcc.gnu.org/viewcvs/trunk/gcc/config/sparc/sparc.h?r1=127157&r2=129385&...

woohoo!




Index: conf/files
===================================================================
RCS file: /home/cvs/src/sys/conf/files,v
retrieving revision 1.499
diff -u -p -r1.499 files
--- conf/files	31 Jul 2010 08:33:19 -0000	1.499
+++ conf/files	3 Aug 2010 17:42:09 -0000
@@ -897,6 +897,7 @@ file crypto/arc4.c			
 file crypto/michael.c			wlan
 file crypto/cmac.c			wlan
 file crypto/hmac.c			wlan | (softraid & crypto)
+file crypto/gmac.c			(inet & ipsec) | crypto
 file crypto/key_wrap.c			wlan
 file crypto/idgen.c			inet6 | nfsclient | nfsserver
 file netatalk/aarp.c			netatalk
Index: crypto/cryptodev.c
===================================================================
RCS file: /home/cvs/src/sys/crypto/cryptodev.c,v
retrieving revision 1.73
diff -u -p -r1.73 cryptodev.c
--- crypto/cryptodev.c	21 Jul 2010 18:44:01 -0000	1.73
+++ crypto/cryptodev.c	26 Jul 2010 11:26:07 -0000
@@ -178,6 +178,9 @@ cryptof_ioctl(struct file *fp, u_long cm
 		case CRYPTO_AES_XTS:
 			txform = &enc_xform_aes_xts;
 			break;
+		case CRYPTO_AES_GCM_16:
+			txform = &enc_xform_aes_gcm;
+			break;
 		case CRYPTO_ARC4:
 			txform = &enc_xform_arc4;
 			break;
Index: crypto/cryptodev.h
===================================================================
RCS file: ...
From: Mark Kettenis
Date: Monday, August 23, 2010 - 2:35 pm

Ah, that's a good find.  I had been looking at LOCAL_ALIGNMENT before,
but wasn't sure that was the way to go.

I'm testing the diff from that bug report now on sparc64 and an
equivalent diff on hppa.

From: Mike Belopuhov
Date: Thursday, September 2, 2010 - 7:12 am

Latest version.  No changes since the last one, except for the
fixed CRYPTO_ALGORITHM_MAX. OK to commit? :)

Index: conf/files
===================================================================
RCS file: /home/cvs/src/sys/conf/files,v
retrieving revision 1.499
diff -u -p -u -p -r1.499 files
--- conf/files	31 Jul 2010 08:33:19 -0000	1.499
+++ conf/files	3 Aug 2010 17:42:09 -0000
@@ -897,6 +897,7 @@ file crypto/arc4.c			
 file crypto/michael.c			wlan
 file crypto/cmac.c			wlan
 file crypto/hmac.c			wlan | (softraid & crypto)
+file crypto/gmac.c			(inet & ipsec) | crypto
 file crypto/key_wrap.c			wlan
 file crypto/idgen.c			inet6 | nfsclient | nfsserver
 file netatalk/aarp.c			netatalk
Index: crypto/cryptodev.c
===================================================================
RCS file: /home/cvs/src/sys/crypto/cryptodev.c,v
retrieving revision 1.73
diff -u -p -u -p -r1.73 cryptodev.c
--- crypto/cryptodev.c	21 Jul 2010 18:44:01 -0000	1.73
+++ crypto/cryptodev.c	26 Jul 2010 11:26:07 -0000
@@ -178,6 +178,9 @@ cryptof_ioctl(struct file *fp, u_long cm
 		case CRYPTO_AES_XTS:
 			txform = &enc_xform_aes_xts;
 			break;
+		case CRYPTO_AES_GCM_16:
+			txform = &enc_xform_aes_gcm;
+			break;
 		case CRYPTO_ARC4:
 			txform = &enc_xform_arc4;
 			break;
Index: crypto/cryptodev.h
===================================================================
RCS file: /home/cvs/src/sys/crypto/cryptodev.h,v
retrieving revision 1.51
diff -u -p -u -p -r1.51 cryptodev.h
--- crypto/cryptodev.h	23 Jun 2010 09:26:32 -0000	1.51
+++ crypto/cryptodev.h	24 Aug 2010 09:19:42 -0000
@@ -105,7 +105,12 @@
 #define CRYPTO_SHA2_512_HMAC	20
 #define CRYPTO_AES_CTR		21
 #define CRYPTO_AES_XTS		22
-#define CRYPTO_ALGORITHM_MAX	22 /* Keep updated */
+#define CRYPTO_AES_GCM_16	23
+#define CRYPTO_AES_128_GMAC	24
+#define CRYPTO_AES_192_GMAC	25
+#define CRYPTO_AES_256_GMAC	26
+#define CRYPTO_AES_GMAC		27
+#define CRYPTO_ALGORITHM_MAX	27 /* Keep updated */
 
 /* Algorithm flags */
 ...
Previous thread: Kill struct dkdriver, redux by Matthew Dempsky on Friday, August 20, 2010 - 9:53 am. (2 messages)

Next thread: pckbc_isa.c cleanup by Alexandr Shadchin on Friday, August 20, 2010 - 11:52 pm. (1 message)