Skip to content

Commit 51adbe5

Browse files
committed
Merge branch 'main' of gitlab.cryptoworkshop.com:root/bc-java
2 parents 7961514 + 61dd2bb commit 51adbe5

File tree

2 files changed

+63
-49
lines changed

2 files changed

+63
-49
lines changed

core/src/main/java/org/bouncycastle/crypto/engines/ElephantEngine.java

+49-40
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ private enum State
6565
private byte[] current_mask;
6666
private byte[] next_mask;
6767
private final byte[] buffer;
68+
private final byte[] previous_outputMessage;
6869
private State m_state = State.Uninitialized;
6970
private final ByteArrayOutputStream aadData = new ByteArrayOutputStream();
7071
private int inputOff;
@@ -135,6 +136,7 @@ public ElephantEngine(ElephantParameters parameters)
135136
current_mask = new byte[BLOCK_SIZE];
136137
next_mask = new byte[BLOCK_SIZE];
137138
buffer = new byte[BLOCK_SIZE];
139+
previous_outputMessage = new byte[BLOCK_SIZE];
138140
initialised = false;
139141
reset(false);
140142
}
@@ -285,35 +287,6 @@ private void xor_block(byte[] state, byte[] block, int bOff, int size)
285287
}
286288
}
287289

288-
// Return the ith ciphertext block.
289-
// clen is the length of the ciphertext in bytes
290-
private void get_c_block(byte[] output, byte[] c, int cOff, int clen, int i)
291-
{
292-
int block_offset = i * BLOCK_SIZE;
293-
// If clen is divisible by BLOCK_SIZE, add an additional padding block
294-
if (block_offset == clen)
295-
{
296-
Arrays.fill(output, 0, BLOCK_SIZE, (byte)0);
297-
output[0] = 0x01;
298-
return;
299-
}
300-
int r_clen = clen - block_offset;
301-
// Fill with ciphertext if available
302-
if (BLOCK_SIZE <= r_clen)
303-
{ // enough ciphertext
304-
System.arraycopy(c, cOff + block_offset, output, 0, BLOCK_SIZE);
305-
}
306-
else
307-
{ // not enough ciphertext, need to pad
308-
if (r_clen > 0) // c might be nullptr
309-
{
310-
System.arraycopy(c, cOff + block_offset, output, 0, r_clen);
311-
Arrays.fill(output, r_clen, BLOCK_SIZE, (byte)0);
312-
output[r_clen] = 0x01;
313-
}
314-
}
315-
}
316-
317290
@Override
318291
public void init(boolean forEncryption, CipherParameters params)
319292
throws IllegalArgumentException
@@ -400,11 +373,11 @@ public int processBytes(byte[] input, int inOff, int len, byte[] output, int out
400373
byte[] tempInput = new byte[Math.max(nblocks_c, 1) * BLOCK_SIZE];
401374
System.arraycopy(inputMessage, 0, tempInput, 0, inputOff);
402375
System.arraycopy(input, inOff, tempInput, inputOff, Math.min(len, tempInput.length));
403-
int rv = processBytes(tempInput, output, outOff, nb_it, nblocks_m, nblocks_c, mlen, nblocks_ad);
376+
int rv = processBytes(tempInput, output, outOff, nb_it, nblocks_m, nblocks_c, mlen, nblocks_ad, false);
404377
int copyLen = rv - inputOff;
405378
inputOff = inputOff + len - rv;
406379
System.arraycopy(input, inOff + copyLen, inputMessage, 0, inputOff);
407-
nb_its += nblocks_c + 1;
380+
408381
messageLen += rv;
409382
return rv;
410383
}
@@ -436,7 +409,7 @@ public int doFinal(byte[] output, int outOff)
436409
int nblocks_m = (mlen % BLOCK_SIZE) != 0 ? nblocks_c : nblocks_c - 1;
437410
int nblocks_ad = 1 + (CRYPTO_NPUBBYTES + adlen) / BLOCK_SIZE;
438411
int nb_it = Math.max(nblocks_c + 1, nblocks_ad - 1);
439-
outOff += processBytes(inputMessage, output, outOff, nb_it, nblocks_m, nblocks_c, mlen, nblocks_ad);
412+
outOff += processBytes(inputMessage, output, outOff, nb_it, nblocks_m, nblocks_c, mlen, nblocks_ad, true);
440413
tag = new byte[CRYPTO_ABYTES];
441414
xor_block(tag_buffer, expanded_key, 0, BLOCK_SIZE);
442415
permutation(tag_buffer);
@@ -531,6 +504,7 @@ private void reset(boolean clearMac)
531504
}
532505
aadData.reset();
533506
Arrays.fill(tag_buffer, (byte)0);
507+
Arrays.fill(previous_outputMessage, (byte)0);
534508
inputOff = 0;
535509
nb_its = 0;
536510
adOff = -1;
@@ -639,12 +613,18 @@ private void processAADBytes(byte[] output)
639613
}
640614

