From 589fa346c83f8dcbd5d41584a392fd602b8a240a Mon Sep 17 00:00:00 2001 From: Johannes Leupold Date: Mon, 18 Jul 2022 17:50:25 +0200 Subject: [PATCH 1/4] Add variants of sodium_memzero, sodium_mlock and sodium_munlock that accept a JNA Pointer in place of a byte array. --- .../com/goterl/lazysodium/LazySodium.java | 15 ++++++ .../java/com/goterl/lazysodium/Sodium.java | 3 ++ .../lazysodium/interfaces/SecureMemory.java | 26 ++++++++++ .../goterl/lazysodium/SecureMemoryTest.java | 49 +++++++++++++++++-- 4 files changed, 90 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/goterl/lazysodium/LazySodium.java b/src/main/java/com/goterl/lazysodium/LazySodium.java index 4c0e7ff..0e00749 100644 --- a/src/main/java/com/goterl/lazysodium/LazySodium.java +++ b/src/main/java/com/goterl/lazysodium/LazySodium.java @@ -205,16 +205,31 @@ public boolean sodiumMemZero(byte[] pnt, int len) { return successful(getSodium().sodium_memzero(pnt, len)); } + @Override + public boolean sodiumMemZero(Pointer pnt, int len) { + return successful(getSodium().sodium_memzero(pnt, len)); + } + @Override public boolean sodiumMLock(byte[] array, int len) { return successful(getSodium().sodium_mlock(array, len)); } + @Override + public boolean sodiumMLock(Pointer pnt, int len) { + return successful(getSodium().sodium_mlock(pnt, len)); + } + @Override public boolean sodiumMUnlock(byte[] array, int len) { return successful(getSodium().sodium_munlock(array, len)); } + @Override + public boolean sodiumMUnlock(Pointer pnt, int len) { + return successful(getSodium().sodium_munlock(pnt, len)); + } + @Override public Pointer sodiumMalloc(int size) { return getSodium().sodium_malloc(size); diff --git a/src/main/java/com/goterl/lazysodium/Sodium.java b/src/main/java/com/goterl/lazysodium/Sodium.java index 3588ee3..f593c47 100644 --- a/src/main/java/com/goterl/lazysodium/Sodium.java +++ b/src/main/java/com/goterl/lazysodium/Sodium.java @@ -73,8 +73,11 @@ public native int sodium_base642bin(byte[] bin, //// -------------------------------------------| public native int sodium_memzero(byte[] pnt, int len); + public native int sodium_memzero(Pointer pnt, int len); public native int sodium_mlock(byte[] addr, int len); + public native int sodium_mlock(Pointer addr, int len); public native int sodium_munlock(byte[] addr, int len); + public native int sodium_munlock(Pointer addr, int len); public native Pointer sodium_malloc(int size); public native Pointer sodium_allocarray(int count, int size); public native void sodium_free(Pointer p); diff --git a/src/main/java/com/goterl/lazysodium/interfaces/SecureMemory.java b/src/main/java/com/goterl/lazysodium/interfaces/SecureMemory.java index c9cb125..49a6005 100644 --- a/src/main/java/com/goterl/lazysodium/interfaces/SecureMemory.java +++ b/src/main/java/com/goterl/lazysodium/interfaces/SecureMemory.java @@ -25,6 +25,15 @@ interface Native { */ boolean sodiumMemZero(byte[] pnt, int len); + /** + * The sodium_memzero() function tries to effectively zero len bytes starting at pnt, + * even if optimizations are being applied to the code. + * @param pnt The pointer to zero out. + * @param len How many bytes to zero out. + * @return True if zeroed + */ + boolean sodiumMemZero(Pointer pnt, int len); + /** * Locks at least len bytes of memory from the array. * This can help avoid swapping sensitive data to disk. @@ -34,6 +43,15 @@ interface Native { */ boolean sodiumMLock(byte[] array, int len); + /** + * Locks at least len bytes of memory from the pointer. + * This can help avoid swapping sensitive data to disk. + * @param pnt pointer to the memory to lock. + * @param len Number of bytes to lock. + * @return True if locked, false otherwise. + */ + boolean sodiumMLock(Pointer pnt, int len); + /** * Unlocks at least len bytes of memory from the array. * @param array Array to unlock. @@ -42,6 +60,14 @@ interface Native { */ boolean sodiumMUnlock(byte[] array, int len); + /** + * Unlocks at least len bytes of memory from the pointer. + * @param pnt pointer to the memory to unlock. + * @param len Number of bytes to unlock. + * @return True if locked, false otherwise. + */ + boolean sodiumMUnlock(Pointer pnt, int len); + /** * Returns a pointer from which exactly * size contiguous bytes of memory can be accessed. diff --git a/src/test/java/com/goterl/lazysodium/SecureMemoryTest.java b/src/test/java/com/goterl/lazysodium/SecureMemoryTest.java index 11c4bfe..e756a33 100644 --- a/src/test/java/com/goterl/lazysodium/SecureMemoryTest.java +++ b/src/test/java/com/goterl/lazysodium/SecureMemoryTest.java @@ -6,13 +6,14 @@ * file, you can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.goterl.lazysodium;import com.sun.jna.Pointer; +package com.goterl.lazysodium; + +import com.sun.jna.Memory; +import com.sun.jna.Pointer; import junit.framework.TestCase; import org.junit.Test; public class SecureMemoryTest extends BaseTest { - - @Test public void memZero() { byte[] b = new byte[] { 4, 2, 2, 1 }; @@ -20,14 +21,45 @@ public void memZero() { TestCase.assertTrue(isZero(b)); } + @Test + public void memZeroPtr() { + Pointer p = new Memory(32); + p.write(0, lazySodium.randomBytesBuf(32), 0, 32); + TestCase.assertFalse(isZero(p.getByteArray(0, 32))); + + boolean res = lazySodium.sodiumMemZero(p, 32); + + TestCase.assertTrue(res); + TestCase.assertTrue(isZero(p.getByteArray(0, 32))); + + } + @Test public void mLock() { byte[] b = new byte[] { 4, 5, 2, 1 }; + boolean res = lazySodium.sodiumMLock(b, b.length); boolean res2 = lazySodium.sodiumMUnlock(b, b.length); + + TestCase.assertTrue(res); + TestCase.assertTrue(res2); TestCase.assertTrue(isZero(b)); } + @Test + public void mLockPtr() { + Pointer p = new Memory(32); + p.write(0, lazySodium.randomBytesBuf(32), 0, 32); + TestCase.assertFalse(isZero(p.getByteArray(0, 32))); + + boolean res = lazySodium.sodiumMLock(p, 32); + boolean res2 = lazySodium.sodiumMUnlock(p, 32); + + TestCase.assertTrue(res); + TestCase.assertTrue(res2); + TestCase.assertTrue(isZero(p.getByteArray(0, 32))); + } + @Test public void malloc() { int size = 10; @@ -39,6 +71,17 @@ public void malloc() { TestCase.assertEquals(arr.length, size); } + @Test + public void allocArray() { + int size = 10; + + Pointer ptr = lazySodium.sodiumAllocArray(size, 2); + + byte[] arr = ptr.getByteArray(0, size * 2); + + TestCase.assertEquals(arr.length, size * 2); + } + @Test public void free() { int size = 10; From 6f48d80f2408c024e0ff3ede2ea94b9ba7cc6348 Mon Sep 17 00:00:00 2001 From: Johannes Leupold Date: Mon, 18 Jul 2022 18:07:10 +0200 Subject: [PATCH 2/4] Try to update SHA-512 alg identifier and correct return type of sodium_memzero to void --- src/main/java/com/goterl/lazysodium/LazySodium.java | 6 ++++-- src/main/java/com/goterl/lazysodium/Sodium.java | 4 ++-- src/test/java/com/goterl/lazysodium/Ristretto255Test.java | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/goterl/lazysodium/LazySodium.java b/src/main/java/com/goterl/lazysodium/LazySodium.java index 0e00749..d0baa7e 100644 --- a/src/main/java/com/goterl/lazysodium/LazySodium.java +++ b/src/main/java/com/goterl/lazysodium/LazySodium.java @@ -202,12 +202,14 @@ public boolean sodiumUnpad(IntByReference unPaddedBuffLen, Pointer buf, int padd @Override public boolean sodiumMemZero(byte[] pnt, int len) { - return successful(getSodium().sodium_memzero(pnt, len)); + getSodium().sodium_memzero(pnt, len); + return true; } @Override public boolean sodiumMemZero(Pointer pnt, int len) { - return successful(getSodium().sodium_memzero(pnt, len)); + getSodium().sodium_memzero(pnt, len); + return true; } @Override diff --git a/src/main/java/com/goterl/lazysodium/Sodium.java b/src/main/java/com/goterl/lazysodium/Sodium.java index f593c47..8508202 100644 --- a/src/main/java/com/goterl/lazysodium/Sodium.java +++ b/src/main/java/com/goterl/lazysodium/Sodium.java @@ -72,8 +72,8 @@ public native int sodium_base642bin(byte[] bin, //// SECURE MEMORY //// -------------------------------------------| - public native int sodium_memzero(byte[] pnt, int len); - public native int sodium_memzero(Pointer pnt, int len); + public native void sodium_memzero(byte[] pnt, int len); + public native void sodium_memzero(Pointer pnt, int len); public native int sodium_mlock(byte[] addr, int len); public native int sodium_mlock(Pointer addr, int len); public native int sodium_munlock(byte[] addr, int len); diff --git a/src/test/java/com/goterl/lazysodium/Ristretto255Test.java b/src/test/java/com/goterl/lazysodium/Ristretto255Test.java index 6f9c28e..6f69db8 100644 --- a/src/test/java/com/goterl/lazysodium/Ristretto255Test.java +++ b/src/test/java/com/goterl/lazysodium/Ristretto255Test.java @@ -170,7 +170,7 @@ public void fromHash() throws Exception { }; for (int i = 0; i < testInput.length; ++i) { - MessageDigest sha512 = MessageDigest.getInstance("SHA512"); + MessageDigest sha512 = MessageDigest.getInstance("SHA-512"); byte[] hashed = sha512.digest(testInput[i].getBytes(StandardCharsets.UTF_8)); RistrettoPoint encoded = lazySodium.cryptoCoreRistretto255FromHash(hashed); From 4f2f263655706ee145d057a450cf13a13922d88d Mon Sep 17 00:00:00 2001 From: Johannes Leupold Date: Mon, 18 Jul 2022 18:10:46 +0200 Subject: [PATCH 3/4] Add missing sodium_free to malloc/allocArray tests to avoid leaking memory in tests --- src/test/java/com/goterl/lazysodium/SecureMemoryTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/java/com/goterl/lazysodium/SecureMemoryTest.java b/src/test/java/com/goterl/lazysodium/SecureMemoryTest.java index e756a33..8cfd064 100644 --- a/src/test/java/com/goterl/lazysodium/SecureMemoryTest.java +++ b/src/test/java/com/goterl/lazysodium/SecureMemoryTest.java @@ -69,6 +69,8 @@ public void malloc() { byte[] arr = ptr.getByteArray(0, size); TestCase.assertEquals(arr.length, size); + + lazySodium.sodiumFree(ptr); } @Test @@ -80,6 +82,8 @@ public void allocArray() { byte[] arr = ptr.getByteArray(0, size * 2); TestCase.assertEquals(arr.length, size * 2); + + lazySodium.sodiumFree(ptr); } @Test From 52c3eac22fb0a3404e6886c7625b6e98fc51ea29 Mon Sep 17 00:00:00 2001 From: Johannes Leupold Date: Mon, 18 Jul 2022 18:13:38 +0200 Subject: [PATCH 4/4] Revert previous commit, as it triggers a segfault in tests --- src/test/java/com/goterl/lazysodium/SecureMemoryTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/test/java/com/goterl/lazysodium/SecureMemoryTest.java b/src/test/java/com/goterl/lazysodium/SecureMemoryTest.java index 8cfd064..e756a33 100644 --- a/src/test/java/com/goterl/lazysodium/SecureMemoryTest.java +++ b/src/test/java/com/goterl/lazysodium/SecureMemoryTest.java @@ -69,8 +69,6 @@ public void malloc() { byte[] arr = ptr.getByteArray(0, size); TestCase.assertEquals(arr.length, size); - - lazySodium.sodiumFree(ptr); } @Test @@ -82,8 +80,6 @@ public void allocArray() { byte[] arr = ptr.getByteArray(0, size * 2); TestCase.assertEquals(arr.length, size * 2); - - lazySodium.sodiumFree(ptr); } @Test