diff --git a/README_JCE.md b/README_JCE.md index b3d9a37..3adba67 100644 --- a/README_JCE.md +++ b/README_JCE.md @@ -108,6 +108,7 @@ The JCE provider currently supports the following algorithms: Mac Class HmacMD5 HmacSHA1 + HmacSHA224 HmacSHA256 HmacSHA384 HmacSHA512 diff --git a/jni/include/com_wolfssl_wolfcrypt_Hmac.h b/jni/include/com_wolfssl_wolfcrypt_Hmac.h index f2e4460..a992d9f 100644 --- a/jni/include/com_wolfssl_wolfcrypt_Hmac.h +++ b/jni/include/com_wolfssl_wolfcrypt_Hmac.h @@ -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 diff --git a/jni/jni_hmac.c b/jni/jni_hmac.c index 923936c..edc66bf 100644 --- a/jni/jni_hmac.c +++ b/jni/jni_hmac.c @@ -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) diff --git a/src/main/java/com/wolfssl/provider/jce/WolfCryptMac.java b/src/main/java/com/wolfssl/provider/jce/WolfCryptMac.java index 3c7eac1..98fff82 100644 --- a/src/main/java/com/wolfssl/provider/jce/WolfCryptMac.java +++ b/src/main/java/com/wolfssl/provider/jce/WolfCryptMac.java @@ -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 */ diff --git a/src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java b/src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java index 376d152..439e17a 100644 --- a/src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java +++ b/src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java @@ -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"); diff --git a/src/main/java/com/wolfssl/wolfcrypt/Hmac.java b/src/main/java/com/wolfssl/wolfcrypt/Hmac.java index 2986f91..e5b2abf 100644 --- a/src/main/java/com/wolfssl/wolfcrypt/Hmac.java +++ b/src/main/java/com/wolfssl/wolfcrypt/Hmac.java @@ -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 { } } } - diff --git a/src/test/java/com/wolfssl/provider/jce/test/WolfCryptMacTest.java b/src/test/java/com/wolfssl/provider/jce/test/WolfCryptMacTest.java index 151c5d7..65eb5c5 100644 --- a/src/test/java/com/wolfssl/provider/jce/test/WolfCryptMacTest.java +++ b/src/test/java/com/wolfssl/provider/jce/test/WolfCryptMacTest.java @@ -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); }