JCE: add HmacSHA224 support to Mac implementation

pull/104/head
Chris Conlon 2025-03-03 13:51:37 -07:00
parent 0149a37ef1
commit dcddf92aaf
7 changed files with 260 additions and 10 deletions

View File

@ -108,6 +108,7 @@ The JCE provider currently supports the following algorithms:
Mac Class
HmacMD5
HmacSHA1
HmacSHA224
HmacSHA256
HmacSHA384
HmacSHA512

View File

@ -73,6 +73,14 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeMd5
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_wolfcrypt_Hmac
* Method: getCodeSha224
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha224
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_wolfcrypt_Hmac
* Method: getCodeSha256

View File

@ -46,6 +46,9 @@
#ifndef NO_SHA
#define SHA_DIGEST_SIZE WC_SHA_DIGEST_SIZE
#endif
#ifdef WOLFSSL_SHA224
#define SHA224_DIGEST_SIZE WC_SHA224_DIGEST_SIZE
#endif
#ifndef NO_SHA256
#define SHA256_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
#endif
@ -61,44 +64,44 @@
/* copy from cyassl/hmac.c */
static WC_INLINE int GetHashSizeByType(int type)
{
if (!(type == WC_MD5 || type == WC_SHA || type == WC_SHA256
|| type == WC_SHA384 || type == WC_SHA512))
if (!(type == WC_MD5 || type == WC_SHA || type == WC_SHA224
|| type == WC_SHA256 || type == WC_SHA384 || type == WC_SHA512)) {
return BAD_FUNC_ARG;
}
switch (type) {
#ifndef NO_MD5
case WC_MD5:
return MD5_DIGEST_SIZE;
break;
#endif
#ifndef NO_SHA
case WC_SHA:
return SHA_DIGEST_SIZE;
break;
#endif
#ifdef WOLFSSL_SHA224
case WC_SHA224:
return SHA224_DIGEST_SIZE;
#endif
#ifndef NO_SHA256
case WC_SHA256:
return SHA256_DIGEST_SIZE;
break;
#endif
#if defined(CYASSL_SHA384) || defined(WOLFSSL_SHA384)
case WC_SHA384:
return SHA384_DIGEST_SIZE;
break;
#endif
#if defined(CYASSL_SHA512) || defined(WOLFSSL_SHA512)
case WC_SHA512:
return SHA512_DIGEST_SIZE;
break;
#endif
default:
return BAD_FUNC_ARG;
break;
}
}
@ -355,6 +358,20 @@ Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha(
#endif
}
JNIEXPORT jint JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha224(
JNIEnv* env, jobject this)
{
#ifdef WOLFSSL_SHA224
jint result = WC_SHA224;
LogStr("WC_SHA224 = %d\n", result);
return result;
#else
/* not compiled in */
return (jint) -1;
#endif
}
JNIEXPORT jint JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha256(
JNIEnv* env, jobject this)

View File