641615
private int processBytes(byte[] m, byte[] output, int outOff, int nb_it, int nblocks_m, int nblocks_c, int mlen,
642-
int nblocks_ad)
616+
int nblocks_ad, boolean isDofinal)
643617
{
644618
int rv = 0;
645-
int original_outOff = outOff;
646-
for (int i = nb_its; i < nb_it; ++i)
619+
byte[] outputMessage = new byte[BLOCK_SIZE];
620+
int i;
621+
for (i = nb_its; i < nb_it; ++i)
647622
{
623+
int r_size = (i == nblocks_m - 1) ? mlen - i * BLOCK_SIZE : BLOCK_SIZE;
624+
if (!isDofinal && (r_size % BLOCK_SIZE != 0 || mlen <= i * BLOCK_SIZE))
625+
{
626+
break;
627+
}
648628
// Compute mask for the next message
649629
lfsr_step(next_mask, current_mask);
650630
if (i < nblocks_m)
@@ -657,23 +637,50 @@ private int processBytes(byte[] m, byte[] output, int outOff, int nb_it, int nbl
657637
permutation(buffer);
658638
xor_block(buffer, current_mask, 0, BLOCK_SIZE);
659639
xor_block(buffer, next_mask, 0, BLOCK_SIZE);
660-
int r_size = (i == nblocks_m - 1) ? mlen - i * BLOCK_SIZE : BLOCK_SIZE;
640+
661641
xor_block(buffer, m, rv, r_size);
662642
System.arraycopy(buffer, 0, output, outOff, r_size);
643+
if (forEncryption)
644+
{
645+
System.arraycopy(buffer, 0, outputMessage, 0, r_size);
646+
}
647+
else
648+
{
649+
System.arraycopy(m, rv, outputMessage, 0, r_size);
650+
}
651+
663652
outOff += r_size;
664653
rv += r_size;
665654
}
666655
if (i > 0 && i <= nblocks_c)
667656
{
668-
// Compute tag for ciphertext block
669-
if (forEncryption)
657+
//get_c_block: Compute tag for ciphertext block
658+
int block_offset = (i - 1) * BLOCK_SIZE;
659+
// If clen is divisible by BLOCK_SIZE, add an additional padding block
660+
if (block_offset == mlen)
670661
{
671-
get_c_block(buffer, output, original_outOff, mlen, i - 1);
662+
Arrays.fill(buffer, 0, BLOCK_SIZE, (byte)0);
663+
buffer[0] = 0x01;
672664
}
673665
else
674666
{
675-
get_c_block(buffer, m, 0, mlen, i - 1);
667+
int r_clen = mlen - block_offset;
668+
// Fill with ciphertext if available
669+
if (BLOCK_SIZE <= r_clen)
670+
{ // enough ciphertext
671+
System.arraycopy(previous_outputMessage, 0, buffer, 0, BLOCK_SIZE);
672+
}
673+
else
674+
{ // not enough ciphertext, need to pad
675+
if (r_clen > 0) // c might be nullptr
676+
{
677+
System.arraycopy(previous_outputMessage, 0, buffer, 0, r_clen);
678+
Arrays.fill(buffer, r_clen, BLOCK_SIZE, (byte)0);
679+
buffer[r_clen] = 0x01;
680+
}
681+
}
676682
}
683+
677684
xor_block(buffer, previous_mask, 0, BLOCK_SIZE);
678685
xor_block(buffer, next_mask, 0, BLOCK_SIZE);
679686
permutation(buffer);
@@ -696,7 +703,9 @@ private int processBytes(byte[] m, byte[] output, int outOff, int nb_it, int nbl
696703
previous_mask = current_mask;
697704
current_mask = next_mask;
698705
next_mask = temp;
706+
System.arraycopy(outputMessage, 0, previous_outputMessage, 0, BLOCK_SIZE);
699707
}
708+
nb_its = i;
700709
return rv;
701710
}
702711
}

core/src/test/java/org/bouncycastle/crypto/test/ElephantTest.java

+14-9
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ private void testExceptions(AEADCipher aeadBlockCipher, int keysize, int ivsize,
379379
//expected;
380380
}
381381

382-
byte[] m7 = new byte[blocksize * 2];
382+
byte[] m7 = new byte[blocksize * 3];
383383
for (int i = 0; i < m7.length; ++i)
384384
{
385385
m7[i] = (byte)rand.nextInt();
@@ -397,16 +397,21 @@ private void testExceptions(AEADCipher aeadBlockCipher, int keysize, int ivsize,
397397
offset = aeadBlockCipher.processBytes(m7, 0, blocksize, c8, 0);
398398
offset += aeadBlockCipher.processBytes(m7, blocksize, m7.length - blocksize, c8, offset);
399399
aeadBlockCipher.doFinal(c8, offset);
400-
aeadBlockCipher.init(true, params);
401-
int split = rand.nextInt(blocksize * 2);
402-
aeadBlockCipher.processAADBytes(aad2, 0, aad2.length);
403-
offset = aeadBlockCipher.processBytes(m7, 0, split, c9, 0);
404-
offset += aeadBlockCipher.processBytes(m7, split, m7.length - split, c9, offset);
405-
aeadBlockCipher.doFinal(c9, offset);
406-
if (!areEqual(c7, c8) || !areEqual(c7, c9))
400+
401+
// random split for several times
402+
for (int split = 0; split < blocksize * 3; ++split)
407403
{
408-
fail(aeadBlockCipher.getAlgorithmName() + ": Splitting input of plaintext should output the same ciphertext");
404+
aeadBlockCipher.init(true, params);
405+
aeadBlockCipher.processAADBytes(aad2, 0, aad2.length);
406+
offset = aeadBlockCipher.processBytes(m7, 0, split, c9, 0);
407+
offset += aeadBlockCipher.processBytes(m7, split, m7.length - split, c9, offset);
408+
aeadBlockCipher.doFinal(c9, offset);
409+
if (!areEqual(c7, c8) || !areEqual(c7, c9))
410+
{
411+
fail(aeadBlockCipher.getAlgorithmName() + ": Splitting input of plaintext should output the same ciphertext");
412+
}
409413
}
414+
410415
// System.out.println(aeadBlockCipher.getAlgorithmName() + " test Exceptions pass");
411416
}
412417

0 commit comments

Comments
 (0)