refactor(applet): AliroGcm.setKeyAndIv consolidates re-keying (M2C.2)
This commit is contained in:
@@ -144,22 +144,7 @@ final class AliroGcm {
|
||||
byte[] pt, short ptOff, short ptLen,
|
||||
byte[] out, short outOff) {
|
||||
|
||||
aesKey.setKey(key, keyOff);
|
||||
aesEcb.init(aesKey, Cipher.MODE_ENCRYPT);
|
||||
|
||||
// H = AES_K(0^128). Zero scratch[OFF_H..OFF_H+16) and encrypt in place.
|
||||
Util.arrayFillNonAtomic(scratch, OFF_H, BLOCK_LEN, (byte) 0);
|
||||
aesEcb.doFinal(scratch, OFF_H, BLOCK_LEN, scratch, OFF_H);
|
||||
// Build the 4-bit GHASH M-table from the fresh H. One-time cost per
|
||||
// encrypt (~700 JC bytecodes), amortized over the ~10 gfMul4Bit calls.
|
||||
buildMTable();
|
||||
|
||||
// J0 = IV || 0x00000001 (12B IV + 4B counter). 96-bit IV canonical case.
|
||||
Util.arrayCopyNonAtomic(iv, ivOff, scratch, OFF_J0, IV_LEN);
|
||||
scratch[(short) (OFF_J0 + 12)] = 0x00;
|
||||
scratch[(short) (OFF_J0 + 13)] = 0x00;
|
||||
scratch[(short) (OFF_J0 + 14)] = 0x00;
|
||||
scratch[(short) (OFF_J0 + 15)] = 0x01;
|
||||
setKeyAndIv(key, keyOff, iv, ivOff);
|
||||
|
||||
// cb = INC32(J0) — first counter block for the plaintext stream.
|
||||
Util.arrayCopyNonAtomic(scratch, OFF_J0, scratch, OFF_CB, BLOCK_LEN);
|
||||
@@ -305,23 +290,7 @@ final class AliroGcm {
|
||||
short ctLen = (short) (inLen - TAG_LEN);
|
||||
short tagOff = (short) (inOff + ctLen);
|
||||
|
||||
aesKey.setKey(key, keyOff);
|
||||
aesEcb.init(aesKey, Cipher.MODE_ENCRYPT);
|
||||
|
||||
// H = AES_K(0^128). Same as encrypt() -- GCM is one-direction at the
|
||||
// primitive level: encrypt and decrypt both run GCTR + GHASH and
|
||||
// differ only in whether GHASH consumes provided ciphertext or
|
||||
// freshly-emitted ciphertext, plus the tag compare/emit step.
|
||||
Util.arrayFillNonAtomic(scratch, OFF_H, BLOCK_LEN, (byte) 0);
|
||||
aesEcb.doFinal(scratch, OFF_H, BLOCK_LEN, scratch, OFF_H);
|
||||
buildMTable();
|
||||
|
||||
// J0 = IV || 0x00000001 (96-bit IV canonical case).
|
||||
Util.arrayCopyNonAtomic(iv, ivOff, scratch, OFF_J0, IV_LEN);
|
||||
scratch[(short) (OFF_J0 + 12)] = 0x00;
|
||||
scratch[(short) (OFF_J0 + 13)] = 0x00;
|
||||
scratch[(short) (OFF_J0 + 14)] = 0x00;
|
||||
scratch[(short) (OFF_J0 + 15)] = 0x01;
|
||||
setKeyAndIv(key, keyOff, iv, ivOff);
|
||||
|
||||
// GHASH over the PROVIDED ciphertext first (so tag verify doesn't
|
||||
// depend on a successful decrypt). AAD is empty.
|
||||
@@ -412,6 +381,35 @@ final class AliroGcm {
|
||||
return ctLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-(key, IV) GCM setup, shared by {@link #encrypt} and {@link #decrypt}:
|
||||
* loads the AES-256 key, derives H = AES_K(0^128), rebuilds the 4-bit
|
||||
* GHASH M-table, and lays down J0 = IV || 0x00000001 at OFF_J0. M2D.3's
|
||||
* stream-encrypt path calls {@link #encrypt} twice per Step-Up session
|
||||
* with a different (key, IV) each time; consolidating the rekey path
|
||||
* keeps that contract pinned to one method.
|
||||
*/
|
||||
private void setKeyAndIv(
|
||||
byte[] key, short keyOff,
|
||||
byte[] iv, short ivOff) {
|
||||
aesKey.setKey(key, keyOff);
|
||||
aesEcb.init(aesKey, Cipher.MODE_ENCRYPT);
|
||||
|
||||
// H = AES_K(0^128). Zero scratch[OFF_H..OFF_H+16) and encrypt in place.
|
||||
Util.arrayFillNonAtomic(scratch, OFF_H, BLOCK_LEN, (byte) 0);
|
||||
aesEcb.doFinal(scratch, OFF_H, BLOCK_LEN, scratch, OFF_H);
|
||||
// Build the 4-bit GHASH M-table from the fresh H. One-time cost per
|
||||
// encrypt (~700 JC bytecodes), amortized over the ~10 gfMul4Bit calls.
|
||||
buildMTable();
|
||||
|
||||
// J0 = IV || 0x00000001 (12B IV + 4B counter). 96-bit IV canonical case.
|
||||
Util.arrayCopyNonAtomic(iv, ivOff, scratch, OFF_J0, IV_LEN);
|
||||
scratch[(short) (OFF_J0 + 12)] = 0x00;
|
||||
scratch[(short) (OFF_J0 + 13)] = 0x00;
|
||||
scratch[(short) (OFF_J0 + 14)] = 0x00;
|
||||
scratch[(short) (OFF_J0 + 15)] = 0x01;
|
||||
}
|
||||
|
||||
/**
|
||||
* INC32 per NIST SP 800-38D §6.2: increments the last 4 bytes of the
|
||||
* 16-byte block, big-endian, modulo 2^32.
|
||||
|
||||
Reference in New Issue
Block a user