Plan 9 from Bell Labs’s /usr/web/sources/contrib/mospak/tls-modern-client/tls-aead-record-layer.patch

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


devtls: AEAD record layer (AES-GCM and ChaCha20-Poly1305)

Extends the kernel TLS record layer (#a/tls, devtls.c) to
support AEAD ciphers.  Prerequisite for any TLS 1.2 cipher
suite using AES-GCM or ChaCha20-Poly1305.

Applied identically to both kernel trees:
    sys/src/9/port/devtls.c    (i386 family)
    sys/src/9k/port/devtls.c   (amd64 family)

Secret gains aead_enc / aead_dec function pointers and a
recivlen field for the per-record explicit IV (8 bytes for
GCM, 0 for ChaCha20-Poly1305 under RFC 7905).  tlsrecread and
tlsrecwrite branch on sec->aead_{enc,dec}: the AEAD path builds
the 13-byte additional_data (RFC 5246 §6.2.3.3) and combines
encrypt+MAC; the legacy CBC+HMAC path is unchanged.  The
explicit GCM IV is derived salt||counter XOR sequence — matches
9front and avoids per-record random reads.  encrypttab[] gains
ccpoly96_aead, aes_128_gcm_aead, and aes_256_gcm_aead entries
recognized by the "secret" ctl command.

AEAD plumbing is modelled on 9front's devtls.c, adapted to
9legacy's framing (per-version packMac function pointer,
smalloc, randfill for the GCM IV seed).

RFC 5246 §6 (record protocol); 5288 §3 (AES-GCM);
7905 §2 (ChaCha20-Poly1305).

