Skip to content

Commit 42fe75d

Browse files
committed
JCE: add Mac AESGMAC / AES-GMAC support
1 parent f665b74 commit 42fe75d

File tree

6 files changed

+280
-13
lines changed

6 files changed

+280
-13
lines changed

README_JCE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ The JCE provider currently supports the following algorithms:
116116

117117
Mac Class
118118
AESCMAC (aliased also as: AES-CMAC)
119+
AESGMAC (aliased also as: AES-GMAC)
119120
HmacMD5
120121
HmacSHA1
121122
HmacSHA224

jni/jni_aesgcm.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,10 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_AesGcm_wc_1AesGcmEncrypt
275275

276276
#else
277277
(void)this;
278-
(void)input;
279-
(void)iv;
280-
(void)authTag;
281-
(void)authIn;
278+
(void)inputArr;
279+
(void)ivArr;
280+
(void)authTagArr;
281+
(void)authInArr;
282282
throwNotCompiledInException(env);
283283
return NULL;
284284
#endif
@@ -398,10 +398,10 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_AesGcm_wc_1AesGcmDecrypt
398398

399399
#else
400400
(void)this;
401-
(void)input;
402-
(void)iv;
403-
(void)authTag;
404-
(void)authIn;
401+
(void)inputArr;
402+
(void)ivArr;
403+
(void)authTagArr;
404+
(void)authInArr;
405405
throwNotCompiledInException(env);
406406
return NULL;
407407
#endif

src/main/java/com/wolfssl/provider/jce/WolfCryptMac.java

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import java.security.InvalidAlgorithmParameterException;
2929
import java.security.NoSuchAlgorithmException;
3030
import javax.crypto.SecretKey;
31+
import javax.crypto.spec.GCMParameterSpec;
32+
import java.io.ByteArrayOutputStream;
3133

3234
import com.wolfssl.wolfcrypt.Md5;
3335
import com.wolfssl.wolfcrypt.Sha;
@@ -38,6 +40,7 @@
3840
import com.wolfssl.wolfcrypt.Sha3;
3941
import com.wolfssl.wolfcrypt.Hmac;
4042
import com.wolfssl.wolfcrypt.AesCmac;
43+
import com.wolfssl.wolfcrypt.AesGmac;
4144
import com.wolfssl.wolfcrypt.Aes;
4245

4346
/**
@@ -56,15 +59,22 @@ enum MacType {
5659
WC_HMAC_SHA3_256,
5760
WC_HMAC_SHA3_384,
5861
WC_HMAC_SHA3_512,
59-
WC_AES_CMAC
62+
WC_AES_CMAC,
63+
WC_AES_GMAC
6064
}
6165

6266
private Hmac hmac = null;
6367
private AesCmac aesCmac = null;
68+
private AesGmac aesGmac = null;
6469
private int nativeHmacType = 0;
6570
private int digestSize = 0;
6671
private MacType macType;
6772

73+
/* GMAC-specific fields */
74+
private byte[] gmacIv = null;
75+
private int gmacTagLen = 16; /* default tag length */
76+
private ByteArrayOutputStream gmacAuthData = null;
77+
6878
/* for debug logging */
6979
private String algString;
7080

@@ -139,6 +149,12 @@ private WolfCryptMac(MacType type)
139149
this.digestSize = Aes.BLOCK_SIZE;
140150
break;
141151

