Skip to content

Commit 817181b

Browse files
ligefeiBouncycastledghgit
authored andcommitted
1847 elephant
1 parent 6543f9a commit 817181b

File tree

3 files changed

+176
-81
lines changed

3 files changed

+176
-81
lines changed

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

Lines changed: 46 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ private enum State
6969
private final ByteArrayOutputStream aadData = new ByteArrayOutputStream();
7070
private int inputOff;
7171
private byte[] inputMessage;
72-
private final byte[] previous_outputMessage;
73-
private final byte[] outputMessage;
72+
private int messageLen;
7473

7574
private final byte[] sBoxLayer = {
7675
(byte)0xee, (byte)0xed, (byte)0xeb, (byte)0xe0, (byte)0xe2, (byte)0xe1, (byte)0xe4, (byte)0xef, (byte)0xe7, (byte)0xea, (byte)0xe8, (byte)0xe5, (byte)0xe9, (byte)0xec, (byte)0xe3, (byte)0xe6,
@@ -100,6 +99,7 @@ private enum State
10099

101100
public ElephantEngine(ElephantParameters parameters)
102101
{
102+
103103
switch (parameters)
104104
{
105105
case elephant160:
@@ -117,14 +117,14 @@ public ElephantEngine(ElephantParameters parameters)
117117
nSBox = 22;
118118
nRounds = 90;
119119
lfsrIV = 0x45;
120-
CRYPTO_ABYTES = 8;
121120
algorithmName = "Elephant 176 AEAD";
121+
CRYPTO_ABYTES = 8;
122122
break;
123123
case elephant200:
124124
BLOCK_SIZE = 25;
125125
nRounds = 18;
126-
CRYPTO_ABYTES = 16;
127126
algorithmName = "Elephant 200 AEAD";
127+
CRYPTO_ABYTES = 16;
128128
break;
129129
default:
130130
throw new IllegalArgumentException("Invalid parameter settings for Elephant");
@@ -135,8 +135,6 @@ public ElephantEngine(ElephantParameters parameters)
135135
current_mask = new byte[BLOCK_SIZE];
136136
next_mask = new byte[BLOCK_SIZE];
137137
buffer = new byte[BLOCK_SIZE];
138-
previous_outputMessage = new byte[BLOCK_SIZE];
139-
outputMessage = new byte[BLOCK_SIZE];
140138
initialised = false;
141139
reset(false);
142140
}
@@ -303,16 +301,16 @@ private void get_c_block(byte[] output, byte[] c, int cOff, int clen, int i)
303301
// Fill with ciphertext if available
304302
if (BLOCK_SIZE <= r_clen)
305303
{ // enough ciphertext
306-
System.arraycopy(c, cOff, output, 0, BLOCK_SIZE);
304+
System.arraycopy(c, cOff + block_offset, output, 0, BLOCK_SIZE);
307305
}
308306
else
309307
{ // not enough ciphertext, need to pad
310308
if (r_clen > 0) // c might be nullptr
311309
{
312-
System.arraycopy(c, cOff, output, 0, r_clen);
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;
313313
}
314-
Arrays.fill(output, r_clen, BLOCK_SIZE, (byte)0);
315-
output[r_clen] = 0x01;
316314
}
317315
}
318316

@@ -390,32 +388,25 @@ public int processBytes(byte[] input, int inOff, int len, byte[] output, int out
390388
{
391389
throw new DataLengthException("input buffer too short");
392390
}
393-
byte[] ad = aadData.toByteArray();
394-
395391

396392
if (inputOff + len - (forEncryption ? 0 : CRYPTO_ABYTES) >= BLOCK_SIZE)
397393
{
398-
switch (m_state)
399-
{
400-
case EncInit:
401-
case DecInit:
402-
processAADBytes(tag_buffer);
403-
break;
404-
}
405394
int mlen = inputOff + len - (forEncryption ? 0 : CRYPTO_ABYTES);
406-
int adlen = ad.length;
407-
int nblocks_c = mlen / BLOCK_SIZE;
408-
int nblocks_m = 1 + ((mlen % BLOCK_SIZE) != 0 ? nblocks_c : nblocks_c - 1);
395+
int adlen = processAADBytes();
396+
int nblocks_c = 1 + mlen / BLOCK_SIZE;
397+
int nblocks_m = ((mlen % BLOCK_SIZE) != 0 ? nblocks_c : nblocks_c - 1);
409398
int nblocks_ad = 1 + (CRYPTO_NPUBBYTES + adlen) / BLOCK_SIZE;
399+
int nb_it = Math.max(nblocks_c + 1, nblocks_ad - 1);
410400
byte[] tempInput = new byte[Math.max(nblocks_c, 1) * BLOCK_SIZE];
411401
System.arraycopy(inputMessage, 0, tempInput, 0, inputOff);
412-
int templen = tempInput.length - inputOff;
413-
System.arraycopy(input, inOff, tempInput, inputOff, tempInput.length - inputOff);
414-
processBytes(tempInput, output, outOff, nblocks_c, nblocks_m, nblocks_c, mlen, nblocks_ad);
415-
inputOff = len - templen;
416-
System.arraycopy(input, inOff + templen, inputMessage, 0, inputOff);
417-
nb_its += nblocks_c;
418-
return nblocks_c * BLOCK_SIZE;
402+
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);
404+
int copyLen = rv - inputOff;
405+
inputOff = inputOff + len - rv;
406+
System.arraycopy(input, inOff + copyLen, inputMessage, 0, inputOff);
407+
nb_its += nblocks_c + 1;
408+
messageLen += rv;
409+
return rv;
419410
}
420411
else
421412
{
@@ -439,16 +430,8 @@ public int doFinal(byte[] output, int outOff)
439430
{
440431
throw new OutputLengthException("output buffer is too short");
441432
}
442-
byte[] ad = aadData.toByteArray();
443-
switch (m_state)
444-
{
445-
case EncInit:
446-
case DecInit:
447-
processAADBytes(tag_buffer);
448-
break;
449-
}
450-
int mlen = len + nb_its * BLOCK_SIZE - (forEncryption ? 0 : CRYPTO_ABYTES);
451-
int adlen = ad.length;
433+
int mlen = len + messageLen - (forEncryption ? 0 : CRYPTO_ABYTES);
434+
int adlen = processAADBytes();
452435
int nblocks_c = 1 + mlen / BLOCK_SIZE;
453436
int nblocks_m = (mlen % BLOCK_SIZE) != 0 ? nblocks_c : nblocks_c - 1;
454437
int nblocks_ad = 1 + (CRYPTO_NPUBBYTES + adlen) / BLOCK_SIZE;
@@ -527,6 +510,19 @@ public void reset()
527510
reset(true);
528511
}
529512

513+
private int processAADBytes()
514+
{
515+
byte[] ad = aadData.toByteArray();
516+
switch (m_state)
517+
{
518+
case EncInit:
519+
case DecInit:
520+
processAADBytes(tag_buffer);
521+
break;
522+
}
523+
return ad.length;
524+
}
525+
530526
private void reset(boolean clearMac)
531527
{
532528
if (clearMac)
@@ -538,6 +534,7 @@ private void reset(boolean clearMac)
538534
inputOff = 0;
539535
nb_its = 0;
540536
adOff = -1;
537+
messageLen = 0;
541538
}
542539

543540
public int getKeyBytesSize()
@@ -645,6 +642,7 @@ private int processBytes(byte[] m, byte[] output, int outOff, int nb_it, int nbl
645642
int nblocks_ad)
646643
{
647644
int rv = 0;
645+
int original_outOff = outOff;
648646
for (int i = nb_its; i < nb_it; ++i)
649647
{
650648
// Compute mask for the next message
@@ -660,22 +658,22 @@ private int processBytes(byte[] m, byte[] output, int outOff, int nb_it, int nbl
660658
xor_block(buffer, current_mask, 0, BLOCK_SIZE);
661659
xor_block(buffer, next_mask, 0, BLOCK_SIZE);
662660
int r_size = (i == nblocks_m - 1) ? mlen - i * BLOCK_SIZE : BLOCK_SIZE;
663-
xor_block(buffer, m, 0, r_size);
661+
xor_block(buffer, m, rv, r_size);
664662
System.arraycopy(buffer, 0, output, outOff, r_size);
663+
outOff += r_size;
664+
rv += r_size;
665+
}
666+
if (i > 0 && i <= nblocks_c)
667+
{
668+
// Compute tag for ciphertext block
665669
if (forEncryption)
666670
{
667-
System.arraycopy(buffer, 0, outputMessage, 0, r_size);
671+
get_c_block(buffer, output, original_outOff, mlen, i - 1);
668672
}
669673
else
670674
{
671-
System.arraycopy(m, 0, outputMessage, 0, r_size);
675+
get_c_block(buffer, m, 0, mlen, i - 1);
672676
}
673-
rv += r_size;
674-
}
675-
if (i > 0 && i <= nblocks_c)
676-
{
677-
// Compute tag for ciphertext block
678-
get_c_block(buffer, previous_outputMessage, 0, mlen, i - 1);
679677
xor_block(buffer, previous_mask, 0, BLOCK_SIZE);
680678
xor_block(buffer, next_mask, 0, BLOCK_SIZE);
681679
permutation(buffer);
@@ -698,7 +696,6 @@ private int processBytes(byte[] m, byte[] output, int outOff, int nb_it, int nbl
698696
previous_mask = current_mask;
699697
current_mask = next_mask;
700698
next_mask = temp;
701-
System.arraycopy(outputMessage, 0, previous_outputMessage, 0, BLOCK_SIZE);
702699
}
703700
return rv;
704701
}

0 commit comments

Comments
 (0)