JNI: add synchronization around native Hmac pointer access in Hmac class

pull/53/head
Chris Conlon 2023-08-04 17:31:57 -06:00
parent f6ffb7489e
commit 79bed5d9d3
3 changed files with 578 additions and 83 deletions

View File

@ -50,6 +50,9 @@ public class Hmac extends NativeStruct {
private int type = -1;
private byte[] key;
/* Lock around object state */
protected final Object stateLock = new Object();
/**
* Create new Hmac object
*/
@ -90,7 +93,9 @@ public class Hmac extends NativeStruct {
/* check if type is -1, if so that type is not compiled in at native
* wolfSSL level. Throw exception if so. */
private void checkHashTypeCompiledIn(int type) throws WolfCryptException {
private void checkHashTypeCompiledIn(int type)
throws WolfCryptException {
WolfCryptError notCompiledIn = WolfCryptError.NOT_COMPILED_IN;
if (type == -1) {
throw new WolfCryptException(notCompiledIn.getCode());
@ -105,17 +110,22 @@ public class Hmac extends NativeStruct {
*
* @throws WolfCryptException if native operation fails
*/
public void setKey(int type, byte[] key) {
public synchronized void setKey(int type, byte[] key)
throws WolfCryptException {
synchronized (stateLock) {
/* verify hash type is compiled in */
checkHashTypeCompiledIn(type);
synchronized (pointerLock) {
wc_HmacSetKey(type, key);
}
this.type = type;
this.key = key;
state = WolfCryptState.READY;
}
}
/**
* Reset Hmac object state with key and type that have been set
@ -123,12 +133,16 @@ public class Hmac extends NativeStruct {
* @throws WolfCryptException if native operation fails
* @throws IllegalStateException if object has no key
*/
public void reset() {
public synchronized void reset()
throws WolfCryptException, IllegalStateException {
synchronized (stateLock) {
if (state == WolfCryptState.READY) {
setKey(type, key);
} else {
throw new IllegalStateException(
"No available key to perform the operation.");
"No available key to perform the operation");
}
}
}
@ -140,12 +154,19 @@ public class Hmac extends NativeStruct {
* @throws WolfCryptException if native operation fails
* @throws IllegalStateException if object has no key
*/
public void update(byte data) {
public synchronized void update(byte data)
throws WolfCryptException, IllegalStateException {
synchronized (stateLock) {
if (state == WolfCryptState.READY) {
synchronized (pointerLock) {
wc_HmacUpdate(data);
}
} else {
throw new IllegalStateException(
"No available key to perform the operation.");
"No available key to perform the operation");
}
}
}
@ -157,12 +178,19 @@ public class Hmac extends NativeStruct {
* @throws WolfCryptException if native operation fails
* @throws IllegalStateException if object has no key
*/
public void update(byte[] data) {
public void update(byte[] data)
throws WolfCryptException, IllegalStateException {
synchronized (stateLock) {
if (state == WolfCryptState.READY) {
synchronized (pointerLock) {
wc_HmacUpdate(data, 0, data.length);
}
} else {
throw new IllegalStateException(
"No available key to perform the operation.");
"No available key to perform the operation");
}
}
}
@ -176,12 +204,19 @@ public class Hmac extends NativeStruct {
* @throws WolfCryptException if native operation fails
* @throws IllegalStateException if object has no key
*/
public void update(byte[] data, int offset, int length) {
public synchronized void update(byte[] data, int offset, int length)
throws WolfCryptException, IllegalStateException {
synchronized (stateLock) {
if (state == WolfCryptState.READY) {
synchronized (pointerLock) {
wc_HmacUpdate(data, offset, length);
}
} else {
throw new IllegalStateException(
"No available key to perform the operation.");
"No available key to perform the operation");
}
}
}
@ -193,17 +228,23 @@ public class Hmac extends NativeStruct {
* @throws WolfCryptException if native operation fails
* @throws IllegalStateException if object has no key
*/
public void update(ByteBuffer data) {
public synchronized void update(ByteBuffer data)
throws WolfCryptException, IllegalStateException {
synchronized (stateLock) {
if (state == WolfCryptState.READY) {
int offset = data.position();
int length = data.remaining();
synchronized (pointerLock) {
wc_HmacUpdate(data, offset, length);
}
data.position(offset + length);
} else {
throw new IllegalStateException(
"No available key to perform the operation.");
"No available key to perform the operation");
}
}
}
@ -215,12 +256,19 @@ public class Hmac extends NativeStruct {
* @throws WolfCryptException if native operation fails
* @throws IllegalStateException if object has no key
*/
public byte[] doFinal() {
public synchronized byte[] doFinal()
throws WolfCryptException, IllegalStateException {
synchronized (stateLock) {
if (state == WolfCryptState.READY) {
synchronized (pointerLock) {
return wc_HmacFinal();
}
} else {
throw new IllegalStateException(
"No available key to perform the operation.");
"No available key to perform the operation");
}
}
}
@ -234,13 +282,20 @@ public class Hmac extends NativeStruct {
* @throws WolfCryptException if native operation fails
* @throws IllegalStateException if object has no key
*/
public byte[] doFinal(byte[] data) {
public synchronized byte[] doFinal(byte[] data)
throws WolfCryptException, IllegalStateException {
synchronized (stateLock) {
if (state == WolfCryptState.READY) {
update(data);
synchronized (pointerLock) {
return wc_HmacFinal();
}
} else {
throw new IllegalStateException(
"No available key to perform the operation.");
"No available key to perform the operation");
}
}
}
@ -251,9 +306,11 @@ public class Hmac extends NativeStruct {
*
* @throws IllegalStateException if object has no key
*/
public String getAlgorithm() {
if (state == WolfCryptState.READY) {
public synchronized String getAlgorithm()
throws IllegalStateException {
synchronized (stateLock) {
if (state == WolfCryptState.READY) {
if (type == MD5) {
return "HmacMD5";
}
@ -269,10 +326,10 @@ public class Hmac extends NativeStruct {
else {
return "";
}
} else {
throw new IllegalStateException(
"No available key to perform the operation.");
"No available key to perform the operation");
}
}
}
@ -284,12 +341,18 @@ public class Hmac extends NativeStruct {
* @throws WolfCryptException if native operation fails
* @throws IllegalStateException if object has no key
*/
public int getMacLength() {
public synchronized int getMacLength()
throws WolfCryptException, IllegalStateException {
synchronized (stateLock) {
if (state == WolfCryptState.READY) {
/* Does not use Hmac poiner, no need to lock */
return wc_HmacSizeByType(type);
} else {
throw new IllegalStateException(
"No available key to perform the operation.");
"No available key to perform the operation");
}
}
}

View File

@ -26,11 +26,17 @@ import org.junit.Test;
import org.junit.Assume;
import org.junit.BeforeClass;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Random;
import java.util.Iterator;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;
import java.security.Provider;
@ -665,6 +671,274 @@ public class WolfCryptMacTest {
}
}
private void threadRunnerMacTest(String hmacAlgo, String digest,
HmacVector vector) throws InterruptedException {
int numThreads = 20;
ExecutorService service = Executors.newFixedThreadPool(numThreads);
final CountDownLatch latch = new CountDownLatch(numThreads);
final LinkedBlockingQueue<Integer> results = new LinkedBlockingQueue<>();
final String currentAlgo = hmacAlgo;
final String mdAlgo = digest;
final byte[] key = vector.getKey();
final byte[] input = vector.getInput();
final byte[] output = vector.getOutput();
/* Do MAC in parallel across numThreads threads, all ops should pass */
for (int i = 0; i < numThreads; i++) {
service.submit(new Runnable() {
@Override public void run() {
int failed = 0;
SecretKeySpec keyspec = null;
Mac mac = null;
try {
keyspec = new SecretKeySpec(key, mdAlgo);
mac = Mac.getInstance(currentAlgo, "wolfJCE");
mac.init(keyspec);
mac.update(input);
byte out[] = mac.doFinal();
if (!Arrays.equals(out, output)) {
failed = 1;
}
} catch (Exception e) {
e.printStackTrace();
failed = 1;
} finally {
latch.countDown();
}
if (failed == 1) {
results.add(1);
}
else {
results.add(0);
}
}
});
}
/* wait for all threads to complete */
latch.await();
/* Look for any failures that happened */
Iterator<Integer> listIterator = results.iterator();
while (listIterator.hasNext()) {
Integer cur = listIterator.next();
if (cur == 1) {
fail("Threading error in MAC thread test: " + currentAlgo);
}
}
}
@Test
public void testThreadedMac() throws InterruptedException {
HmacVector md5Vector = new HmacVector(
new byte[] {
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
},
new byte[] {
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD
},
new byte[] {
(byte)0x56, (byte)0xbe, (byte)0x34, (byte)0x52,
(byte)0x1d, (byte)0x14, (byte)0x4c, (byte)0x88,
(byte)0xdb, (byte)0xb8, (byte)0xc7, (byte)0x33,
(byte)0xf0, (byte)0xe8, (byte)0xb3, (byte)0xf6
}
);
HmacVector sha1Vector = new HmacVector(
new byte[] {
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA
},
new byte[] {
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD
},
new byte[] {
(byte)0x12, (byte)0x5d, (byte)0x73, (byte)0x42,
(byte)0xb9, (byte)0xac, (byte)0x11, (byte)0xcd,
(byte)0x91, (byte)0xa3, (byte)0x9a, (byte)0xf4,
(byte)0x8a, (byte)0xa1, (byte)0x7b, (byte)0x4f,
(byte)0x63, (byte)0xf1, (byte)0x75, (byte)0xd3
}
);
HmacVector sha256Vector = new HmacVector(
new byte[] {
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA
},
new byte[] {
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD
},
new byte[] {
(byte)0x77, (byte)0x3e, (byte)0xa9, (byte)0x1e,
(byte)0x36, (byte)0x80, (byte)0x0e, (byte)0x46,
(byte)0x85, (byte)0x4d, (byte)0xb8, (byte)0xeb,
(byte)0xd0, (byte)0x91, (byte)0x81, (byte)0xa7,
(byte)0x29, (byte)0x59, (byte)0x09, (byte)0x8b,
(byte)0x3e, (byte)0xf8, (byte)0xc1, (byte)0x22,
(byte)0xd9, (byte)0x63, (byte)0x55, (byte)0x14,
(byte)0xce, (byte)0xd5, (byte)0x65, (byte)0xfe
}
);
HmacVector sha384Vector = new HmacVector(
new byte[] {
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA
},
new byte[] {
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD
},
new byte[] {
(byte)0x88, (byte)0x06, (byte)0x26, (byte)0x08,
(byte)0xd3, (byte)0xe6, (byte)0xad, (byte)0x8a,
(byte)0x0a, (byte)0xa2, (byte)0xac, (byte)0xe0,
(byte)0x14, (byte)0xc8, (byte)0xa8, (byte)0x6f,
(byte)0x0a, (byte)0xa6, (byte)0x35, (byte)0xd9,
(byte)0x47, (byte)0xac, (byte)0x9f, (byte)0xeb,
(byte)0xe8, (byte)0x3e, (byte)0xf4, (byte)0xe5,
(byte)0x59, (byte)0x66, (byte)0x14, (byte)0x4b,
(byte)0x2a, (byte)0x5a, (byte)0xb3, (byte)0x9d,
(byte)0xc1, (byte)0x38, (byte)0x14, (byte)0xb9,
(byte)0x4e, (byte)0x3a, (byte)0xb6, (byte)0xe1,
(byte)0x01, (byte)0xa3, (byte)0x4f, (byte)0x27
}
);
HmacVector sha512Vector = new HmacVector(
new byte[] {
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA
},
new byte[] {
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD, (byte)0xDD, (byte)0xDD,
(byte)0xDD, (byte)0xDD
},
new byte[] {
(byte)0xfa, (byte)0x73, (byte)0xb0, (byte)0x08,
(byte)0x9d, (byte)0x56, (byte)0xa2, (byte)0x84,
(byte)0xef, (byte)0xb0, (byte)0xf0, (byte)0x75,
(byte)0x6c, (byte)0x89, (byte)0x0b, (byte)0xe9,
(byte)0xb1, (byte)0xb5, (byte)0xdb, (byte)0xdd,
(byte)0x8e, (byte)0xe8, (byte)0x1a, (byte)0x36,
(byte)0x55, (byte)0xf8, (byte)0x3e, (byte)0x33,
(byte)0xb2, (byte)0x27, (byte)0x9d, (byte)0x39,
(byte)0xbf, (byte)0x3e, (byte)0x84, (byte)0x82,
(byte)0x79, (byte)0xa7, (byte)0x22, (byte)0xc8,
(byte)0x06, (byte)0xb4, (byte)0x85, (byte)0xa4,
(byte)0x7e, (byte)0x67, (byte)0xc8, (byte)0x07,
(byte)0xb9, (byte)0x46, (byte)0xa3, (byte)0x37,
(byte)0xbe, (byte)0xe8, (byte)0x94, (byte)0x26,
(byte)0x74, (byte)0x27, (byte)0x88, (byte)0x59,
(byte)0xe1, (byte)0x32, (byte)0x92, (byte)0xfb
}
);
if (enabledAlgos.contains("HmacMD5")) {
threadRunnerMacTest("HmacMD5", "MD5", md5Vector);
}
if (enabledAlgos.contains("HmacSHA1")) {
threadRunnerMacTest("HmacSHA1", "SHA1", sha1Vector);
}
if (enabledAlgos.contains("HmacSHA256")) {
threadRunnerMacTest("HmacSHA256", "SHA256", sha256Vector);
}
if (enabledAlgos.contains("HmacSHA384")) {
threadRunnerMacTest("HmacSHA384", "SHA384", sha384Vector);
}
if (enabledAlgos.contains("HmacSHA512")) {
threadRunnerMacTest("HmacSHA512", "SHA512", sha512Vector);
}
}
private class HmacVector {
private byte key[];

View File

@ -29,6 +29,15 @@ import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Random;
import java.util.Iterator;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import com.wolfssl.wolfcrypt.Hmac;
import com.wolfssl.wolfcrypt.NativeStruct;
import com.wolfssl.wolfcrypt.WolfCryptError;
@ -253,4 +262,153 @@ public class HmacTest {
}
}
}
private void threadRunnerHmacTest(int hmacType, byte[] inKey,
byte[] inData, byte[] inExpected)
throws InterruptedException {
int numThreads = 20;
ExecutorService service = Executors.newFixedThreadPool(numThreads);
final CountDownLatch latch = new CountDownLatch(numThreads);
final LinkedBlockingQueue<Integer> results = new LinkedBlockingQueue<>();
final int type = hmacType;
final byte[] key = inKey;
final byte[] data = inData;
final byte[] expected = inExpected;
/* Do HMAC across numThread threads, all should be successful */
for (int i = 0; i < numThreads; i++) {
service.submit(new Runnable() {
@Override public void run() {
int failed = 0;
Hmac hmac = null;
try {
hmac = new Hmac();
hmac.setKey(type, key);
hmac.update(data);
if (!Arrays.equals(expected, hmac.doFinal())) {
failed = 1;
}
if (failed == 0) {
hmac.reset();
hmac.update(data);
if (!Arrays.equals(expected, hmac.doFinal())) {
failed = 1;
}
}
} catch (Exception e) {
e.printStackTrace();
failed = 1;
} finally {
latch.countDown();
}
if (failed == 1) {
results.add(1);
}
else {
results.add(0);
}
}
});
}
/* wait for all threads to complete */
latch.await();
/* Look for any failures that happened */
Iterator<Integer> listIterator = results.iterator();
while (listIterator.hasNext()) {
Integer cur = listIterator.next();
if (cur == 1) {
fail("Threading error in HMAC thread test");
}
}
}
@Test
public void testThreadedHmac() throws InterruptedException {
if (Hmac.SHA != -1) {
threadRunnerHmacTest(Hmac.SHA,
Util.h2b("fd42f5044e3f70825102017f8521"), /* key */
Util.h2b("c9995cad63f60f7c7c552ac12c08" + /* data */
"0a7262cec4636d47c460c2abb47a" +
"f9bca09e18f9576c1415144595a7" +
"5da6fa232cb59d094d1a585c0710" +
"4856febcd05a58bde12a1f04795a" +
"e6e66a05b06f5dbe0dfa16c986fe" +
"fa8c3b2bce40cbb6c1ec74f1ad94" +
"7c1e9aadcf8584d5e9c45ec1f667" +
"567738b85bbdaad8dcd1e30fd35a" +
"3c61"),
Util.h2b("8865eb9df41dcc2e74360f0c97ae" + /* expected */
"567cb2377022")
);
}
if (Hmac.SHA256 != -1) {
threadRunnerHmacTest(Hmac.SHA256,
Util.h2b("26afdd2445b1f3cecbd4a797fed8"), /* key */
Util.h2b("bd74f8646cdd9b217927b04ef4ee" + /* data */
"ef0b8ef0b78fafcabb11c202f8e8" +
"d44aeaf15d03ff315d014cbbab8e" +
"7ed48ab114567eb0cc525ed35bf9" +
"a96b61bd1d139cb386365c3cd5d1" +
"37e4717afd8ad2a2efc24b172b77" +
"27cc6bd5f8ddef652cceb87ae114" +
"f7cdfbd6c56473f414b8f149e616" +
"9e2dbd46333e526b5761892a2703" +
"a50e"),
Util.h2b("208661dd6bdeab1c2843dfb8226c" + /* expected */
"be0a69db31aa183004e12025039f" +
"9fc2446a")
);
}
if (Hmac.SHA384 != -1) {
threadRunnerHmacTest(Hmac.SHA384,
Util.h2b("d35d6a733af2947fbdb4a67f5b3d"), /* key */
Util.h2b("44a8e36ec9b42a94a9627bd391f7" + /* data */
"114dad4296d31c3639a8a1d80188" +
"9b5c61e9378a0c81e4670a080712" +
"0c3ff0ecfd310dfbd9b95e91c244" +
"292851d8ef912a569e4ed3fc083c" +
"c62d9475c47534746dc8977a0e0a" +
"9f31bad5158f9c769cfe8b38e3ba" +
"dfe61f7a838bb9524c7c43d88998" +
"b186dccfc65f48e1ccd58a6888eb" +
"ad19"),
Util.h2b("346ff5f9b77866d72154b6b6965f" + /* expected */
"1f56e7c21ddf3392bdbe12e5dffb" +
"1d75e2f0d919c1e133c83b9b56d3" +
"17c3db1364de")
);
}
if (Hmac.SHA512 != -1) {
threadRunnerHmacTest(Hmac.SHA512,
Util.h2b("c3ec1135bb477eb81ca421deb9e0"), /* key */
Util.h2b("837dbbb0371bf60082c788c8f16f" + /* data */
"f883dd9216d235f7decf7ea09f9e" +
"17fa5d46c25673bf609c7c4dfc3e" +
"740c0b6c1bcbf2879a1dc9d769ae" +
"5f8070d47eb26d66702195d1c1b5" +
"7e6847823cfc60facbad7b61adff" +
"da82d33196a1c1cae3b0ee7495c6" +
"690de3ccc2fc6b7a28c17782cfd0" +
"7f0a95a0ef60e4ff29e9daa8ce5b" +
"a717"),
Util.h2b("517bd0146fe52cb464a0d555a7c2" + /* expected */
"9b5f9a604b07f32ff255f139156e" +
"214b6eb3836aa089987a5aca585e" +
"3cb10af8cb19c12a89628e8f59b6" +
"952ac4b7da7131f0")
);
}
}
}