--- sys/src/9/port/devtls.c
+++ sys/src/9/port/devtls.c
@@ -87,7 +87,10 @@
 	int		(*dec)(Secret*, uchar*, int);
 	int		(*unpad)(uchar*, int, int);
 	DigestState	*(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+	int		(*aead_enc)(Secret*, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
+	int		(*aead_dec)(Secret*, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
 	int		block;		/* encryption block len, 0 if none */
+	int		recivlen;	/* explicit record IV length (AEAD only, else 0) */
 	int		maclen;
 	void		*enckey;
 	uchar	mackey[MaxMacLen];
@@ -238,6 +241,10 @@
 static int	des3dec(Secret *sec, uchar *buf, int n);
 static int	aesenc(Secret *sec, uchar *buf, int n);
 static int	aesdec(Secret *sec, uchar *buf, int n);
+static int	ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
+static int	ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
+static int	aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
+static int	aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
 static int	noenc(Secret *sec, uchar *buf, int n);
 static int	sslunpad(uchar *buf, int n, int block);
 static int	tlsunpad(uchar *buf, int n, int block);
@@ -734,9 +741,9 @@
 {
 	OneWay *volatile in;
 	Block *volatile b;
-	uchar *p, seq[8], header[RecHdrLen], hmac[MaxMacLen];
+	uchar *p, seq[8], header[RecHdrLen], hmac[MaxMacLen], aad[13];
 	int volatile nconsumed;
-	int len, type, ver, unpad_len;
+	int len, type, ver, unpad_len, ivlen;
 
 	nconsumed = 0;
 	if(waserror()){
@@ -801,32 +808,45 @@
 	if(in->sec != nil) {
 		/* to avoid Canvel-Hiltgen-Vaudenay-Vuagnoux attack, all errors here
 		        should look alike, including timing of the response. */
-		unpad_len = (*in->sec->dec)(in->sec, p, len);
+		if(in->sec->aead_dec != nil)
+			unpad_len = len;
+		else
+			unpad_len = (*in->sec->dec)(in->sec, p, len);
+if(tr->debug) pprint("decrypted %d\n", unpad_len);
+if(tr->debug) pdump(unpad_len, p, "decrypted:");
 
-		/* excplicit iv */
-		if(tr->version >= TLS11Version){
-			len -= in->sec->block;
-			if(len < 0)
-				rcvError(tr, EDecodeError, "runt record message");
+		/* explicit iv: AEAD uses recivlen, CBC uses block len starting from TLS 1.1 */
+		ivlen = in->sec->recivlen;
+		if(ivlen == 0 && tr->version >= TLS11Version)
+			ivlen = in->sec->block;
+		len -= ivlen;
+		if(len < 0)
+			rcvError(tr, EDecodeError, "runt record message");
+		unpad_len -= ivlen;
+		p += ivlen;
 
-			unpad_len -= in->sec->block;
-			p += in->sec->block;
-		}
-
 		if(unpad_len >= in->sec->maclen)
 			len = unpad_len - in->sec->maclen;
-if(tr->debug) pprint("decrypted %d\n", unpad_len);
-if(tr->debug) pdump(unpad_len, p, "decrypted:");
 
 		/* update length */
 		put16(header+3, len);
 		put64(seq, in->seq);
 		in->seq++;
-		(*tr->packMac)(in->sec, in->sec->mackey, seq, header, p, len, hmac);
-		if(unpad_len < in->sec->maclen)
-			rcvError(tr, EBadRecordMac, "short record mac");
-		if(memcmp(hmac, p+len, in->sec->maclen) != 0)
-			rcvError(tr, EBadRecordMac, "record mac mismatch");
+
+		if(in->sec->aead_dec != nil) {
+			/* aad per RFC 5246 §6.2.3.3: seq (8) | type (1) | version (2) | length (2) */
+			memmove(aad, seq, 8);
+			memmove(aad+8, header, RecHdrLen);
+			len = (*in->sec->aead_dec)(in->sec, aad, sizeof(aad), p - ivlen, p, unpad_len);
+			if(len < 0)
+				rcvError(tr, EBadRecordMac, "record mac mismatch");
+		} else {
+			(*tr->packMac)(in->sec, in->sec->mackey, seq, header, p, len, hmac);
+			if(unpad_len < in->sec->maclen)
+				rcvError(tr, EBadRecordMac, "short record mac");
+			if(memcmp(hmac, p+len, in->sec->maclen) != 0)
+				rcvError(tr, EBadRecordMac, "record mac mismatch");
+		}
 		b->rp = p;
 		b->wp = p+len;
 	}
@@ -1279,7 +1299,8 @@
 		if(out->sec != nil){
 			maclen = out->sec->maclen;
 			pad = maclen + out->sec->block;
-			if(tr->version >= TLS11Version)
+			ivlen = out->sec->recivlen;
+			if(ivlen == 0 && tr->version >= TLS11Version)
 				ivlen = out->sec->block;
 		}
 		n = BLEN(bb);
@@ -1308,17 +1329,26 @@
 		if(out->sec != nil){
 			put64(seq, out->seq);
 			out->seq++;
-			(*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen + ivlen, n, p + RecHdrLen + ivlen + n);
-			n += maclen;
 
-			/* explicit iv */
-			if(ivlen > 0){
-				randfill(p + RecHdrLen, ivlen);
-				n += ivlen;
-			}
+			if(out->sec->aead_enc != nil){
+				/* aad per RFC 5246 §6.2.3.3: seq (8) | type (1) | version (2) | length (2) */
+				uchar aad[13];
+				memmove(aad, seq, 8);
+				memmove(aad+8, p, RecHdrLen);
+				n = (*out->sec->aead_enc)(out->sec, aad, sizeof(aad), p + RecHdrLen, p + RecHdrLen + ivlen, n) + ivlen;
+			} else {
+				(*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen + ivlen, n, p + RecHdrLen + ivlen + n);
+				n += maclen;
 
-			/* encrypt */
-			n = (*out->sec->enc)(out->sec, p + RecHdrLen, n);
+				/* explicit iv */
+				if(ivlen > 0){
+					randfill(p + RecHdrLen, ivlen);
+					n += ivlen;
+				}
+
+				/* encrypt */
+				n = (*out->sec->enc)(out->sec, p + RecHdrLen, n);
+			}
 			nb->wp = p + RecHdrLen + n;
 
 			/* update length */
@@ -1489,6 +1519,32 @@
 }
 
 static void
+initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
+{
+	s->enckey = smalloc(sizeof(Chachastate));
+	s->aead_enc = ccpoly_aead_enc;
+	s->aead_dec = ccpoly_aead_dec;
+	s->maclen = Poly1305dlen;
+	/* RFC 7905: 96-bit iv xored with sequence number (stored in mackey as salt) */
+	memmove(s->mackey, iv, ea->ivlen);
+	setupChachastate(s->enckey, p, ea->keylen, iv, ea->ivlen, 20);
+}
+
+static void
+initaesgcmkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
+{
+	s->enckey = smalloc(sizeof(AESGCMstate));
+	s->aead_enc = aesgcm_aead_enc;
+	s->aead_dec = aesgcm_aead_dec;
+	s->maclen = 16;
+	s->recivlen = 8;
+	/* mackey slot holds 4-byte salt || 8-byte running explicit-IV counter */
+	memmove(s->mackey, iv, ea->ivlen);
+	randfill(s->mackey + ea->ivlen, s->recivlen);
+	setupAESGCMstate(s->enckey, p, ea->keylen, nil, 0);
+}
+
+static void
 initclearenc(Encalg *, Secret *s, uchar *, uchar *)
 {
 	s->enc = noenc;
@@ -1503,6 +1559,9 @@
 	{ "3des_ede_cbc", 3 * 8, 8, initDES3key },
 	{ "aes_128_cbc", 128/8, 16, initAESkey },
 	{ "aes_256_cbc", 256/8, 16, initAESkey },
+	{ "ccpoly96_aead", 256/8, 96/8, initccpolykey },
+	{ "aes_128_gcm_aead", 128/8, 4, initaesgcmkey },
+	{ "aes_256_gcm_aead", 256/8, 4, initaesgcmkey },
 	{ 0 }
 };
 
@@ -2092,6 +2151,77 @@
 {
 	aesCBCdecrypt(buf, n, sec->enckey);
 	return (*sec->unpad)(buf, n, 16);
+}
+
+static void
+ccpoly_aead_setiv(Secret *sec, uchar seq[8])
+{
+	uchar iv[ChachaIVlen];
+	Chachastate *cs;
+	int i;
+
+	cs = (Chachastate*)sec->enckey;
+	memmove(iv, sec->mackey, ChachaIVlen);
+	for(i=0; i<8; i++)
+		iv[i+(ChachaIVlen-8)] ^= seq[i];
+	chacha_setiv(cs, iv);
+	memset(iv, 0, sizeof(iv));
+}
+
+static int
+ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len)
+{
+	USED(reciv);
+	ccpoly_aead_setiv(sec, aad);
+	ccpoly_encrypt(data, len, aad, aadlen, data+len, sec->enckey);
+	return len + sec->maclen;
+}
+
+static int
+ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len)
+{
+	USED(reciv);
+	len -= sec->maclen;
+	if(len < 0)
+		return -1;
+	ccpoly_aead_setiv(sec, aad);
+	if(ccpoly_decrypt(data, len, aad, aadlen, data+len, sec->enckey) != 0)
+		return -1;
+	return len;
+}
+
+static int
+aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len)
+{
+	uchar iv[12];
+	int i;
+
+	/* explicit IV = salt(4) || counter(8) XOR seq(8).  sec->mackey = salt||counter. */
+	memmove(iv, sec->mackey, 4+8);
+	for(i=0; i<8; i++)
+		iv[4+i] ^= aad[i];
+	memmove(reciv, iv+4, 8);
+	aesgcm_setiv(sec->enckey, iv, 12);
+	memset(iv, 0, sizeof(iv));
+	aesgcm_encrypt(data, len, aad, aadlen, data+len, sec->enckey);
+	return len + sec->maclen;
+}
+
+static int
+aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len)
+{
+	uchar iv[12];
+
+	len -= sec->maclen;
+	if(len < 0)
+		return -1;
+	memmove(iv, sec->mackey, 4);
+	memmove(iv+4, reciv, 8);
+	aesgcm_setiv(sec->enckey, iv, 12);
+	memset(iv, 0, sizeof(iv));
+	if(aesgcm_decrypt(data, len, aad, aadlen, data+len, sec->enckey) != 0)
+		return -1;
+	return len;
 }
 
 static DigestState*
--- sys/src/9k/port/devtls.c
+++ sys/src/9k/port/devtls.c
@@ -87,7 +87,10 @@
 	int		(*dec)(Secret*, uchar*, int);
 	int		(*unpad)(uchar*, int, int);
 	DigestState	*(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+	int		(*aead_enc)(Secret*, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
+	int		(*aead_dec)(Secret*, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
 	int		block;		/* encryption block len, 0 if none */
+	int		recivlen;	/* explicit record IV length (AEAD only, else 0) */
 	int		maclen;
 	void		*enckey;
 	uchar	mackey[MaxMacLen];
@@ -238,6 +241,10 @@
 static int	des3dec(Secret *sec, uchar *buf, int n);
 static int	aesenc(Secret *sec, uchar *buf, int n);
 static int	aesdec(Secret *sec, uchar *buf, int n);
+static int	ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
+static int	ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
+static int	aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
+static int	aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
 static int	noenc(Secret *sec, uchar *buf, int n);
 static int	sslunpad(uchar *buf, int n, int block);
 static int	tlsunpad(uchar *buf, int n, int block);
@@ -734,9 +741,9 @@
 {
 	OneWay *volatile in;
 	Block *volatile b;
-	uchar *p, seq[8], header[RecHdrLen], hmac[MaxMacLen];
+	uchar *p, seq[8], header[RecHdrLen], hmac[MaxMacLen], aad[13];
 	int volatile nconsumed;
-	int len, type, ver, unpad_len;
+	int len, type, ver, unpad_len, ivlen;
 
 	nconsumed = 0;
 	if(waserror()){
@@ -801,32 +808,45 @@
 	if(in->sec != nil) {
 		/* to avoid Canvel-Hiltgen-Vaudenay-Vuagnoux attack, all errors here
 		        should look alike, including timing of the response. */
-		unpad_len = (*in->sec->dec)(in->sec, p, len);
+		if(in->sec->aead_dec != nil)
+			unpad_len = len;
+		else
+			unpad_len = (*in->sec->dec)(in->sec, p, len);
+if(tr->debug) pprint("decrypted %d\n", unpad_len);
+if(tr->debug) pdump(unpad_len, p, "decrypted:");
 
-		/* excplicit iv */
-		if(tr->version >= TLS11Version){
-			len -= in->sec->block;
-			if(len < 0)
-				rcvError(tr, EDecodeError, "runt record message");
+		/* explicit iv: AEAD uses recivlen, CBC uses block len starting from TLS 1.1 */
+		ivlen = in->sec->recivlen;
+		if(ivlen == 0 && tr->version >= TLS11Version)
+			ivlen = in->sec->block;
+		len -= ivlen;
+		if(len < 0)
+			rcvError(tr, EDecodeError, "runt record message");
+		unpad_len -= ivlen;
+		p += ivlen;
 
-			unpad_len -= in->sec->block;
-			p += in->sec->block;
-		}
-
 		if(unpad_len >= in->sec->maclen)
 			len = unpad_len - in->sec->maclen;
-if(tr->debug) pprint("decrypted %d\n", unpad_len);
-if(tr->debug) pdump(unpad_len, p, "decrypted:");
 
 		/* update length */
 		put16(header+3, len);
 		put64(seq, in->seq);
 		in->seq++;
-		(*tr->packMac)(in->sec, in->sec->mackey, seq, header, p, len, hmac);
-		if(unpad_len < in->sec->maclen)
-			rcvError(tr, EBadRecordMac, "short record mac");
-		if(memcmp(hmac, p+len, in->sec->maclen) != 0)
-			rcvError(tr, EBadRecordMac, "record mac mismatch");
+
+		if(in->sec->aead_dec != nil) {
+			/* aad per RFC 5246 §6.2.3.3: seq (8) | type (1) | version (2) | length (2) */
+			memmove(aad, seq, 8);
+			memmove(aad+8, header, RecHdrLen);
+			len = (*in->sec->aead_dec)(in->sec, aad, sizeof(aad), p - ivlen, p, unpad_len);
+			if(len < 0)
+				rcvError(tr, EBadRecordMac, "record mac mismatch");
+		} else {
+			(*tr->packMac)(in->sec, in->sec->mackey, seq, header, p, len, hmac);
+			if(unpad_len < in->sec->maclen)
+				rcvError(tr, EBadRecordMac, "short record mac");
+			if(memcmp(hmac, p+len, in->sec->maclen) != 0)
+				rcvError(tr, EBadRecordMac, "record mac mismatch");
+		}
 		b->rp = p;
 		b->wp = p+len;
 	}
@@ -1279,7 +1299,8 @@
 		if(out->sec != nil){
 			maclen = out->sec->maclen;
 			pad = maclen + out->sec->block;
-			if(tr->version >= TLS11Version)
+			ivlen = out->sec->recivlen;
+			if(ivlen == 0 && tr->version >= TLS11Version)
 				ivlen = out->sec->block;
 		}
 		n = BLEN(bb);
@@ -1308,17 +1329,26 @@
 		if(out->sec != nil){
 			put64(seq, out->seq);
 			out->seq++;
-			(*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen + ivlen, n, p + RecHdrLen + ivlen + n);
-			n += maclen;
 
-			/* explicit iv */
-			if(ivlen > 0){
-				randfill(p + RecHdrLen, ivlen);
-				n += ivlen;
-			}
+			if(out->sec->aead_enc != nil){
+				/* aad per RFC 5246 §6.2.3.3: seq (8) | type (1) | version (2) | length (2) */
+				uchar aad[13];
+				memmove(aad, seq, 8);
+				memmove(aad+8, p, RecHdrLen);
+				n = (*out->sec->aead_enc)(out->sec, aad, sizeof(aad), p + RecHdrLen, p + RecHdrLen + ivlen, n) + ivlen;
+			} else {
+				(*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen + ivlen, n, p + RecHdrLen + ivlen + n);
+				n += maclen;
 
-			/* encrypt */
-			n = (*out->sec->enc)(out->sec, p + RecHdrLen, n);
+				/* explicit iv */
+				if(ivlen > 0){
+					randfill(p + RecHdrLen, ivlen);
+					n += ivlen;
+				}
+
+				/* encrypt */
+				n = (*out->sec->enc)(out->sec, p + RecHdrLen, n);
+			}
 			nb->wp = p + RecHdrLen + n;
 
 			/* update length */
@@ -1489,6 +1519,32 @@
 }
 
 static void
+initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
+{
+	s->enckey = smalloc(sizeof(Chachastate));
+	s->aead_enc = ccpoly_aead_enc;
+	s->aead_dec = ccpoly_aead_dec;
+	s->maclen = Poly1305dlen;
+	/* RFC 7905: 96-bit iv xored with sequence number (stored in mackey as salt) */
+	memmove(s->mackey, iv, ea->ivlen);
+	setupChachastate(s->enckey, p, ea->keylen, iv, ea->ivlen, 20);
+}
+
+static void
+initaesgcmkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
+{
+	s->enckey = smalloc(sizeof(AESGCMstate));
+	s->aead_enc = aesgcm_aead_enc;
+	s->aead_dec = aesgcm_aead_dec;
+	s->maclen = 16;
+	s->recivlen = 8;
+	/* mackey slot holds 4-byte salt || 8-byte running explicit-IV counter */
+	memmove(s->mackey, iv, ea->ivlen);
+	randfill(s->mackey + ea->ivlen, s->recivlen);
+	setupAESGCMstate(s->enckey, p, ea->keylen, nil, 0);
+}
+
+static void
 initclearenc(Encalg *, Secret *s, uchar *, uchar *)
 {
 	s->enc = noenc;
@@ -1503,6 +1559,9 @@
 	{ "3des_ede_cbc", 3 * 8, 8, initDES3key },
 	{ "aes_128_cbc", 128/8, 16, initAESkey },
 	{ "aes_256_cbc", 256/8, 16, initAESkey },
+	{ "ccpoly96_aead", 256/8, 96/8, initccpolykey },
+	{ "aes_128_gcm_aead", 128/8, 4, initaesgcmkey },
+	{ "aes_256_gcm_aead", 256/8, 4, initaesgcmkey },
 	{ 0 }
 };
 
@@ -2092,6 +2151,77 @@
 {
 	aesCBCdecrypt(buf, n, sec->enckey);
 	return (*sec->unpad)(buf, n, 16);
+}
+
+static void
+ccpoly_aead_setiv(Secret *sec, uchar seq[8])
+{
+	uchar iv[ChachaIVlen];
+	Chachastate *cs;
+	int i;
+
+	cs = (Chachastate*)sec->enckey;
+	memmove(iv, sec->mackey, ChachaIVlen);
+	for(i=0; i<8; i++)
+		iv[i+(ChachaIVlen-8)] ^= seq[i];
+	chacha_setiv(cs, iv);
+	memset(iv, 0, sizeof(iv));
+}
+
+static int
+ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len)
+{
+	USED(reciv);
+	ccpoly_aead_setiv(sec, aad);
+	ccpoly_encrypt(data, len, aad, aadlen, data+len, sec->enckey);
+	return len + sec->maclen;
+}
+
+static int
+ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len)
+{
+	USED(reciv);
+	len -= sec->maclen;
+	if(len < 0)
+		return -1;
+	ccpoly_aead_setiv(sec, aad);
+	if(ccpoly_decrypt(data, len, aad, aadlen, data+len, sec->enckey) != 0)
+		return -1;
+	return len;
+}
+
+static int
+aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len)
+{
+	uchar iv[12];
+	int i;
+
+	/* explicit IV = salt(4) || counter(8) XOR seq(8).  sec->mackey = salt||counter. */
+	memmove(iv, sec->mackey, 4+8);
+	for(i=0; i<8; i++)
+		iv[4+i] ^= aad[i];
+	memmove(reciv, iv+4, 8);
+	aesgcm_setiv(sec->enckey, iv, 12);
+	memset(iv, 0, sizeof(iv));
+	aesgcm_encrypt(data, len, aad, aadlen, data+len, sec->enckey);
+	return len + sec->maclen;
+}
+
+static int
+aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len)
+{
+	uchar iv[12];
+
+	len -= sec->maclen;
+	if(len < 0)
+		return -1;
+	memmove(iv, sec->mackey, 4);
+	memmove(iv+4, reciv, 8);
+	aesgcm_setiv(sec->enckey, iv, 12);
+	memset(iv, 0, sizeof(iv));
+	if(aesgcm_decrypt(data, len, aad, aadlen, data+len, sec->enckey) != 0)
+		return -1;
+	return len;
 }
 
 static DigestState*

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.