--- sys/src/9/port/devtls.c
+++ sys/src/9/port/devtls.c
@@ -93,6 +93,7 @@ struct Secret
int recivlen; /* explicit record IV length (AEAD only, else 0) */
int maclen;
void *enckey;
+ int enckeylen; /* sizeof(*enckey) for zeroize-on-free */
uchar mackey[MaxMacLen];
};
@@ -1502,6 +1503,7 @@ initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *)
initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *)
{
s->enckey = smalloc(sizeof(RC4state));
+ s->enckeylen = sizeof(RC4state);
s->enc = rc4enc;
s->dec = rc4enc;
s->block = 0;
@@ -1512,6 +1514,7 @@ initDES3key(Encalg *, Secret *s, uchar *p, uchar *iv)
initDES3key(Encalg *, Secret *s, uchar *p, uchar *iv)
{
s->enckey = smalloc(sizeof(DES3state));
+ s->enckeylen = sizeof(DES3state);
s->enc = des3enc;
s->dec = des3dec;
s->block = 8;
@@ -1522,6 +1525,7 @@ initAESkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
initAESkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
{
s->enckey = smalloc(sizeof(AESstate));
+ s->enckeylen = sizeof(AESstate);
s->enc = aesenc;
s->dec = aesdec;
s->block = 16;
@@ -1532,6 +1536,7 @@ initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *
initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
{
s->enckey = smalloc(sizeof(Chachastate));
+ s->enckeylen = sizeof(Chachastate);
s->aead_enc = ccpoly_aead_enc;
s->aead_dec = ccpoly_aead_dec;
s->maclen = Poly1305dlen;
@@ -1544,6 +1549,7 @@ initaesgcmkey(Encalg *ea, Secret *s, uchar *p, uchar *
initaesgcmkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
{
s->enckey = smalloc(sizeof(AESGCMstate));
+ s->enckeylen = sizeof(AESGCMstate);
s->aead_enc = aesgcm_aead_enc;
s->aead_dec = aesgcm_aead_dec;
s->maclen = 16;
@@ -2071,11 +2077,27 @@ tlsstate(int s)
return "Unknown";
}
+/* secmemset zeroes through a volatile pointer so dead-store elimination
+ * cannot drop the writes. Plan 9 8c/kencc do not currently elide, but
+ * gcc/clang would; the volatile is defense against future toolchain ports. */
static void
+secmemset(void *p, int v, int n)
+{
+ volatile uchar *vp;
+
+ vp = p;
+ while(n-- > 0)
+ *vp++ = v;
+}
+
+static void
freeSec(Secret *s)
{
if(s != nil){
+ if(s->enckey != nil && s->enckeylen > 0)
+ secmemset(s->enckey, 0, s->enckeylen);
free(s->enckey);
+ secmemset(s, 0, sizeof(*s));
free(s);
}
}
--- sys/src/9k/port/devtls.c
+++ sys/src/9k/port/devtls.c
@@ -93,6 +93,7 @@ struct Secret
int recivlen; /* explicit record IV length (AEAD only, else 0) */
int maclen;
void *enckey;
+ int enckeylen; /* sizeof(*enckey) for zeroize-on-free */
uchar mackey[MaxMacLen];
};
@@ -1502,6 +1503,7 @@ initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *)
initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *)
{
s->enckey = smalloc(sizeof(RC4state));
+ s->enckeylen = sizeof(RC4state);
s->enc = rc4enc;
s->dec = rc4enc;
s->block = 0;
@@ -1512,6 +1514,7 @@ initDES3key(Encalg *, Secret *s, uchar *p, uchar *iv)
initDES3key(Encalg *, Secret *s, uchar *p, uchar *iv)
{
s->enckey = smalloc(sizeof(DES3state));
+ s->enckeylen = sizeof(DES3state);
s->enc = des3enc;
s->dec = des3dec;
s->block = 8;
@@ -1522,6 +1525,7 @@ initAESkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
initAESkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
{
s->enckey = smalloc(sizeof(AESstate));
+ s->enckeylen = sizeof(AESstate);
s->enc = aesenc;
s->dec = aesdec;
s->block = 16;
@@ -1532,6 +1536,7 @@ initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *
initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
{
s->enckey = smalloc(sizeof(Chachastate));
+ s->enckeylen = sizeof(Chachastate);
s->aead_enc = ccpoly_aead_enc;
s->aead_dec = ccpoly_aead_dec;
s->maclen = Poly1305dlen;
@@ -1544,6 +1549,7 @@ initaesgcmkey(Encalg *ea, Secret *s, uchar *p, uchar *
initaesgcmkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
{
s->enckey = smalloc(sizeof(AESGCMstate));
+ s->enckeylen = sizeof(AESGCMstate);
s->aead_enc = aesgcm_aead_enc;
s->aead_dec = aesgcm_aead_dec;
s->maclen = 16;
@@ -2071,11 +2077,27 @@ tlsstate(int s)
return "Unknown";
}
+/* secmemset zeroes through a volatile pointer so dead-store elimination
+ * cannot drop the writes. Plan 9 8c/kencc do not currently elide, but
+ * gcc/clang would; the volatile is defense against future toolchain ports. */
static void
+secmemset(void *p, int v, int n)
+{
+ volatile uchar *vp;
+
+ vp = p;
+ while(n-- > 0)
+ *vp++ = v;
+}
+
+static void
freeSec(Secret *s)
{
if(s != nil){
+ if(s->enckey != nil && s->enckeylen > 0)
+ secmemset(s->enckey, 0, s->enckeylen);
free(s->enckey);
+ secmemset(s, 0, sizeof(*s));
free(s);
}
}
|