Skip to content

Commit 92f2dd8

Browse files
committed
AESWrap: fix wrap/unwrap of 64-bit keys
1 parent fa156fa commit 92f2dd8

File tree

3 files changed

+70
-44
lines changed

3 files changed

+70
-44
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public AESWrapEngine()
1818
}
1919

2020
/**
21-
* Create an AESWrapEngine where the underlying cipher is set to decrypt for wrapping, encrypt for unwrapping.
21+
* Create an AESWrapEngine where the underlying cipher is (optionally) set to decrypt for wrapping, encrypt for unwrapping.
2222
*
2323
* @param useReverseDirection true if underlying cipher should be used in decryption mode, false otherwise.
2424
*/

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

Lines changed: 63 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public RFC3394WrapEngine(BlockCipher engine)
4848
public RFC3394WrapEngine(BlockCipher engine, boolean useReverseDirection)
4949
{
5050
this.engine = engine;
51-
this.wrapCipherMode = (useReverseDirection) ? false : true;
51+
this.wrapCipherMode = !useReverseDirection;
5252
}
5353

5454
public void init(
@@ -91,6 +91,10 @@ public byte[] wrap(
9191
{
9292
throw new IllegalStateException("not set for wrapping");
9393
}
94+
if (inLen < 8)
95+
{
96+
throw new DataLengthException("wrap data must be at least 8 bytes");
97+
}
9498

9599
int n = inLen / 8;
96100

@@ -99,34 +103,41 @@ public byte[] wrap(
99103
throw new DataLengthException("wrap data must be a multiple of 8 bytes");
100104
}
101105

102-
byte[] block = new byte[inLen + iv.length];
103-
byte[] buf = new byte[8 + iv.length];
106+
engine.init(wrapCipherMode, param);
104107

108+
byte[] block = new byte[inLen + iv.length];
105109
System.arraycopy(iv, 0, block, 0, iv.length);
106110
System.arraycopy(in, inOff, block, iv.length, inLen);
107111

108-
engine.init(wrapCipherMode, param);
109-
110-
for (int j = 0; j != 6; j++)
112+
if (n == 1)
111113
{
112-
for (int i = 1; i <= n; i++)
113-
{
114-
System.arraycopy(block, 0, buf, 0, iv.length);
115-
System.arraycopy(block, 8 * i, buf, iv.length, 8);
116-
engine.processBlock(buf, 0, buf, 0);
114+
engine.processBlock(block, 0, block, 0);
115+
}
116+
else
117+
{
118+
byte[] buf = new byte[8 + iv.length];
117119

118-
int t = n * j + i;
119-
for (int k = 1; t != 0; k++)
120+
for (int j = 0; j != 6; j++)
121+
{
122+
for (int i = 1; i <= n; i++)
120123
{
121-
byte v = (byte)t;
124+
System.arraycopy(block, 0, buf, 0, iv.length);
125+
System.arraycopy(block, 8 * i, buf, iv.length, 8);
126+
engine.processBlock(buf, 0, buf, 0);
122127

123-
buf[iv.length - k] ^= v;
128+
int t = n * j + i;
129+
for (int k = 1; t != 0; k++)
130+
{
131+
byte v = (byte)t;
124132

125-
t >>>= 8;
126-
}
133+
buf[iv.length - k] ^= v;
134+
135+
t >>>= 8;
136+
}
127137

128-
System.arraycopy(buf, 0, block, 0, 8);
129-
System.arraycopy(buf, 8, block, 8 * i, 8);
138+
System.arraycopy(buf, 0, block, 0, 8);
139+
System.arraycopy(buf, 8, block, 8 * i, 8);
140+
}
130141
}
131142
}
132143

@@ -143,7 +154,7 @@ public byte[] unwrap(
143154
{
144155
throw new IllegalStateException("not set for unwrapping");
145156
}
146-
if (inLen < iv.length)
157+
if (inLen < 16)
147158
{
148159
throw new InvalidCipherTextException("unwrap data too short");
149160
}
@@ -155,37 +166,46 @@ public byte[] unwrap(
155166
throw new InvalidCipherTextException("unwrap data must be a multiple of 8 bytes");
156167
}
157168

158-
byte[] block = new byte[inLen - iv.length];
159-
byte[] a = new byte[iv.length];
160-
byte[] buf = new byte[8 + iv.length];
161-
162-
System.arraycopy(in, inOff, a, 0, iv.length);
163-
System.arraycopy(in, inOff + iv.length, block, 0, inLen - iv.length);
164-
165169
engine.init(!wrapCipherMode, param);
166170

171+
byte[] block = new byte[inLen - iv.length];
172+
byte[] a = new byte[iv.length];
173+
byte[] buf = new byte[8 + iv.length];
174+
167175
n = n - 1;
168176

169-
for (int j = 5; j >= 0; j--)
177+
if (n == 1)
170178
{
171-
for (int i = n; i >= 1; i--)
172-
{
173-
System.arraycopy(a, 0, buf, 0, iv.length);
174-
System.arraycopy(block, 8 * (i - 1), buf, iv.length, 8);
179+
engine.processBlock(in, inOff, buf, 0);
180+
System.arraycopy(buf, 0, a, 0, iv.length);
181+
System.arraycopy(buf, iv.length, block, 0, 8);
182+
}
183+
else
184+
{
185+
System.arraycopy(in, inOff, a, 0, iv.length);
186+
System.arraycopy(in, inOff + iv.length, block, 0, inLen - iv.length);
175187

176-
int t = n * j + i;
177-
for (int k = 1; t != 0; k++)
188+
for (int j = 5; j >= 0; j--)
189+
{
190+
for (int i = n; i >= 1; i--)
178191
{
179-
byte v = (byte)t;
180-
181-
buf[iv.length - k] ^= v;
182-
183-
t >>>= 8;
192+
System.arraycopy(a, 0, buf, 0, iv.length);
193+
System.arraycopy(block, 8 * (i - 1), buf, iv.length, 8);
194+
195+
int t = n * j + i;
196+
for (int k = 1; t != 0; k++)
197+
{
198+
byte v = (byte)t;
199+
200+
buf[iv.length - k] ^= v;
201+
202+
t >>>= 8;
203+
}
204+
205+
engine.processBlock(buf, 0, buf, 0);
206+
System.arraycopy(buf, 0, a, 0, 8);
207+
System.arraycopy(buf, 8, block, 8 * (i - 1), 8);
184208
}
185-
186-
engine.processBlock(buf, 0, buf, 0);
187-
System.arraycopy(buf, 0, a, 0, 8);
188-
System.arraycopy(buf, 8, block, 8 * (i - 1), 8);
189209
}
190210
}
191211

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@ public void performTest()
181181
byte[] out7 = Hex.decode("cba01acbdb4c7c39fa59babb383c485f318837208731a81c735b5be6ba710375a1159e26a9b57228");
182182
wrapTest(7, kek7, in7, out7, true);
183183

184+
// Example of 64-bit input (which uses a simplified wrapping algorithm)
185+
byte[] kek8 = Hex.decode("574957151fc2afe0fa3dc7a9a7da6495");
186+
byte[] in8 = Hex.decode("0001020304050607");
187+
byte[] out8 = Hex.decode("6f0b501f1f2f59e3ae605aa679ce43a6");
188+
wrapTest(8, kek8, in8, out8);
189+
184190
Wrapper wrapper = new AESWrapEngine();
185191
KeyParameter key = new KeyParameter(new byte[16]);
186192
byte[] buf = new byte[16];

0 commit comments

Comments
 (0)