152+
case WC_AES_GMAC:
153+
aesGmac = new AesGmac();
154+
this.digestSize = Aes.BLOCK_SIZE;
155+
gmacAuthData = new ByteArrayOutputStream();
156+
break;
157+
142158
default:
143159
throw new NoSuchAlgorithmException(
144160
"Unsupported MAC type");
@@ -156,6 +172,12 @@ protected byte[] engineDoFinal() {
156172

157173
if (macType == MacType.WC_AES_CMAC) {
158174
out = this.aesCmac.doFinal();
175+
} else if (macType == MacType.WC_AES_GMAC) {
176+
/* Compute GMAC using accumulated auth data */
177+
byte[] authData = gmacAuthData.toByteArray();
178+
out = this.aesGmac.update(gmacIv, authData, gmacTagLen);
179+
/* Reset for next operation */
180+
gmacAuthData.reset();
159181
} else {
160182
out = this.hmac.doFinal();
161183
}
@@ -192,6 +214,19 @@ protected void engineInit(Key key, AlgorithmParameterSpec params)
192214
try {
193215
if (macType == MacType.WC_AES_CMAC) {
194216
this.aesCmac.setKey(encodedKey);
217+
} else if (macType == MacType.WC_AES_GMAC) {
218+
/* GMAC requires GCMParameterSpec with IV */
219+
if (params == null || !(params instanceof GCMParameterSpec)) {
220+
throw new InvalidAlgorithmParameterException(
221+
"AES-GMAC requires GCMParameterSpec with IV");
222+
}
223+
GCMParameterSpec gcmSpec = (GCMParameterSpec) params;
224+
this.gmacIv = gcmSpec.getIV();
225+
/* Convert bits to bytes */
226+
this.gmacTagLen = gcmSpec.getTLen() / 8;
227+
this.aesGmac.setKey(encodedKey);
228+
/* Reset auth data accumulator */
229+
gmacAuthData.reset();
195230
} else {
196231
this.hmac.setKey(nativeHmacType, encodedKey);
197232
}
@@ -206,6 +241,11 @@ protected void engineInit(Key key, AlgorithmParameterSpec params)
206241
protected void engineReset() {
207242
if (macType == MacType.WC_AES_CMAC) {
208243
this.aesCmac.reset();
244+
} else if (macType == MacType.WC_AES_GMAC) {
245+
/* Reset GMAC auth data accumulator */
246+
if (gmacAuthData != null) {
247+
gmacAuthData.reset();
248+
}
209249
} else {
210250
this.hmac.reset();
211251
}
@@ -217,6 +257,9 @@ protected void engineReset() {
217257
protected void engineUpdate(byte input) {
218258
if (macType == MacType.WC_AES_CMAC) {
219259
this.aesCmac.update(input);
260+
} else if (macType == MacType.WC_AES_GMAC) {
261+
/* Accumulate auth data for GMAC */
262+
gmacAuthData.write(input);
220263
} else {
221264
this.hmac.update(input);
222265
}
@@ -228,6 +271,9 @@ protected void engineUpdate(byte input) {
228271
protected void engineUpdate(byte[] input, int offset, int len) {
229272
if (macType == MacType.WC_AES_CMAC) {
230273
this.aesCmac.update(input, offset, len);
274+
} else if (macType == MacType.WC_AES_GMAC) {
275+
/* Accumulate auth data for GMAC */
276+
gmacAuthData.write(input, offset, len);
231277
} else {
232278
this.hmac.update(input, offset, len);
233279
}
@@ -259,6 +305,8 @@ private String typeToString(MacType type) {
259305
return "SHA3-512";
260306
case WC_AES_CMAC:
261307
return "AES-CMAC";
308+
case WC_AES_GMAC:
309+
return "AES-GMAC";
262310
default:
263311
return "None";
264312
}
@@ -277,6 +325,8 @@ protected void finalize() throws Throwable {
277325
this.hmac.releaseNativeStruct();
278326
if (this.aesCmac != null)
279327
this.aesCmac.releaseNativeStruct();
328+
if (this.aesGmac != null)
329+
this.aesGmac.releaseNativeStruct();
280330
} finally {
281331
super.finalize();
282332
}
@@ -446,4 +496,19 @@ public wcAesCmac() throws NoSuchAlgorithmException {
446496
super(MacType.WC_AES_CMAC);
447497
}
448498
}
499+
500+
/**
501+
* wolfJCE AES-GMAC class
502+
*/
503+
public static final class wcAesGmac extends WolfCryptMac {
504+
/**
505+
* Create new wcAesGmac object
506+
*
507+
* @throws NoSuchAlgorithmException if AES-GMAC is not available at
508+
* native wolfCrypt level.
509+
*/
510+
public wcAesGmac() throws NoSuchAlgorithmException {
511+
super(MacType.WC_AES_GMAC);
512+
}
513+
}
449514
}

src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,12 @@ private void registerServices() {
215215
put("Alg.Alias.Mac.AES-CMAC", "AESCMAC");
216216
}
217217

218+
if (FeatureDetect.AesGmacEnabled()) {
219+
put("Mac.AESGMAC",
220+
"com.wolfssl.provider.jce.WolfCryptMac$wcAesGmac");
221+
put("Alg.Alias.Mac.AES-GMAC", "AESGMAC");
222+
}
223+
218224
/* Cipher */
219225
if (FeatureDetect.AesCbcEnabled()) {
220226
put("Cipher.AES/CBC/NoPadding",

src/test/java/com/wolfssl/provider/jce/test/WolfCryptCipherTest.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2269,6 +2269,11 @@ public void testAesGcmNoPaddingInterop() throws NoSuchAlgorithmException,
22692269
@Test
22702270
public void testAesGcmGetOutputSize() throws Exception {
22712271

2272+
if (!enabledJCEAlgos.contains("AES/GCM/NoPadding")) {
2273+
/* skip if AES-GCM is not enabled */
2274+
return;
2275+
}
2276+
22722277
final int TAG_LENGTH_BYTES = 16; /* Default tag length */
22732278
final int KEY_LENGTH_BYTES = 16; /* 128-bit AES key */
22742279
final int IV_LENGTH_BYTES = 12;
@@ -2444,7 +2449,8 @@ public void testAesEcbNoPaddingWithUpdate()
24442449
/* Combine outputs */
24452450
byte[] fullOutput = new byte[output1.length + output2.length];
24462451
System.arraycopy(output1, 0, fullOutput, 0, output1.length);
2447-
System.arraycopy(output2, 0, fullOutput, output1.length, output2.length);
2452+
System.arraycopy(output2, 0, fullOutput, output1.length,
2453+
output2.length);
24482454

24492455
assertArrayEquals(expected, fullOutput);
24502456

@@ -3293,7 +3299,8 @@ public void testDESedeCbcNoPaddingThreaded() throws InterruptedException {
32933299
int numThreads = 50;
32943300
ExecutorService service = Executors.newFixedThreadPool(numThreads);
32953301
final CountDownLatch latch = new CountDownLatch(numThreads);
3296-
final LinkedBlockingQueue<Integer> results = new LinkedBlockingQueue<>();
3302+
final LinkedBlockingQueue<Integer> results =
3303+
new LinkedBlockingQueue<>();
32973304
final byte[] rand2kBuf = new byte[2048];
32983305

32993306
final byte key[] = new byte[] {

0 commit comments

Comments
 (0)