mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Fix AES-CMAC for incomplete blocks
This commit is contained in:
parent
d29f7b27a7
commit
10e62b5ee1
2 changed files with 72 additions and 14 deletions
|
@ -344,11 +344,12 @@ namespace LibHac
|
|||
return t;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/29163493/aes-cmac-calculation-c-sharp
|
||||
public static void CalculateAesCmac(byte[] key, byte[] src, int srcIndex, byte[] dest, int destIndex, int length)
|
||||
{
|
||||
var l = new byte[16];
|
||||
EncryptCbc(key, new byte[16], new byte[16], l, 0x10);
|
||||
byte[] paddedMessage = src;
|
||||
int paddedLength = length;
|
||||
|
||||
byte[] firstSubkey = Rol(l);
|
||||
if ((l[0] & 0x80) == 0x80)
|
||||
|
@ -358,28 +359,26 @@ namespace LibHac
|
|||
if ((firstSubkey[0] & 0x80) == 0x80)
|
||||
secondSubkey[15] ^= 0x87;
|
||||
|
||||
int paddingBytes = 16 - length % 16;
|
||||
var srcPadded = new byte[length + paddingBytes];
|
||||
|
||||
Array.Copy(src, srcIndex, srcPadded, 0, length);
|
||||
|
||||
if (paddingBytes > 0)
|
||||
if (length != 0 && length % 16 == 0)
|
||||
{
|
||||
srcPadded[length] = 0x80;
|
||||
|
||||
for (int j = 0; j < firstSubkey.Length; j++)
|
||||
srcPadded[length - 16 + j] ^= firstSubkey[j];
|
||||
src[length - 16 + j] ^= firstSubkey[j];
|
||||
}
|
||||
else
|
||||
{
|
||||
paddedLength += 16 - length % 16;
|
||||
paddedMessage = new byte[paddedLength];
|
||||
paddedMessage[length] = 0x80;
|
||||
Array.Copy(src, srcIndex, paddedMessage, 0, length);
|
||||
|
||||
for (int j = 0; j < secondSubkey.Length; j++)
|
||||
srcPadded[length - 16 + j] ^= secondSubkey[j];
|
||||
paddedMessage[paddedLength - 16 + j] ^= secondSubkey[j];
|
||||
}
|
||||
|
||||
var encResult = new byte[length];
|
||||
EncryptCbc(key, new byte[16], srcPadded, encResult, length);
|
||||
var encResult = new byte[paddedMessage.Length];
|
||||
EncryptCbc(key, new byte[16], paddedMessage, encResult, paddedLength);
|
||||
|
||||
Array.Copy(encResult, length - 0x10, dest, destIndex, 0x10);
|
||||
Array.Copy(encResult, paddedLength - 0x10, dest, destIndex, 0x10);
|
||||
}
|
||||
|
||||
private static byte[] Rol(byte[] b)
|
||||
|
|
59
tests/LibHac.Tests/AesCmac.cs
Normal file
59
tests/LibHac.Tests/AesCmac.cs
Normal file
|
@ -0,0 +1,59 @@
|
|||
using Xunit;
|
||||
|
||||
namespace LibHac.Tests
|
||||
{
|
||||
public class AesCmac
|
||||
{
|
||||
private static readonly byte[] CmacKey = "2b7e151628aed2a6abf7158809cf4f3c".ToBytes();
|
||||
|
||||
private static readonly TestData[] TestVectors =
|
||||
{
|
||||
new TestData
|
||||
{
|
||||
Key = CmacKey,
|
||||
Message = "".ToBytes(),
|
||||
Expected = "bb1d6929e95937287fa37d129b756746".ToBytes()
|
||||
},
|
||||
new TestData
|
||||
{
|
||||
Key = CmacKey,
|
||||
Message = "6bc1bee22e409f96e93d7e117393172a".ToBytes(),
|
||||
Expected = "070a16b46b4d4144f79bdd9dd04a287c".ToBytes()
|
||||
},
|
||||
new TestData
|
||||
{
|
||||
Key = CmacKey,
|
||||
Message = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411".ToBytes(),
|
||||
Expected = "dfa66747de9ae63030ca32611497c827".ToBytes()
|
||||
},
|
||||
new TestData
|
||||
{
|
||||
Key = CmacKey,
|
||||
Message = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710".ToBytes(),
|
||||
Expected = "51f0bebf7e3b9d92fc49741779363cfe".ToBytes()
|
||||
}
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[InlineData(0)]
|
||||
[InlineData(1)]
|
||||
[InlineData(2)]
|
||||
[InlineData(3)]
|
||||
public static void Encrypt(int index)
|
||||
{
|
||||
TestData data = TestVectors[index];
|
||||
var actual = new byte[0x10];
|
||||
|
||||
Crypto.CalculateAesCmac(data.Key, data.Message, 0, actual, 0, data.Message.Length);
|
||||
|
||||
Assert.Equal(data.Expected, actual);
|
||||
}
|
||||
|
||||
private struct TestData
|
||||
{
|
||||
public byte[] Key;
|
||||
public byte[] Message;
|
||||
public byte[] Expected;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue