[PATCH] Crypto EC - avoids possible memset compiler optimisation

David CARLIER devnexen at gmail.com
Mon Jan 8 15:13:29 UTC 2018


Hi,

Here a little patch proposal which is usually relevant in cryptographics
matters. Usually memset/bzero/... is used to clear private structures but
the compiler can possibly optimize those calls but with this change we can
unsure sensitive data is properly zero'ed using if possible native calls or
memory fence.

Kind regards.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/security-dev/attachments/20180108/c2bc056f/attachment.html>
-------------- next part --------------
diff --git a/src/jdk.crypto.ec/share/native/libsunec/impl/ec.c b/src/jdk.crypto.ec/share/native/libsunec/impl/ec.c
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ec.c
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ec.c
@@ -59,11 +59,7 @@
 #ifdef _KERNEL
 #define PORT_ZFree(p, l)                bzero((p), (l)); kmem_free((p), (l))
 #else
-#ifndef _WIN32
-#define PORT_ZFree(p, l)                bzero((p), (l)); free((p))
-#else
-#define PORT_ZFree(p, l)                memset((p), 0, (l)); free((p))
-#endif /* _WIN32 */
+#define PORT_ZFree(p, l)                mp_safe_memzero((p), (l)); free((p))
 #endif
 
 /*
@@ -323,7 +319,7 @@
     if (privKeyLen >= len) {
         memcpy(key->privateValue.data, privKeyBytes, len);
     } else {
-        memset(key->privateValue.data, 0, (len - privKeyLen));
+        mp_safe_memzero(key->privateValue.data, (len - privKeyLen));
         memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen);
     }
 
@@ -415,7 +411,7 @@
     CHECK_MPI_OK( mp_mod(&privKeyVal, &order_1, &privKeyVal) );
     CHECK_MPI_OK( mp_add(&privKeyVal, &one, &privKeyVal) );
     CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len) );
-    memset(privKeyBytes+len, 0, len);
+    mp_safe_memzero(privKeyBytes+len, len);
 cleanup:
     mp_clear(&privKeyVal);
     mp_clear(&order_1);
@@ -592,7 +588,7 @@
         return SECFailure;
     }
 
-    memset(derivedSecret, 0, sizeof *derivedSecret);
+    mp_safe_memzero(derivedSecret, sizeof *derivedSecret);
     len = (ecParams->fieldID.size + 7) >> 3;
     pointQ.len = 2*len + 1;
     if ((pointQ.data = PORT_Alloc(2*len + 1, kmflag)) == NULL) goto cleanup;
diff --git a/src/jdk.crypto.ec/share/native/libsunec/impl/mpi.c b/src/jdk.crypto.ec/share/native/libsunec/impl/mpi.c
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/mpi.c
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/mpi.c
@@ -2077,6 +2077,20 @@
   return n;
 }
 
+void mp_safe_memzero(void *a, mp_size len)
+{
+#if defined(_WIN32)
+  SecureZeroMemory(a, len);
+#elif defined(__FreeBSD__) || defined(__OpenBSD__)
+  explicit_bzero(a, len);
+#elif defined(__NetBSD__)
+  explicit_memset(a, 0, len);
+#else
+  memset(a, 0, len);
+  __asm__ volatile("" :: "r"(a) : "memory");
+#endif
+}
+
 /* Given a and prime p, computes c and k such that a*c == 2**k (mod p).
 ** Returns k (positive) or error (negative).
 ** This technique from the paper "Fast Modular Reciprocals" (unpublished)
diff --git a/src/jdk.crypto.ec/share/native/libsunec/impl/mpi.h b/src/jdk.crypto.ec/share/native/libsunec/impl/mpi.h
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/mpi.h
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/mpi.h
@@ -351,6 +351,7 @@
 
 /* Miscellaneous */
 mp_size mp_trailing_zeros(const mp_int *mp);
+void mp_safe_memzero(void *, mp_size);
 
 #define MP_CHECKOK(x)  if (MP_OKAY > (res = (x))) goto CLEANUP
 #define MP_CHECKERR(x) if (MP_OKAY > (res = (x))) goto CLEANUP


More information about the security-dev mailing list