Plan 9 from Bell Labs’s /usr/web/sources/contrib/yk/dist/9legacy/applied/aes-ctr.diff

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


The implementation of AES CTR mode had a flaw resulting in a
divide by zero when incrementing the counter, if its size
was 32 bits or larger.  While fixing this, the temptation
was irresistible to insert a fast path (avoiding mp arithmetic)
for the special case of a 32-bit counter (which is the size
mandated by RFC 3686 and used in ssh2).

Reference: /n/sources/patch/aes-ctr
Date: Mon Apr  9 13:35:14 GMT 2018
Signed-off-by: [email protected]

--- /sys/src/libsec/port/aes.c	Mon Apr  9 13:29:10 2018
+++ /sys/src/libsec/port/aes.c	Mon Apr  9 13:29:03 2018
@@ -77,6 +77,7 @@
 		keybytes = AESmaxkey;
 	memmove(s->key, key, keybytes);
 	s->keybytes = keybytes;
+	s->ctrsz = 4;	/* default counter size from rfc3686 */
 	s->rounds = aes_setup(s->ekey, s->dkey, s->key, keybytes * 8);
 	if(ivec != nil)
 		memmove(s->ivec, ivec, AESbsize);
@@ -230,12 +231,23 @@
 incrementCTR(uchar *p, uint ctrsz)
 {
 	int len;
+	ulong c;
 	uchar *ctr;
 	mpint *mpctr, *mpctrsz;
 
 	ctr = p + AESbsize - ctrsz;
+	if(ctrsz == 4){
+		/*
+		 * If counter is 32 bits (as in rfc3686 and ssh2) there's
+		 * no need to use extended precision.
+		 */
+		c = 1 + (ctr[0]<<24 | ctr[1]<<16 | ctr[2]<<8 | ctr[3]);
+		ctr[0] = c>>24; ctr[1] = c>>16; ctr[2] = c>>8; ctr[3] = c;
+		return;
+	}
 	mpctr = betomp(ctr, ctrsz, nil);
-	mpctrsz = itomp(1 << (ctrsz*8), nil);
+	mpctrsz = mpnew(ctrsz*8 + 1);
+	mpleft(mpone, ctrsz*8, mpctrsz);
 	mpadd(mpctr, mpone, mpctr);
 	mpmod(mpctr, mpctrsz, mpctr);
 	len = mptobe(mpctr, ctr, ctrsz, nil);

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].