@ -31,6 +31,7 @@ import javax.crypto.SecretKey;
import com.wolfssl.wolfcrypt.Md5;
import com.wolfssl.wolfcrypt.Sha;
import com.wolfssl.wolfcrypt.Sha224;
import com.wolfssl.wolfcrypt.Sha256;
import com.wolfssl.wolfcrypt.Sha384;
import com.wolfssl.wolfcrypt.Sha512;
@ -44,6 +45,7 @@ public class WolfCryptMac extends MacSpi {
enum HmacType {
WC_HMAC_MD5,
WC_HMAC_SHA,
WC_HMAC_SHA224,
WC_HMAC_SHA256,
WC_HMAC_SHA384,
WC_HMAC_SHA512
@ -72,6 +74,11 @@ public class WolfCryptMac extends MacSpi {
this.nativeHmacType = Hmac.SHA;
break;
case WC_HMAC_SHA224:
this.digestSize = Sha224.DIGEST_SIZE;
this.nativeHmacType = Hmac.SHA224;
break;
case WC_HMAC_SHA256:
this.digestSize = Sha256.DIGEST_SIZE;
this.nativeHmacType = Hmac.SHA256;
@ -163,6 +170,8 @@ public class WolfCryptMac extends MacSpi {
return "MD5";
case WC_HMAC_SHA:
return "SHA";
case WC_HMAC_SHA224:
return "SHA224";
case WC_HMAC_SHA256:
return "SHA256";
case WC_HMAC_SHA384:
@ -219,6 +228,21 @@ public class WolfCryptMac extends MacSpi {
}
}
/**
* wolfJCE HMAC-SHA2-224 class
*/
public static final class wcHmacSHA224 extends WolfCryptMac {
/**
* Create new wcHmacSHA224 object
*
* @throws NoSuchAlgorithmException if HMAC-SHA2-224 is not available at
* native wolfCrypt level.
*/
public wcHmacSHA224() throws NoSuchAlgorithmException {
super(HmacType.WC_HMAC_SHA224);
}
}
/**
* wolfJCE HMAC-SHA2-256 class
*/

View File

@ -142,6 +142,10 @@ public final class WolfCryptProvider extends Provider {
put("Mac.HmacSHA1",
"com.wolfssl.provider.jce.WolfCryptMac$wcHmacSHA1");
}
if (FeatureDetect.HmacSha224Enabled()) {
put("Mac.HmacSHA224",
"com.wolfssl.provider.jce.WolfCryptMac$wcHmacSHA224");
}
if (FeatureDetect.HmacSha256Enabled()) {
put("Mac.HmacSHA256",
"com.wolfssl.provider.jce.WolfCryptMac$wcHmacSHA256");

View File

@ -29,7 +29,7 @@ import java.nio.ByteBuffer;
public class Hmac extends NativeStruct {
private enum hashType {
typeMD5, typeSHA, typeSHA256, typeSHA384, typeSHA512;
typeMD5, typeSHA, typeSHA224, typeSHA256, typeSHA384, typeSHA512;
}
/* types may be -1 if not compiled in at native level */
@ -37,6 +37,8 @@ public class Hmac extends NativeStruct {
public static final int MD5 = getHashCode(hashType.typeMD5);
/** HMAC-SHA-1 type */
public static final int SHA = getHashCode(hashType.typeSHA);
/** HMAC-SHA2-224 type */
public static final int SHA224 = getHashCode(hashType.typeSHA224);
/** HMAC-SHA2-256 type */
public static final int SHA256 = getHashCode(hashType.typeSHA256);
/** HMAC-SHA2-384 type */
@ -95,6 +97,7 @@ public class Hmac extends NativeStruct {
private native int wc_HmacSizeByType(int type);
private native static int getCodeMd5();
private native static int getCodeSha();
private native static int getCodeSha224();
private native static int getCodeSha256();
private native static int getCodeSha384();
private native static int getCodeSha512();
@ -318,6 +321,9 @@ public class Hmac extends NativeStruct {
if (type == MD5) {
return "HmacMD5";
}
else if (type == SHA224) {
return "HmacSHA224";
}
else if (type == SHA256) {
return "HmacSHA256";
}
@ -359,6 +365,8 @@ public class Hmac extends NativeStruct {
return getCodeMd5();
case typeSHA:
return getCodeSha();
case typeSHA224:
return getCodeSha224();
case typeSHA256:
return getCodeSha256();
case typeSHA384:
@ -370,4 +378,3 @@ public class Hmac extends NativeStruct {
}
}
}

View File

@ -55,6 +55,7 @@ public class WolfCryptMacTest {
private static String wolfJCEAlgos[] = {
"HmacMD5",
"HmacSHA1",
"HmacSHA224",
"HmacSHA256",
"HmacSHA384",
"HmacSHA512"
@ -67,6 +68,7 @@ public class WolfCryptMacTest {
private static int wolfJCEMacLengths[] = {
16,
20,
28,
32,
48,
64
@ -337,6 +339,155 @@ public class WolfCryptMacTest {
}
}
@Test
public void testMacSha224SingleUpdate()
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchProviderException {
HmacVector[] vectors = new HmacVector[] {
/* HMAC vectors { key, input, output } */
/* Test vectors match test.c, from RFC 4231 section 4 */
new HmacVector(
new byte[] {
(byte)0x0b, (byte)0x0b, (byte)0x0b, (byte)0x0b,
(byte)0x0b, (byte)0x0b, (byte)0x0b, (byte)0x0b,
(byte)0x0b, (byte)0x0b, (byte)0x0b, (byte)0x0b,
(byte)0x0b, (byte)0x0b, (byte)0x0b, (byte)0x0b,
(byte)0x0b, (byte)0x0b, (byte)0x0b, (byte)0x0b
},
"Hi There".getBytes(),
new byte[] {
(byte)0x89, (byte)0x6f, (byte)0xb1, (byte)0x12,
(byte)0x8a, (byte)0xbb, (byte)0xdf, (byte)0x19,
(byte)0x68, (byte)0x32, (byte)0x10, (byte)0x7c,
(byte)0xd4, (byte)0x9d, (byte)0xf3, (byte)0x3f,
(byte)0x47, (byte)0xb4, (byte)0xb1, (byte)0x16,
(byte)0x99, (byte)0x12, (byte)0xba, (byte)0x4f,
(byte)0x53, (byte)0x68, (byte)0x4b, (byte)0x22
}
),
new HmacVector(
"Jefe".getBytes(),
"what do ya want for nothing?".getBytes(),
new byte[] {
(byte)0xa3, (byte)0x0e, (byte)0x01, (byte)0x09,
(byte)0x8b, (byte)0xc6, (byte)0xdb, (byte)0xbf,
(byte)0x45, (byte)0x69, (byte)0x0f, (byte)0x3a,
(byte)0x7e, (byte)0x9e, (byte)0x6d, (byte)0x0f,
(byte)0x8b, (byte)0xbe, (byte)0xa2, (byte)0xa3,
(byte)0x9e, (byte)0x61, (byte)0x48, (byte)0x00,
(byte)0x8f, (byte)0xd0, (byte)0x5e, (byte)0x44
}
),
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)0x7f, (byte)0xb3, (byte)0xcb, (byte)0x35,
(byte)0x88, (byte)0xc6, (byte)0xc1, (byte)0xf6,
(byte)0xff, (byte)0xa9, (byte)0x69, (byte)0x4d,
(byte)0x7d, (byte)0x6a, (byte)0xd2, (byte)0x64,
(byte)0x93, (byte)0x65, (byte)0xb0, (byte)0xc1,
(byte)0xf6, (byte)0x5d, (byte)0x69, (byte)0xd1,
(byte)0xec, (byte)0x83, (byte)0x33, (byte)0xea
}
),
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,
(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,
(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,
(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,
(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,
(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,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
(byte)0xAA, (byte)0xAA, (byte)0xAA
},
"Test Using Larger Than Block-Size Key - Hash Key First".getBytes(),
new byte[] {
(byte)0x95, (byte)0xe9, (byte)0xa0, (byte)0xdb,
(byte)0x96, (byte)0x20, (byte)0x95, (byte)0xad,
(byte)0xae, (byte)0xbe, (byte)0x9b, (byte)0x2d,
(byte)0x6f, (byte)0x0d, (byte)0xbc, (byte)0xe2,
(byte)0xd4, (byte)0x99, (byte)0xf1, (byte)0x12,
(byte)0xf2, (byte)0xd2, (byte)0xb7, (byte)0x27,
(byte)0x3f, (byte)0xa6, (byte)0x87, (byte)0x0e
}
)
};
for (int i = 0; i < vectors.length; i++) {
if ((i == 1) && Fips.enabled) {
/* FIPS doesn't allow short key lengths */
continue;
}
SecretKeySpec keyspec =
new SecretKeySpec(vectors[i].getKey(), "SHA224");
try {
Mac mac = Mac.getInstance("HmacSHA224", "wolfJCE");
mac.init(keyspec);
mac.update(vectors[i].getInput());
byte out[] = mac.doFinal();
assertArrayEquals(out, vectors[i].getOutput());
} catch (NoSuchAlgorithmException e) {
/* skip test if not available */
Assume.assumeTrue(false);
}
}
}
@Test
public void testMacSha256SingleUpdate()
throws InvalidKeyException, NoSuchAlgorithmException,
@ -815,6 +966,40 @@ public class WolfCryptMacTest {
}
);
HmacVector sha224Vector = 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)0x7f, (byte)0xb3, (byte)0xcb, (byte)0x35,
(byte)0x88, (byte)0xc6, (byte)0xc1, (byte)0xf6,
(byte)0xff, (byte)0xa9, (byte)0x69, (byte)0x4d,
(byte)0x7d, (byte)0x6a, (byte)0xd2, (byte)0x64,
(byte)0x93, (byte)0x65, (byte)0xb0, (byte)0xc1,
(byte)0xf6, (byte)0x5d, (byte)0x69, (byte)0xd1,
(byte)0xec, (byte)0x83, (byte)0x33, (byte)0xea
}
);
HmacVector sha256Vector = new HmacVector(
new byte[] {
(byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA,
@ -940,6 +1125,10 @@ public class WolfCryptMacTest {
threadRunnerMacTest("HmacSHA1", "SHA1", sha1Vector);
}
if (enabledAlgos.contains("HmacSHA224")) {
threadRunnerMacTest("HmacSHA224", "SHA224", sha224Vector);
}
if (enabledAlgos.contains("HmacSHA256")) {
threadRunnerMacTest("HmacSHA256", "SHA256", sha256Vector);
}