From 605ef991b309a87a2ec590625ba449081c806274 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Thu, 10 Mar 2016 13:44:13 +0700
Subject: Implement unique name_type restriction from RFC 6066
---
crypto/src/crypto/tls/NameType.cs | 5 +++++
crypto/src/crypto/tls/ServerNameList.cs | 27 +++++++++++++++++++++++++--
2 files changed, 30 insertions(+), 2 deletions(-)
(limited to 'crypto/src')
diff --git a/crypto/src/crypto/tls/NameType.cs b/crypto/src/crypto/tls/NameType.cs
index 25f6046fc..782164215 100644
--- a/crypto/src/crypto/tls/NameType.cs
+++ b/crypto/src/crypto/tls/NameType.cs
@@ -8,5 +8,10 @@ namespace Org.BouncyCastle.Crypto.Tls
* RFC 3546 3.1.
*/
public const byte host_name = 0;
+
+ public static bool IsValid(byte nameType)
+ {
+ return nameType == host_name;
+ }
}
}
diff --git a/crypto/src/crypto/tls/ServerNameList.cs b/crypto/src/crypto/tls/ServerNameList.cs
index 13da79bf6..5b5b90e58 100644
--- a/crypto/src/crypto/tls/ServerNameList.cs
+++ b/crypto/src/crypto/tls/ServerNameList.cs
@@ -15,8 +15,8 @@ namespace Org.BouncyCastle.Crypto.Tls
*/
public ServerNameList(IList serverNameList)
{
- if (serverNameList == null || serverNameList.Count < 1)
- throw new ArgumentException("must not be null or empty", "serverNameList");
+ if (serverNameList == null)
+ throw new ArgumentNullException("serverNameList");
this.mServerNameList = serverNameList;
}
@@ -40,8 +40,13 @@ namespace Org.BouncyCastle.Crypto.Tls
{
MemoryStream buf = new MemoryStream();
+ byte[] nameTypesSeen = TlsUtilities.EmptyBytes;
foreach (ServerName entry in ServerNames)
{
+ nameTypesSeen = CheckNameType(nameTypesSeen, entry.NameType);
+ if (nameTypesSeen == null)
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+
entry.Encode(buf);
}
@@ -68,14 +73,32 @@ namespace Org.BouncyCastle.Crypto.Tls
MemoryStream buf = new MemoryStream(data, false);
+ byte[] nameTypesSeen = TlsUtilities.EmptyBytes;
IList server_name_list = Platform.CreateArrayList();
while (buf.Position < buf.Length)
{
ServerName entry = ServerName.Parse(buf);
+
+ nameTypesSeen = CheckNameType(nameTypesSeen, entry.NameType);
+ if (nameTypesSeen == null)
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
server_name_list.Add(entry);
}
return new ServerNameList(server_name_list);
}
+
+ private static byte[] CheckNameType(byte[] nameTypesSeen, byte nameType)
+ {
+ /*
+ * RFC 6066 3. The ServerNameList MUST NOT contain more than one name of the same
+ * name_type.
+ */
+ if (!NameType.IsValid(nameType) || Arrays.Contains(nameTypesSeen, nameType))
+ return null;
+
+ return Arrays.Append(nameTypesSeen, nameType);
+ }
}
}
--
cgit 1.5.1
From efb5751fec2aad9cfa98922b11879f9e4efed59d Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Thu, 10 Mar 2016 14:05:15 +0700
Subject: Prefer high bits for powers-of-two
---
crypto/src/security/SecureRandom.cs | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
(limited to 'crypto/src')
diff --git a/crypto/src/security/SecureRandom.cs b/crypto/src/security/SecureRandom.cs
index cb831acc2..bd639a336 100644
--- a/crypto/src/security/SecureRandom.cs
+++ b/crypto/src/security/SecureRandom.cs
@@ -170,6 +170,7 @@ namespace Org.BouncyCastle.Security
public override int Next(int maxValue)
{
+
if (maxValue < 2)
{
if (maxValue < 0)
@@ -178,13 +179,16 @@ namespace Org.BouncyCastle.Security
return 0;
}
+ int bits;
+
// Test whether maxValue is a power of 2
if ((maxValue & (maxValue - 1)) == 0)
{
- return NextInt() & (maxValue - 1);
+ bits = NextInt() & int.MaxValue;
+ return (int)(((long)bits * maxValue) >> 31);
}
- int bits, result;
+ int result;
do
{
bits = NextInt() & int.MaxValue;
--
cgit 1.5.1
From 22467cd66eea50f418f6398910def1f3b84db404 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Fri, 25 Mar 2016 15:10:12 +0700
Subject: Put zero-length extensions first in the ClientHello
---
crypto/src/crypto/tls/TlsProtocol.cs | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
(limited to 'crypto/src')
diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs
index df1c50f02..6e3bbbbdf 100644
--- a/crypto/src/crypto/tls/TlsProtocol.cs
+++ b/crypto/src/crypto/tls/TlsProtocol.cs
@@ -1086,20 +1086,32 @@ namespace Org.BouncyCastle.Crypto.Tls
{
MemoryStream buf = new MemoryStream();
- foreach (int extension_type in extensions.Keys)
- {
- byte[] extension_data = (byte[])extensions[extension_type];
-
- TlsUtilities.CheckUint16(extension_type);
- TlsUtilities.WriteUint16(extension_type, buf);
- TlsUtilities.WriteOpaque16(extension_data, buf);
- }
+ /*
+ * NOTE: There are reports of servers that don't accept a zero-length extension as the last
+ * one, so we write out any zero-length ones first as a best-effort workaround.
+ */
+ WriteSelectedExtensions(buf, extensions, true);
+ WriteSelectedExtensions(buf, extensions, false);
byte[] extBytes = buf.ToArray();
TlsUtilities.WriteOpaque16(extBytes, output);
}
+ protected internal static void WriteSelectedExtensions(Stream output, IDictionary extensions, bool selectEmpty)
+ {
+ foreach (int extension_type in extensions.Keys)
+ {
+ byte[] extension_data = (byte[])extensions[extension_type];
+ if (selectEmpty == (extension_data.Length == 0))
+ {
+ TlsUtilities.CheckUint16(extension_type);
+ TlsUtilities.WriteUint16(extension_type, output);
+ TlsUtilities.WriteOpaque16(extension_data, output);
+ }
+ }
+ }
+
protected internal static void WriteSupplementalData(Stream output, IList supplementalData)
{
MemoryStream buf = new MemoryStream();
--
cgit 1.5.1
From 27ce448162521ace7bc4c0520458ee3dd5665f53 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Wed, 20 Apr 2016 19:48:32 +0700
Subject: Update Poly1305 to comply with RFC 7539
---
crypto/Readme.html | 9 +
.../src/crypto/generators/Poly1305KeyGenerator.cs | 65 +---
crypto/src/crypto/macs/Poly1305.cs | 76 ++---
crypto/src/crypto/tls/Chacha20Poly1305.cs | 5 +-
crypto/test/src/crypto/test/Poly1305Test.cs | 350 ++++++++++++++-------
5 files changed, 300 insertions(+), 205 deletions(-)
(limited to 'crypto/src')
diff --git a/crypto/Readme.html b/crypto/Readme.html
index 7af1bbaf0..0cbd91daa 100644
--- a/crypto/Readme.html
+++ b/crypto/Readme.html
@@ -294,6 +294,15 @@ We state, where EC MQV has not otherwise been disabled or removed:
Release 1.8.2, Release Date TBD
+ IMPORTANT
+
+ -
+ This release brings our Poly1305 implementation into line wih RFC 7539, which breaks backward compatibility. The essential
+ difference from 1.8.1 is that the two halves of the 32-byte Poly1305 key have swapped places. If you have persisted Poly1305
+ keys, or are interoperating with other Poly1305 implementations, you may need to account for this change when migrating to 1.8.2.
+
+
+
Additional Features and Functionality
- TLS: support for ClientHello Padding Extension (RFC 7685).
diff --git a/crypto/src/crypto/generators/Poly1305KeyGenerator.cs b/crypto/src/crypto/generators/Poly1305KeyGenerator.cs
index d05af0add..cdb24bfa0 100644
--- a/crypto/src/crypto/generators/Poly1305KeyGenerator.cs
+++ b/crypto/src/crypto/generators/Poly1305KeyGenerator.cs
@@ -66,51 +66,25 @@ namespace Org.BouncyCastle.Crypto.Generators
* Key is k[0] ... k[15], r[0] ... r[15] as per poly1305_aes_clamp in ref impl.
*/
if (key.Length != 32)
- {
throw new ArgumentException("Poly1305 key must be 256 bits.");
- }
- /*
+ /*
* r[3], r[7], r[11], r[15] have top four bits clear (i.e., are {0, 1, . . . , 15})
*/
- key[19] &= R_MASK_HIGH_4;
- key[23] &= R_MASK_HIGH_4;
- key[27] &= R_MASK_HIGH_4;
- key[31] &= R_MASK_HIGH_4;
+ key[3] &= R_MASK_HIGH_4;
+ key[7] &= R_MASK_HIGH_4;
+ key[11] &= R_MASK_HIGH_4;
+ key[15] &= R_MASK_HIGH_4;
/*
* r[4], r[8], r[12] have bottom two bits clear (i.e., are in {0, 4, 8, . . . , 252}).
*/
- key[20] &= R_MASK_LOW_2;
- key[24] &= R_MASK_LOW_2;
- key[28] &= R_MASK_LOW_2;
+ key[4] &= R_MASK_LOW_2;
+ key[8] &= R_MASK_LOW_2;
+ key[12] &= R_MASK_LOW_2;
}
- internal static void Clamp(byte[] key, int keyOff)
- {
- /*
- * Key is k[0] ... k[15], r[0] ... r[15] as per poly1305_aes_clamp in ref impl.
- */
- if (key.Length - 32 < keyOff)
- throw new ArgumentException("Poly1305 key must be 256 bits.");
-
- /*
- * r[3], r[7], r[11], r[15] have top four bits clear (i.e., are {0, 1, . . . , 15})
- */
- key[keyOff + 19] &= R_MASK_HIGH_4;
- key[keyOff + 23] &= R_MASK_HIGH_4;
- key[keyOff + 27] &= R_MASK_HIGH_4;
- key[keyOff + 31] &= R_MASK_HIGH_4;
-
- /*
- * r[4], r[8], r[12] have bottom two bits clear (i.e., are in {0, 4, 8, . . . , 252}).
- */
- key[keyOff + 20] &= R_MASK_LOW_2;
- key[keyOff + 24] &= R_MASK_LOW_2;
- key[keyOff + 28] &= R_MASK_LOW_2;
- }
-
- ///
+ ///
/// Checks a 32 byte key for compliance with the Poly1305 key requirements, e.g.
/// k[0] ... k[15], r[0] ... r[15]
with the required bits in r
cleared
/// as per .
@@ -121,27 +95,22 @@ namespace Org.BouncyCastle.Crypto.Generators
public static void CheckKey(byte[] key)
{
if (key.Length != 32)
- {
throw new ArgumentException("Poly1305 key must be 256 bits.");
- }
- checkMask(key[19], R_MASK_HIGH_4);
- checkMask(key[23], R_MASK_HIGH_4);
- checkMask(key[27], R_MASK_HIGH_4);
- checkMask(key[31], R_MASK_HIGH_4);
+ CheckMask(key[3], R_MASK_HIGH_4);
+ CheckMask(key[7], R_MASK_HIGH_4);
+ CheckMask(key[11], R_MASK_HIGH_4);
+ CheckMask(key[15], R_MASK_HIGH_4);
- checkMask(key[20], R_MASK_LOW_2);
- checkMask(key[24], R_MASK_LOW_2);
- checkMask(key[28], R_MASK_LOW_2);
+ CheckMask(key[4], R_MASK_LOW_2);
+ CheckMask(key[8], R_MASK_LOW_2);
+ CheckMask(key[12], R_MASK_LOW_2);
}
- private static void checkMask(byte b, byte mask)
+ private static void CheckMask(byte b, byte mask)
{
if ((b & (~mask)) != 0)
- {
throw new ArgumentException("Invalid format for r portion of Poly1305 key.");
- }
}
-
}
}
\ No newline at end of file
diff --git a/crypto/src/crypto/macs/Poly1305.cs b/crypto/src/crypto/macs/Poly1305.cs
index 1a951ca04..0f66ccccc 100644
--- a/crypto/src/crypto/macs/Poly1305.cs
+++ b/crypto/src/crypto/macs/Poly1305.cs
@@ -23,7 +23,7 @@ namespace Org.BouncyCastle.Crypto.Macs
public class Poly1305
: IMac
{
- private const int BLOCK_SIZE = 16;
+ private const int BlockSize = 16;
private readonly IBlockCipher cipher;
@@ -43,7 +43,7 @@ namespace Org.BouncyCastle.Crypto.Macs
// Accumulating state
/** Current block of buffered input */
- private byte[] currentBlock = new byte[BLOCK_SIZE];
+ private byte[] currentBlock = new byte[BlockSize];
/** Current offset in input buffer */
private int currentBlockOffset = 0;
@@ -64,7 +64,7 @@ namespace Org.BouncyCastle.Crypto.Macs
*/
public Poly1305(IBlockCipher cipher)
{
- if (cipher.GetBlockSize() != BLOCK_SIZE)
+ if (cipher.GetBlockSize() != BlockSize)
{
throw new ArgumentException("Poly1305 requires a 128 bit block cipher.");
}
@@ -102,22 +102,24 @@ namespace Org.BouncyCastle.Crypto.Macs
private void SetKey(byte[] key, byte[] nonce)
{
- if (cipher != null && (nonce == null || nonce.Length != BLOCK_SIZE))
- throw new ArgumentException("Poly1305 requires a 128 bit IV.");
+ if (key.Length != 32)
+ throw new ArgumentException("Poly1305 key must be 256 bits.");
- Poly1305KeyGenerator.CheckKey(key);
+ if (cipher != null && (nonce == null || nonce.Length != BlockSize))
+ throw new ArgumentException("Poly1305 requires a 128 bit IV.");
- // Extract r portion of key
- uint t0 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 0);
- uint t1 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 4);
- uint t2 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 8);
- uint t3 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 12);
+ // Extract r portion of key (and "clamp" the values)
+ uint t0 = Pack.LE_To_UInt32(key, 0);
+ uint t1 = Pack.LE_To_UInt32(key, 4);
+ uint t2 = Pack.LE_To_UInt32(key, 8);
+ uint t3 = Pack.LE_To_UInt32(key, 12);
- r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6;
- r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12;
- r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18;
- r3 = t2 & 0x3f03fff; t3 >>= 8;
- r4 = t3 & 0x00fffff;
+ // NOTE: The masks perform the key "clamping" implicitly
+ r0 = t0 & 0x03FFFFFFU;
+ r1 = ((t0 >> 26) | (t1 << 6)) & 0x03FFFF03U;
+ r2 = ((t1 >> 20) | (t2 << 12)) & 0x03FFC0FFU;
+ r3 = ((t2 >> 14) | (t3 << 18)) & 0x03F03FFFU;
+ r4 = (t3 >> 8) & 0x000FFFFFU;
// Precompute multipliers
s1 = r1 * 5;
@@ -126,22 +128,27 @@ namespace Org.BouncyCastle.Crypto.Macs
s4 = r4 * 5;
byte[] kBytes;
+ int kOff;
+
if (cipher == null)
{
kBytes = key;
+ kOff = BlockSize;
}
else
{
// Compute encrypted nonce
- kBytes = new byte[BLOCK_SIZE];
- cipher.Init(true, new KeyParameter(key, 0, BLOCK_SIZE));
+ kBytes = new byte[BlockSize];
+ kOff = 0;
+
+ cipher.Init(true, new KeyParameter(key, BlockSize, BlockSize));
cipher.ProcessBlock(nonce, 0, kBytes, 0);
}
- k0 = Pack.LE_To_UInt32(kBytes, 0);
- k1 = Pack.LE_To_UInt32(kBytes, 4);
- k2 = Pack.LE_To_UInt32(kBytes, 8);
- k3 = Pack.LE_To_UInt32(kBytes, 12);
+ k0 = Pack.LE_To_UInt32(kBytes, kOff + 0);
+ k1 = Pack.LE_To_UInt32(kBytes, kOff + 4);
+ k2 = Pack.LE_To_UInt32(kBytes, kOff + 8);
+ k3 = Pack.LE_To_UInt32(kBytes, kOff + 12);
}
public string AlgorithmName
@@ -151,7 +158,7 @@ namespace Org.BouncyCastle.Crypto.Macs
public int GetMacSize()
{
- return BLOCK_SIZE;
+ return BlockSize;
}
public void Update(byte input)
@@ -165,13 +172,13 @@ namespace Org.BouncyCastle.Crypto.Macs
int copied = 0;
while (len > copied)
{
- if (currentBlockOffset == BLOCK_SIZE)
+ if (currentBlockOffset == BlockSize)
{
- processBlock();
+ ProcessBlock();
currentBlockOffset = 0;
}
- int toCopy = System.Math.Min((len - copied), BLOCK_SIZE - currentBlockOffset);
+ int toCopy = System.Math.Min((len - copied), BlockSize - currentBlockOffset);
Array.Copy(input, copied + inOff, currentBlock, currentBlockOffset, toCopy);
copied += toCopy;
currentBlockOffset += toCopy;
@@ -179,12 +186,12 @@ namespace Org.BouncyCastle.Crypto.Macs
}
- private void processBlock()
+ private void ProcessBlock()
{
- if (currentBlockOffset < BLOCK_SIZE)
+ if (currentBlockOffset < BlockSize)
{
currentBlock[currentBlockOffset] = 1;
- for (int i = currentBlockOffset + 1; i < BLOCK_SIZE; i++)
+ for (int i = currentBlockOffset + 1; i < BlockSize; i++)
{
currentBlock[i] = 0;
}
@@ -201,7 +208,7 @@ namespace Org.BouncyCastle.Crypto.Macs
h3 += (uint)((((t3 << 32) | t2) >> 14) & 0x3ffffff);
h4 += (uint)(t3 >> 8);
- if (currentBlockOffset == BLOCK_SIZE)
+ if (currentBlockOffset == BlockSize)
{
h4 += (1 << 24);
}
@@ -223,15 +230,12 @@ namespace Org.BouncyCastle.Crypto.Macs
public int DoFinal(byte[] output, int outOff)
{
- if (outOff + BLOCK_SIZE > output.Length)
- {
- throw new DataLengthException("Output buffer is too short.");
- }
+ Check.DataLength(output, outOff, BlockSize, "Output buffer is too short.");
if (currentBlockOffset > 0)
{
// Process padded block
- processBlock();
+ ProcessBlock();
}
ulong f0, f1, f2, f3;
@@ -273,7 +277,7 @@ namespace Org.BouncyCastle.Crypto.Macs
Pack.UInt32_To_LE((uint)f3, output, outOff + 12);
Reset();
- return BLOCK_SIZE;
+ return BlockSize;
}
public void Reset()
diff --git a/crypto/src/crypto/tls/Chacha20Poly1305.cs b/crypto/src/crypto/tls/Chacha20Poly1305.cs
index 817e64b25..8687803b4 100644
--- a/crypto/src/crypto/tls/Chacha20Poly1305.cs
+++ b/crypto/src/crypto/tls/Chacha20Poly1305.cs
@@ -145,10 +145,7 @@ namespace Org.BouncyCastle.Crypto.Tls
byte[] firstBlock = new byte[64];
cipher.ProcessBytes(firstBlock, 0, firstBlock.Length, firstBlock, 0);
- // NOTE: The BC implementation puts 'r' after 'k'
- Array.Copy(firstBlock, 0, firstBlock, 32, 16);
- Poly1305KeyGenerator.Clamp(firstBlock, 16);
- KeyParameter macKey = new KeyParameter(firstBlock, 16, 32);
+ KeyParameter macKey = new KeyParameter(firstBlock, 0, 32);
Arrays.Fill(firstBlock, (byte)0);
return macKey;
}
diff --git a/crypto/test/src/crypto/test/Poly1305Test.cs b/crypto/test/src/crypto/test/Poly1305Test.cs
index a1513165b..17c4289aa 100644
--- a/crypto/test/src/crypto/test/Poly1305Test.cs
+++ b/crypto/test/src/crypto/test/Poly1305Test.cs
@@ -20,54 +20,7 @@ namespace Org.BouncyCastle.Crypto.Tests
{
private const int MAXLEN = 1000;
- private class KeyEngine
- : IBlockCipher
- {
-
- private byte[] key;
- private int blockSize;
-
- public KeyEngine(int blockSize)
- {
- this.blockSize = blockSize;
- }
-
- public void Init(bool forEncryption, ICipherParameters parameters)
- {
- if (parameters is KeyParameter)
- {
- this.key = ((KeyParameter)parameters).GetKey();
- }
- }
-
- public bool IsPartialBlockOkay
- {
- get { return false; }
- }
-
- public string AlgorithmName
- {
- get { return "Key"; }
- }
-
- public int GetBlockSize()
- {
- return blockSize;
- }
-
- public int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
- {
- Array.Copy(key, 0, output, outOff, key.Length);
- return key.Length;
- }
-
- public void Reset()
- {
- }
-
- }
-
- private class TestCase
+ private class TestCase
{
internal byte[] key;
internal byte[] nonce;
@@ -85,57 +38,54 @@ namespace Org.BouncyCastle.Crypto.Tests
}
}
- private static TestCase[] CASES = {
- // Raw Poly1305
- // onetimeauth.c from nacl-20110221
- new TestCase("2539121d8e234e652d651fa4c8cff880eea6a7251c1e72916d11c2cb214d3c25", null,
- "8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186a"
- + "c0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738"
- + "b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da"
- + "99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74e355a5",
- "f3ffc7703f9400e52a7dfb4b3d3305d9"),
-
- // Poly1305-AES
- // Loop 1 of test-poly1305aes from poly1305aes-20050218
- new TestCase("0000000000000000000000000000000000000000000000000000000000000000",
- "00000000000000000000000000000000", "", "66e94bd4ef8a2c3b884cfa59ca342b2e"),
- new TestCase("f795bd4a52e29ed713d313fa20e98dbcf795bd0a50e29e0710d3130a20e98d0c",
- "917cf69ebd68b2ec9b9fe9a3eadda692", "66f7", "5ca585c75e8f8f025e710cabc9a1508b"),
- new TestCase("e69dae0aab9f91c03a325dcc9436fa903ef49901c8e11c000430d90ad45e7603",
- "166450152e2394835606a9d1dd2cdc8b", "66f75c0e0c7a406586", "2924f51b9c2eff5df09db61dd03a9ca1"),
- new TestCase("85a4ea91a7de0b0d96eed0d4bf6ecf1cda4afc035087d90e503f8f0ea08c3e0d",
- "0b6ef7a0b8f8c738b0f8d5995415271f",
- "66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea",
- "3c5a13adb18d31c64cc29972030c917d"),
- new TestCase(
- "25eb69bac5cdf7d6bfcee4d9d5507b82ca3c6a0da0a864024ca3090628c28e0d",
- "046772a4f0a8de92e4f0d628cdb04484",
- "66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea3caa4d240bd2ab8a8c4a6bb8d3288d9de4b793f05e97646dd4d98055de",
- "fc5fb58dc65daf19b14d1d05da1064e8"),
-
- // Specific test cases generated from test-poly1305aes from poly1305aes-20050218 that
- // expose Java unsigned integer problems
- new TestCase(
- "95cc0e44d0b79a8856afcae1bec4fe3c" + "01bcb20bfc8b6e03609ddd09f44b060f",
- null,
- "66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea3caa4d240bd2ab8a8c4a6bb8d3288d9de4b793f05e97646dd4d98055de"
- + "fc3e0677d956b4c62664bac15962ab15d93ccbbc03aafdbde779162ed93b55361f0f8acaa41d50ef5175927fe79ea316186516eef15001cd04d3524a55"
- + "e4fa3c5ca479d3aaa8a897c21807f721b6270ffc68b6889d81a116799f6aaa35d8e04c7a7dd5e6da2519e8759f54e906696f5772fee093283bcef7b930"
- + "aed50323bcbc8c820c67422c1e16bdc022a9c0277c9d95fef0ea4ee11e2b27276da811523c5acb80154989f8a67ee9e3fa30b73b0c1c34bf46e3464d97"
- + "7cd7fcd0ac3b82721080bb0d9b982ee2c77feee983d7ba35da88ce86955002940652ab63bc56fb16f994da2b01d74356509d7d1b6d7956b0e5a557757b"
- + "d1ced2eef8650bc5b6d426108c1518abcbd0befb6a0d5fd57a3e2dbf31458eab63df66613653d4beae73f5c40eb438fbcfdcf4a4ba46320184b9ca0da4"
- + "dfae77de7ccc910356caea3243f33a3c81b064b3b7cedc7435c223f664227215715980e6e0bb570d459ba80d7512dbe458c8f0f3f52d659b6e8eef19ee"
- + "71aea2ced85c7a42ffca6522a62db49a2a46eff72bd7f7e0883acd087183f0627f3537a4d558754ed63358e8182bee196735b361dc9bd64d5e34e1074a"
- + "855655d2974cc6fa1653754cf40f561d8c7dc526aab2908ec2d2b977cde1a1fb1071e32f40e049ea20f30368ba1592b4fe57fb51595d23acbdace324cd"
- + "d78060a17187c662368854e915402d9b52fb21e984663e41c26a109437e162cfaf071b53f77e50000a5388ff183b82ce7a1af476c416d7d204157b3633"
- + "b2f4ec077b699b032816997e37bceded8d4a04976fd7d0c0b029f290794c3be504c5242287ea2f831f11ed5690d92775cd6e863d7731fd4da687ebfb13"
- + "df4c41dc0fb8", "ae345d555eb04d6947bb95c0965237e2"),
- new TestCase(
- "76fb3635a2dc92a1f768163ab12f2187" + "cd07fd0ef8c0be0afcbdb30af4af0009",
- null,
- "f05204a74f0f88a7fa1a95b84ec3d8ffb36fcdc7723ea65dfe7cd464e86e0abf6b9d51db3220cfd8496ad6e6d36ebee8d990f9ce0d3bb7f72b7ab5b3ab0a73240d11efe772c857021ae859db4933cdde4387b471d2ce700fef4b81087f8f47c307881fd83017afcd15b8d21edf9b704677f46df97b07e5b83f87c8abd90af9b1d0f9e2710e8ebd0d4d1c6a055abea861f42368bed94d9373e909c1d3715b221c16bc524c55c31ec3eab204850bb2474a84f9917038eff9d921130951391b5c54f09b5e1de833ea2cd7d3b306740abb7096d1e173da83427da2adddd3631eda30b54dbf487f2b082e8646f07d6e0a87e97522ca38d4ace4954bf3db6dd3a93b06fa18eb56856627ed6cffcd7ae26374554ca18ab8905f26331d323fe10e6e70624c7bc07a70f06ecd804b48f8f7e75e910165e1beb554f1f0ec7949c9c8d429a206b4d5c0653102249b6098e6b45fac2a07ff0220b0b8ae8f4c6bcc0c813a7cd141fa8b398b42575fc395747c5a0257ac41d6c1f434cfbf5dfe8349f5347ef6b60e611f5d6c3cbc20ca2555274d1934325824cef4809da293ea13f181929e2af025bbd1c9abdc3af93afd4c50a2854ade3887f4d2c8c225168052c16e74d76d2dd3e9467a2c5b8e15c06ffbffa42b8536384139f07e195a8c9f70f514f31dca4eb2cf262c0dcbde53654b6250a29efe21d54e83c80e005a1cad36d5934ff01c32e4bc5fe06d03064ff4a268517df4a94c759289f323734318cfa5d859d4ce9c16e63d02dff0896976f521607638535d2ee8dd3312e1ddc80a55d34fe829ab954c1ebd54d929954770f1be9d32b4c05003c5c9e97943b6431e2afe820b1e967b19843e5985a131b1100517cdc363799104af91e2cf3f53cb8fd003653a6dd8a31a3f9d566a7124b0ffe9695bcb87c482eb60106f88198f766a40bc0f4873c23653c5f9e7a8e446f770beb8034cf01d21028ba15ccee21a8db918c4829d61c88bfa927bc5def831501796c5b401a60a6b1b433c9fb905c8cd40412fffee81ab",
- "045be28cc52009f506bdbfabedacf0b4"),
-
+ private static TestCase[] CASES = {
+ // Raw Poly1305
+ // onetimeauth.c from nacl-20110221
+ new TestCase("eea6a7251c1e72916d11c2cb214d3c25" + "2539121d8e234e652d651fa4c8cff880", null,
+ "8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186a"
+ + "c0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738"
+ + "b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da"
+ + "99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74e355a5",
+ "f3ffc7703f9400e52a7dfb4b3d3305d9"),
+ // Poly1305-AES
+ // Loop 1 of test-poly1305aes from poly1305aes-20050218
+ new TestCase("0000000000000000000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000", "", "66e94bd4ef8a2c3b884cfa59ca342b2e"),
+ new TestCase("f795bd0a50e29e0710d3130a20e98d0c" + "f795bd4a52e29ed713d313fa20e98dbc",
+ "917cf69ebd68b2ec9b9fe9a3eadda692", "66f7", "5ca585c75e8f8f025e710cabc9a1508b"),
+ new TestCase("3ef49901c8e11c000430d90ad45e7603" + "e69dae0aab9f91c03a325dcc9436fa90",
+ "166450152e2394835606a9d1dd2cdc8b", "66f75c0e0c7a406586", "2924f51b9c2eff5df09db61dd03a9ca1"),
+ new TestCase("da4afc035087d90e503f8f0ea08c3e0d" + "85a4ea91a7de0b0d96eed0d4bf6ecf1c",
+ "0b6ef7a0b8f8c738b0f8d5995415271f",
+ "66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea",
+ "3c5a13adb18d31c64cc29972030c917d"),
+ new TestCase(
+ "ca3c6a0da0a864024ca3090628c28e0d" + "25eb69bac5cdf7d6bfcee4d9d5507b82",
+ "046772a4f0a8de92e4f0d628cdb04484",
+ "66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea3caa4d240bd2ab8a8c4a6bb8d3288d9de4b793f05e97646dd4d98055de",
+ "fc5fb58dc65daf19b14d1d05da1064e8"),
+ // Specific test cases generated from test-poly1305aes from poly1305aes-20050218 that
+ // expose Java unsigned integer problems
+ new TestCase(
+ "01bcb20bfc8b6e03609ddd09f44b060f" + "95cc0e44d0b79a8856afcae1bec4fe3c",
+ null,
+ "66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea3caa4d240bd2ab8a8c4a6bb8d3288d9de4b793f05e97646dd4d98055de"
+ + "fc3e0677d956b4c62664bac15962ab15d93ccbbc03aafdbde779162ed93b55361f0f8acaa41d50ef5175927fe79ea316186516eef15001cd04d3524a55"
+ + "e4fa3c5ca479d3aaa8a897c21807f721b6270ffc68b6889d81a116799f6aaa35d8e04c7a7dd5e6da2519e8759f54e906696f5772fee093283bcef7b930"
+ + "aed50323bcbc8c820c67422c1e16bdc022a9c0277c9d95fef0ea4ee11e2b27276da811523c5acb80154989f8a67ee9e3fa30b73b0c1c34bf46e3464d97"
+ + "7cd7fcd0ac3b82721080bb0d9b982ee2c77feee983d7ba35da88ce86955002940652ab63bc56fb16f994da2b01d74356509d7d1b6d7956b0e5a557757b"
+ + "d1ced2eef8650bc5b6d426108c1518abcbd0befb6a0d5fd57a3e2dbf31458eab63df66613653d4beae73f5c40eb438fbcfdcf4a4ba46320184b9ca0da4"
+ + "dfae77de7ccc910356caea3243f33a3c81b064b3b7cedc7435c223f664227215715980e6e0bb570d459ba80d7512dbe458c8f0f3f52d659b6e8eef19ee"
+ + "71aea2ced85c7a42ffca6522a62db49a2a46eff72bd7f7e0883acd087183f0627f3537a4d558754ed63358e8182bee196735b361dc9bd64d5e34e1074a"
+ + "855655d2974cc6fa1653754cf40f561d8c7dc526aab2908ec2d2b977cde1a1fb1071e32f40e049ea20f30368ba1592b4fe57fb51595d23acbdace324cd"
+ + "d78060a17187c662368854e915402d9b52fb21e984663e41c26a109437e162cfaf071b53f77e50000a5388ff183b82ce7a1af476c416d7d204157b3633"
+ + "b2f4ec077b699b032816997e37bceded8d4a04976fd7d0c0b029f290794c3be504c5242287ea2f831f11ed5690d92775cd6e863d7731fd4da687ebfb13"
+ + "df4c41dc0fb8", "ae345d555eb04d6947bb95c0965237e2"),
+ new TestCase(
+ "cd07fd0ef8c0be0afcbdb30af4af0009" + "76fb3635a2dc92a1f768163ab12f2187",
+ null,
+ "f05204a74f0f88a7fa1a95b84ec3d8ffb36fcdc7723ea65dfe7cd464e86e0abf6b9d51db3220cfd8496ad6e6d36ebee8d990f9ce0d3bb7f72b7ab5b3ab0a73240d11efe772c857021ae859db4933cdde4387b471d2ce700fef4b81087f8f47c307881fd83017afcd15b8d21edf9b704677f46df97b07e5b83f87c8abd90af9b1d0f9e2710e8ebd0d4d1c6a055abea861f42368bed94d9373e909c1d3715b221c16bc524c55c31ec3eab204850bb2474a84f9917038eff9d921130951391b5c54f09b5e1de833ea2cd7d3b306740abb7096d1e173da83427da2adddd3631eda30b54dbf487f2b082e8646f07d6e0a87e97522ca38d4ace4954bf3db6dd3a93b06fa18eb56856627ed6cffcd7ae26374554ca18ab8905f26331d323fe10e6e70624c7bc07a70f06ecd804b48f8f7e75e910165e1beb554f1f0ec7949c9c8d429a206b4d5c0653102249b6098e6b45fac2a07ff0220b0b8ae8f4c6bcc0c813a7cd141fa8b398b42575fc395747c5a0257ac41d6c1f434cfbf5dfe8349f5347ef6b60e611f5d6c3cbc20ca2555274d1934325824cef4809da293ea13f181929e2af025bbd1c9abdc3af93afd4c50a2854ade3887f4d2c8c225168052c16e74d76d2dd3e9467a2c5b8e15c06ffbffa42b8536384139f07e195a8c9f70f514f31dca4eb2cf262c0dcbde53654b6250a29efe21d54e83c80e005a1cad36d5934ff01c32e4bc5fe06d03064ff4a268517df4a94c759289f323734318cfa5d859d4ce9c16e63d02dff0896976f521607638535d2ee8dd3312e1ddc80a55d34fe829ab954c1ebd54d929954770f1be9d32b4c05003c5c9e97943b6431e2afe820b1e967b19843e5985a131b1100517cdc363799104af91e2cf3f53cb8fd003653a6dd8a31a3f9d566a7124b0ffe9695bcb87c482eb60106f88198f766a40bc0f4873c23653c5f9e7a8e446f770beb8034cf01d21028ba15ccee21a8db918c4829d61c88bfa927bc5def831501796c5b401a60a6b1b433c9fb905c8cd40412fffee81ab",
+ "045be28cc52009f506bdbfabedacf0b4"),
};
public override string Name
@@ -153,6 +103,7 @@ namespace Org.BouncyCastle.Crypto.Tests
}
testSequential();
testReset();
+ rfc7539Test();
}
private void testCase(int i)
@@ -164,8 +115,8 @@ namespace Org.BouncyCastle.Crypto.Tests
if (tc.nonce == null)
{
// Raw Poly1305 test - don't do any transform on AES key part
- mac = new Poly1305(new KeyEngine(16));
- mac.Init(new ParametersWithIV(new KeyParameter(tc.key), new byte[16]));
+ mac = new Poly1305();
+ mac.Init(new KeyParameter(tc.key));
}
else
{
@@ -228,23 +179,33 @@ namespace Org.BouncyCastle.Crypto.Tests
if (len >= MAXLEN)
break;
n[0] = (byte)(n[0] ^ loop);
- for (int i = 0; i < 16; ++i)
- n[i] ^= output[i];
- if (len % 2 != 0)
- for (int i = 0; i < 16; ++i)
- kr[i] ^= output[i];
+ for (int i = 0; i < 16; ++i)
+ {
+ n[i] ^= output[i];
+ }
+ if (len % 2 != 0)
+ {
+ for (int i = 0; i < 16; ++i)
+ {
+ kr[i] ^= output[i];
+ }
+ }
if (len % 3 != 0)
+ {
for (int i = 0; i < 16; ++i)
+ {
kr[i + 16] ^= output[i];
- Poly1305KeyGenerator.Clamp(kr);
+ }
+ }
+ Poly1305KeyGenerator.Clamp(kr);
m[len++] ^= output[0];
}
}
// Output after 13 loops as generated by poly1305 ref
- if (c != 13013 || !Arrays.AreEqual(output, Hex.Decode("c96f60a23701a5b0fd2016f58cbe4f7e")))
- {
- Fail("Sequential Poly1305 " + c, "c96f60a23701a5b0fd2016f58cbe4f7e", Hex.ToHexString(output));
- }
+ if (c != 13013 || !Arrays.AreEqual(output, Hex.Decode("89824ddf0816481051f4a82731cd56d5")))
+ {
+ Fail("Sequential Poly1305 " + c, "89824ddf0816481051f4a82731cd56d5", Hex.ToHexString(output));
+ }
}
private void testReset()
@@ -311,7 +272,8 @@ namespace Org.BouncyCastle.Crypto.Tests
{
poly.Init(new ParametersWithIV(new KeyParameter(k), new byte[15]));
Fail("16 byte nonce required");
- } catch (ArgumentException)
+ }
+ catch (ArgumentException)
{
// Expected
}
@@ -322,21 +284,24 @@ namespace Org.BouncyCastle.Crypto.Tests
Array.Copy(k, 0, k2, 0, k2.Length);
poly.Init(new ParametersWithIV(new KeyParameter(k2), new byte[16]));
Fail("32 byte key required");
- } catch (ArgumentException)
+ }
+ catch (ArgumentException)
{
// Expected
}
+ /*
try
{
k[19] = (byte)0xFF;
poly.Init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
Fail("UnClamped key should not be accepted.");
- } catch (ArgumentException)
+ }
+ catch (ArgumentException)
{
// Expected
}
-
+ */
}
private void testKeyGenerator()
@@ -353,7 +318,8 @@ namespace Org.BouncyCastle.Crypto.Tests
try
{
Poly1305KeyGenerator.CheckKey(k);
- } catch (ArgumentException)
+ }
+ catch (ArgumentException)
{
Fail("Poly1305 key should be Clamped on generation.");
}
@@ -366,17 +332,167 @@ namespace Org.BouncyCastle.Crypto.Tests
Fail("Poly1305 key should be Clamped on generation.");
}
+ /*
try
{
k2[19] = (byte)0xff;
Poly1305KeyGenerator.CheckKey(k2);
Fail("UnClamped key should fail check.");
- } catch (ArgumentException)
+ }
+ catch (ArgumentException)
{
// Expected
}
+ */
}
+ public void rfc7539Test()
+ {
+ // From RFC 7539
+ byte[] keyMaterial = Hex.Decode("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b");
+ byte[] data = Hex.Decode("43727970746f677261706869 63 20 46 6f 72 75 6d 20 52 65 73 65 61 72 63 68 20 47 72 6f7570");
+ byte[] expected = Hex.Decode("a8061dc1305136c6c22b8baf0c0127a9");
+
+ CheckVector(keyMaterial, data, expected);
+
+ data = Hex.Decode("48656c6c6f20776f726c6421");
+ keyMaterial = Hex.Decode(
+ "746869732069732033322d6279746520" +
+ "6b657920666f7220506f6c7931333035");
+
+ CheckVector(keyMaterial, data, Hex.Decode("a6f745008f81c916a20dcc74eef2b2f0"));
+
+ // A.3 #1
+ keyMaterial = Hex.Decode("00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
+
+ data = Hex.Decode(
+ "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
+ + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
+ + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
+ + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
+
+ CheckVector(keyMaterial, data, Hex.Decode("00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"));
+
+ // A.3 #2
+ keyMaterial = Hex.Decode("00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0036 e5 f6 b5 c5 e0 60 70 f0 ef ca 96 22 7a 86 3e");
+
+ data = Hex.Decode(
+ "41 6e 79 20 73 75 62 6d 69 73 73 69 6f 6e 20 74"
+ + "6f 20 74 68 65 20 49 45 54 46 20 69 6e 74 65 6e"
+ + "64 65 64 20 62 79 20 74 68 65 20 43 6f 6e 74 72"
+ + "69 62 75 74 6f 72 20 66 6f 72 20 70 75 62 6c 69"
+ + "63 61 74 69 6f 6e 20 61 73 20 61 6c 6c 20 6f 72"
+ + "20 70 61 72 74 20 6f 66 20 61 6e 20 49 45 54 46"
+ + "20 49 6e 74 65 72 6e 65 74 2d 44 72 61 66 74 20"
+ + "6f 72 20 52 46 43 20 61 6e 64 20 61 6e 79 20 73"
+ + "74 61 74 65 6d 65 6e 74 20 6d 61 64 65 20 77 69"
+ + "74 68 69 6e 20 74 68 65 20 63 6f 6e 74 65 78 74"
+ + "20 6f 66 20 61 6e 20 49 45 54 46 20 61 63 74 69"
+ + "76 69 74 79 20 69 73 20 63 6f 6e 73 69 64 65 72"
+ + "65 64 20 61 6e 20 22 49 45 54 46 20 43 6f 6e 74"
+ + "72 69 62 75 74 69 6f 6e 22 2e 20 53 75 63 68 20"
+ + "73 74 61 74 65 6d 65 6e 74 73 20 69 6e 63 6c 75"
+ + "64 65 20 6f 72 61 6c 20 73 74 61 74 65 6d 65 6e"
+ + "74 73 20 69 6e 20 49 45 54 46 20 73 65 73 73 69"
+ + "6f 6e 73 2c 20 61 73 20 77 65 6c 6c 20 61 73 20"
+ + "77 72 69 74 74 65 6e 20 61 6e 64 20 65 6c 65 63"
+ + "74 72 6f 6e 69 63 20 63 6f 6d 6d 75 6e 69 63 61"
+ + "74 69 6f 6e 73 20 6d 61 64 65 20 61 74 20 61 6e"
+ + "79 20 74 69 6d 65 20 6f 72 20 70 6c 61 63 65 2c"
+ + "20 77 68 69 63 68 20 61 72 65 20 61 64 64 72 65"
+ + "73 73 65 64 20 74 6f");
+
+ CheckVector(keyMaterial, data, Hex.Decode("36 e5 f6 b5 c5 e0 60 70 f0 ef ca 96 22 7a 86 3e"));
+
+ // A.3 #3
+ keyMaterial = Hex.Decode("36 e5 f6 b5 c5 e0 60 70 f0 ef ca 96 22 7a 86 3e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
+
+ CheckVector(keyMaterial, data, Hex.Decode("f3 47 7e 7c d9 54 17 af 89 a6 b8 79 4c 31 0c f0"));
+
+ // A.3 #4
+
+ keyMaterial = Hex.Decode("1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f0 47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0");
+
+ data = Hex.Decode(
+ "27 54 77 61 73 20 62 72 69 6c 6c 69 67 2c 20 61"
+ + "6e 64 20 74 68 65 20 73 6c 69 74 68 79 20 74 6f"
+ + "76 65 73 0a 44 69 64 20 67 79 72 65 20 61 6e 64"
+ + "20 67 69 6d 62 6c 65 20 69 6e 20 74 68 65 20 77"
+ + "61 62 65 3a 0a 41 6c 6c 20 6d 69 6d 73 79 20 77"
+ + "65 72 65 20 74 68 65 20 62 6f 72 6f 67 6f 76 65"
+ + "73 2c 0a 41 6e 64 20 74 68 65 20 6d 6f 6d 65 20"
+ + "72 61 74 68 73 20 6f 75 74 67 72 61 62 65 2e");
+
+ CheckVector(keyMaterial, data, Hex.Decode("45 41 66 9a 7e aa ee 61 e7 08 dc 7c bc c5 eb 62"));
+
+ // A.3 #5
+ keyMaterial = Hex.Decode("02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
+ data = Hex.Decode("FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF");
+
+ CheckVector(keyMaterial, data, Hex.Decode("03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"));
+
+ // A.3 #6
+ keyMaterial = Hex.Decode("02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF");
+ data = Hex.Decode("02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
+
+ CheckVector(keyMaterial, data, Hex.Decode("03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"));
+
+ // A.3 #7
+ keyMaterial = Hex.Decode("01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
+ data = Hex.Decode("FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FFF0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
+
+ CheckVector(keyMaterial, data, Hex.Decode("05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"));
+
+ // A.3 #8
+ keyMaterial = Hex.Decode("01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
+ data = Hex.Decode("FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FFFB FE FE FE FE FE FE FE FE FE FE FE FE FE FE FE01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01");
+
+ CheckVector(keyMaterial, data, Hex.Decode("00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"));
+
+ // A.3 #9
+ keyMaterial = Hex.Decode("02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
+ data = Hex.Decode("FD FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF");
+
+ CheckVector(keyMaterial, data, Hex.Decode("FA FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF"));
+
+ // A.3 #10
+ keyMaterial = Hex.Decode("01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
+ data = Hex.Decode(
+ "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00"
+ + "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00"
+ + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
+ + "01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
+
+ CheckVector(keyMaterial, data, Hex.Decode("14 00 00 00 00 00 00 00 55 00 00 00 00 00 00 00"));
+
+ // A.3 #11
+ keyMaterial = Hex.Decode("01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
+ data = Hex.Decode(
+ "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00"
+ + "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00"
+ + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
+
+ CheckVector(keyMaterial, data, Hex.Decode("13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"));
+ }
+
+ private void CheckVector(byte[] keyMaterial, byte[] input, byte[] tag)
+ {
+ Poly1305 poly1305 = new Poly1305();
+
+ poly1305.Init(new KeyParameter(keyMaterial));
+
+ poly1305.BlockUpdate(input, 0, input.Length);
+
+ byte[] mac = new byte[poly1305.GetMacSize()];
+
+ poly1305.DoFinal(mac, 0);
+
+ if (!Arrays.AreEqual(tag, mac))
+ {
+ Fail("rfc7539", Hex.ToHexString(tag), Hex.ToHexString(mac));
+ }
+ }
+
public static void Main(
string[] args)
{
--
cgit 1.5.1
From 3bdc9101f9babcefb1e9e3b8ca6d0a6da39be568 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Wed, 20 Apr 2016 19:53:12 +0700
Subject: Minor change to error messages
---
crypto/src/tsp/TimeStampRequest.cs | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)
(limited to 'crypto/src')
diff --git a/crypto/src/tsp/TimeStampRequest.cs b/crypto/src/tsp/TimeStampRequest.cs
index f54d33e04..0b41adef7 100644
--- a/crypto/src/tsp/TimeStampRequest.cs
+++ b/crypto/src/tsp/TimeStampRequest.cs
@@ -130,34 +130,24 @@ namespace Org.BouncyCastle.Tsp
IList extensions)
{
if (!algorithms.Contains(this.MessageImprintAlgOid))
- {
- throw new TspValidationException("request contains unknown algorithm.", PkiFailureInfo.BadAlg);
- }
+ throw new TspValidationException("request contains unknown algorithm", PkiFailureInfo.BadAlg);
- if (policies != null && this.ReqPolicy != null && !policies.Contains(this.ReqPolicy))
- {
- throw new TspValidationException("request contains unknown policy.", PkiFailureInfo.UnacceptedPolicy);
- }
+ if (policies != null && this.ReqPolicy != null && !policies.Contains(this.ReqPolicy))
+ throw new TspValidationException("request contains unknown policy", PkiFailureInfo.UnacceptedPolicy);
- if (this.Extensions != null && extensions != null)
+ if (this.Extensions != null && extensions != null)
{
foreach (DerObjectIdentifier oid in this.Extensions.ExtensionOids)
{
if (!extensions.Contains(oid.Id))
- {
- throw new TspValidationException("request contains unknown extension.",
- PkiFailureInfo.UnacceptedExtension);
- }
+ throw new TspValidationException("request contains unknown extension", PkiFailureInfo.UnacceptedExtension);
}
}
int digestLength = TspUtil.GetDigestLength(this.MessageImprintAlgOid);
if (digestLength != this.GetMessageImprintDigest().Length)
- {
- throw new TspValidationException("imprint digest the wrong length.",
- PkiFailureInfo.BadDataFormat);
- }
+ throw new TspValidationException("imprint digest the wrong length", PkiFailureInfo.BadDataFormat);
}
/**
--
cgit 1.5.1
From 95e03104ddb274e1f15e41393041068bea97203f Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Thu, 21 Apr 2016 00:03:47 +0700
Subject: Update to draft-zauner-tls-aes-ocb-04
---
crypto/src/crypto/tls/CipherSuite.cs | 2 +-
crypto/src/crypto/tls/DefaultTlsCipherFactory.cs | 2 +-
crypto/src/crypto/tls/EncryptionAlgorithm.cs | 2 +-
crypto/src/crypto/tls/TlsAeadCipher.cs | 76 ++++++++++++++++--------
crypto/src/crypto/tls/TlsDHUtilities.cs | 2 +-
crypto/src/crypto/tls/TlsEccUtilities.cs | 2 +-
6 files changed, 57 insertions(+), 29 deletions(-)
(limited to 'crypto/src')
diff --git a/crypto/src/crypto/tls/CipherSuite.cs b/crypto/src/crypto/tls/CipherSuite.cs
index 265174341..679a8be85 100644
--- a/crypto/src/crypto/tls/CipherSuite.cs
+++ b/crypto/src/crypto/tls/CipherSuite.cs
@@ -347,7 +347,7 @@ namespace Org.BouncyCastle.Crypto.Tls
public const int DRAFT_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAE;
/*
- * draft-zauner-tls-aes-ocb-03 (code points TBD)
+ * draft-zauner-tls-aes-ocb-04 (code points TBD)
*/
public const int DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB = 0xFF00;
public const int DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB = 0xFF01;
diff --git a/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs b/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs
index 1e03ec3a8..af0ec126a 100644
--- a/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs
+++ b/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs
@@ -107,7 +107,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected virtual TlsAeadCipher CreateCipher_Aes_Ocb(TlsContext context, int cipherKeySize, int macSize)
{
return new TlsAeadCipher(context, CreateAeadBlockCipher_Aes_Ocb(),
- CreateAeadBlockCipher_Aes_Ocb(), cipherKeySize, macSize, TlsAeadCipher.NONCE_DRAFT_ZAUNER_TLS_AES_OCB);
+ CreateAeadBlockCipher_Aes_Ocb(), cipherKeySize, macSize, TlsAeadCipher.NONCE_DRAFT_CHACHA20_POLY1305);
}
///
diff --git a/crypto/src/crypto/tls/EncryptionAlgorithm.cs b/crypto/src/crypto/tls/EncryptionAlgorithm.cs
index 04c1733cb..96037ed20 100644
--- a/crypto/src/crypto/tls/EncryptionAlgorithm.cs
+++ b/crypto/src/crypto/tls/EncryptionAlgorithm.cs
@@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Crypto.Tls
[Obsolete] public const int AEAD_CHACHA20_POLY1305 = CHACHA20_POLY1305;
/*
- * draft-zauner-tls-aes-ocb-03
+ * draft-zauner-tls-aes-ocb-04
*/
public const int AES_128_OCB_TAGLEN96 = 103;
public const int AES_256_OCB_TAGLEN96 = 104;
diff --git a/crypto/src/crypto/tls/TlsAeadCipher.cs b/crypto/src/crypto/tls/TlsAeadCipher.cs
index bff719db1..cc0575cf0 100644
--- a/crypto/src/crypto/tls/TlsAeadCipher.cs
+++ b/crypto/src/crypto/tls/TlsAeadCipher.cs
@@ -10,8 +10,14 @@ namespace Org.BouncyCastle.Crypto.Tls
public class TlsAeadCipher
: TlsCipher
{
+ // TODO[draft-zauner-tls-aes-ocb-04] Apply data volume limit described in section 8.4
+
public const int NONCE_RFC5288 = 1;
- internal const int NONCE_DRAFT_ZAUNER_TLS_AES_OCB = 2;
+
+ /*
+ * draft-zauner-tls-aes-ocb-04 specifies the nonce construction from draft-ietf-tls-chacha20-poly1305-04
+ */
+ internal const int NONCE_DRAFT_CHACHA20_POLY1305 = 2;
protected readonly TlsContext context;
protected readonly int macSize;
@@ -23,6 +29,8 @@ namespace Org.BouncyCastle.Crypto.Tls
protected readonly byte[] encryptImplicitNonce, decryptImplicitNonce;
+ protected readonly int nonceMode;
+
///
public TlsAeadCipher(TlsContext context, IAeadBlockCipher clientWriteCipher, IAeadBlockCipher serverWriteCipher,
int cipherKeySize, int macSize)
@@ -37,12 +45,19 @@ namespace Org.BouncyCastle.Crypto.Tls
if (!TlsUtilities.IsTlsV12(context))
throw new TlsFatalAlert(AlertDescription.internal_error);
+ this.nonceMode = nonceMode;
+
+ // TODO SecurityParameters.fixed_iv_length
+ int fixed_iv_length;
+
switch (nonceMode)
{
case NONCE_RFC5288:
+ fixed_iv_length = 4;
this.record_iv_length = 8;
break;
- case NONCE_DRAFT_ZAUNER_TLS_AES_OCB:
+ case NONCE_DRAFT_CHACHA20_POLY1305:
+ fixed_iv_length = 12;
this.record_iv_length = 0;
break;
default:
@@ -52,9 +67,6 @@ namespace Org.BouncyCastle.Crypto.Tls
this.context = context;
this.macSize = macSize;
- // TODO SecurityParameters.fixed_iv_length
- int fixed_iv_length = 4;
-
int key_block_size = (2 * cipherKeySize) + (2 * fixed_iv_length);
byte[] key_block = TlsUtilities.CalculateKeyBlock(context, key_block_size);
@@ -93,7 +105,7 @@ namespace Org.BouncyCastle.Crypto.Tls
decryptKey = server_write_key;
}
- byte[] dummyNonce = new byte[fixed_iv_length + 8];
+ byte[] dummyNonce = new byte[fixed_iv_length + record_iv_length];
this.encryptCipher.Init(true, new AeadParameters(encryptKey, 8 * macSize, dummyNonce));
this.decryptCipher.Init(false, new AeadParameters(decryptKey, 8 * macSize, dummyNonce));
@@ -108,16 +120,25 @@ namespace Org.BouncyCastle.Crypto.Tls
///
public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
{
- byte[] nonce = new byte[this.encryptImplicitNonce.Length + 8];
- Array.Copy(encryptImplicitNonce, 0, nonce, 0, encryptImplicitNonce.Length);
+ byte[] nonce = new byte[encryptImplicitNonce.Length + record_iv_length];
- /*
- * RFC 5288/6655: The nonce_explicit MAY be the 64-bit sequence number.
- * draft-zauner-tls-aes-ocb-03: uses the sequence number (not included in message).
- *
- * (May need review for other AEAD ciphers).
- */
- TlsUtilities.WriteUint64(seqNo, nonce, encryptImplicitNonce.Length);
+ switch (nonceMode)
+ {
+ case NONCE_RFC5288:
+ Array.Copy(encryptImplicitNonce, 0, nonce, 0, encryptImplicitNonce.Length);
+ // RFC 5288/6655: The nonce_explicit MAY be the 64-bit sequence number.
+ TlsUtilities.WriteUint64(seqNo, nonce, encryptImplicitNonce.Length);
+ break;
+ case NONCE_DRAFT_CHACHA20_POLY1305:
+ TlsUtilities.WriteUint64(seqNo, nonce, nonce.Length - 8);
+ for (int i = 0; i < encryptImplicitNonce.Length; ++i)
+ {
+ nonce[i] ^= encryptImplicitNonce[i];
+ }
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
int plaintextOffset = offset;
int plaintextLength = len;
@@ -159,16 +180,23 @@ namespace Org.BouncyCastle.Crypto.Tls
if (GetPlaintextLimit(len) < 0)
throw new TlsFatalAlert(AlertDescription.decode_error);
- byte[] nonce = new byte[this.decryptImplicitNonce.Length + 8];
- Array.Copy(decryptImplicitNonce, 0, nonce, 0, decryptImplicitNonce.Length);
- //Array.Copy(ciphertext, offset, nonce, decryptImplicitNonce.Length, nonce_explicit_length);
- if (record_iv_length == 0)
- {
- TlsUtilities.WriteUint64(seqNo, nonce, decryptImplicitNonce.Length);
- }
- else
+ byte[] nonce = new byte[decryptImplicitNonce.Length + record_iv_length];
+
+ switch (nonceMode)
{
- Array.Copy(ciphertext, offset, nonce, nonce.Length - record_iv_length, record_iv_length);
+ case NONCE_RFC5288:
+ Array.Copy(decryptImplicitNonce, 0, nonce, 0, decryptImplicitNonce.Length);
+ Array.Copy(ciphertext, offset, nonce, nonce.Length - record_iv_length, record_iv_length);
+ break;
+ case NONCE_DRAFT_CHACHA20_POLY1305:
+ TlsUtilities.WriteUint64(seqNo, nonce, nonce.Length - 8);
+ for (int i = 0; i < decryptImplicitNonce.Length; ++i)
+ {
+ nonce[i] ^= decryptImplicitNonce[i];
+ }
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
int ciphertextOffset = offset + record_iv_length;
diff --git a/crypto/src/crypto/tls/TlsDHUtilities.cs b/crypto/src/crypto/tls/TlsDHUtilities.cs
index f94163c6a..019d084e3 100644
--- a/crypto/src/crypto/tls/TlsDHUtilities.cs
+++ b/crypto/src/crypto/tls/TlsDHUtilities.cs
@@ -375,7 +375,7 @@ namespace Org.BouncyCastle.Crypto.Tls
case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
/*
- * draft-zauner-tls-aes-ocb-03
+ * draft-zauner-tls-aes-ocb-04
*/
case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB:
case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB:
diff --git a/crypto/src/crypto/tls/TlsEccUtilities.cs b/crypto/src/crypto/tls/TlsEccUtilities.cs
index 5a4c2b60e..706ebfd3c 100644
--- a/crypto/src/crypto/tls/TlsEccUtilities.cs
+++ b/crypto/src/crypto/tls/TlsEccUtilities.cs
@@ -261,7 +261,7 @@ namespace Org.BouncyCastle.Crypto.Tls
case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
/*
- * draft-zauner-tls-aes-ocb-03
+ * draft-zauner-tls-aes-ocb-04
*/
case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB:
case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB:
--
cgit 1.5.1
From 744747862b6d5f0357eec0ecddc3a51939f91c38 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Fri, 29 Apr 2016 17:25:09 +0700
Subject: Update various parameter classes following Java API
---
crypto/src/crypto/agreement/ECDHBasicAgreement.cs | 3 ++
crypto/src/crypto/agreement/ECDHCBasicAgreement.cs | 10 ++++---
crypto/src/crypto/agreement/ECMqvBasicAgreement.cs | 10 +++++--
crypto/src/crypto/parameters/DHParameters.cs | 2 +-
crypto/src/crypto/parameters/ECDomainParameters.cs | 9 ++----
.../src/crypto/parameters/MqvPrivateParameters.cs | 32 ++++++++++++++++++----
.../src/crypto/parameters/MqvPublicParameters.cs | 17 ++++++++----
crypto/src/crypto/tls/TlsDHUtilities.cs | 3 +-
crypto/src/crypto/tls/TlsEccUtilities.cs | 3 +-
9 files changed, 61 insertions(+), 28 deletions(-)
(limited to 'crypto/src')
diff --git a/crypto/src/crypto/agreement/ECDHBasicAgreement.cs b/crypto/src/crypto/agreement/ECDHBasicAgreement.cs
index c33f16f78..ca7b3fa3f 100644
--- a/crypto/src/crypto/agreement/ECDHBasicAgreement.cs
+++ b/crypto/src/crypto/agreement/ECDHBasicAgreement.cs
@@ -46,6 +46,9 @@ namespace Org.BouncyCastle.Crypto.Agreement
ICipherParameters pubKey)
{
ECPublicKeyParameters pub = (ECPublicKeyParameters) pubKey;
+ if (!pub.Parameters.Equals(privKey.Parameters))
+ throw new InvalidOperationException("ECDH public key has wrong domain parameters");
+
ECPoint P = pub.Q.Multiply(privKey.D).Normalize();
if (P.IsInfinity)
diff --git a/crypto/src/crypto/agreement/ECDHCBasicAgreement.cs b/crypto/src/crypto/agreement/ECDHCBasicAgreement.cs
index 89be7061e..1c9ae45f9 100644
--- a/crypto/src/crypto/agreement/ECDHCBasicAgreement.cs
+++ b/crypto/src/crypto/agreement/ECDHCBasicAgreement.cs
@@ -29,7 +29,7 @@ namespace Org.BouncyCastle.Crypto.Agreement
public class ECDHCBasicAgreement
: IBasicAgreement
{
- private ECPrivateKeyParameters key;
+ private ECPrivateKeyParameters privKey;
public virtual void Init(
ICipherParameters parameters)
@@ -39,12 +39,12 @@ namespace Org.BouncyCastle.Crypto.Agreement
parameters = ((ParametersWithRandom) parameters).Parameters;
}
- this.key = (ECPrivateKeyParameters)parameters;
+ this.privKey = (ECPrivateKeyParameters)parameters;
}
public virtual int GetFieldSize()
{
- return (key.Parameters.Curve.FieldSize + 7) / 8;
+ return (privKey.Parameters.Curve.FieldSize + 7) / 8;
}
public virtual BigInteger CalculateAgreement(
@@ -52,8 +52,10 @@ namespace Org.BouncyCastle.Crypto.Agreement
{
ECPublicKeyParameters pub = (ECPublicKeyParameters) pubKey;
ECDomainParameters parameters = pub.Parameters;
+ if (!parameters.Equals(privKey.Parameters))
+ throw new InvalidOperationException("ECDHC public key has wrong domain parameters");
- BigInteger hd = parameters.H.Multiply(key.D).Mod(parameters.N);
+ BigInteger hd = parameters.H.Multiply(privKey.D).Mod(parameters.N);
ECPoint P = pub.Q.Multiply(hd).Normalize();
diff --git a/crypto/src/crypto/agreement/ECMqvBasicAgreement.cs b/crypto/src/crypto/agreement/ECMqvBasicAgreement.cs
index f55ae46af..8d5cebb13 100644
--- a/crypto/src/crypto/agreement/ECMqvBasicAgreement.cs
+++ b/crypto/src/crypto/agreement/ECMqvBasicAgreement.cs
@@ -34,8 +34,12 @@ namespace Org.BouncyCastle.Crypto.Agreement
MqvPublicParameters pubParams = (MqvPublicParameters)pubKey;
ECPrivateKeyParameters staticPrivateKey = privParams.StaticPrivateKey;
+ ECDomainParameters parameters = staticPrivateKey.Parameters;
- ECPoint agreement = CalculateMqvAgreement(staticPrivateKey.Parameters, staticPrivateKey,
+ if (!parameters.Equals(pubParams.StaticPublicKey.Parameters))
+ throw new InvalidOperationException("ECMQV public key components have wrong domain parameters");
+
+ ECPoint agreement = CalculateMqvAgreement(parameters, staticPrivateKey,
privParams.EphemeralPrivateKey, privParams.EphemeralPublicKey,
pubParams.StaticPublicKey, pubParams.EphemeralPublicKey).Normalize();
@@ -61,8 +65,8 @@ namespace Org.BouncyCastle.Crypto.Agreement
ECCurve curve = parameters.Curve;
ECPoint[] points = new ECPoint[]{
- // The Q2U public key is optional
- ECAlgorithms.ImportPoint(curve, Q2U == null ? parameters.G.Multiply(d2U.D) : Q2U.Q),
+ // The Q2U public key is optional - but will be calculated for us if it wasn't present
+ ECAlgorithms.ImportPoint(curve, Q2U.Q),
ECAlgorithms.ImportPoint(curve, Q1V.Q),
ECAlgorithms.ImportPoint(curve, Q2V.Q)
};
diff --git a/crypto/src/crypto/parameters/DHParameters.cs b/crypto/src/crypto/parameters/DHParameters.cs
index 4258df5c5..bdea12432 100644
--- a/crypto/src/crypto/parameters/DHParameters.cs
+++ b/crypto/src/crypto/parameters/DHParameters.cs
@@ -162,7 +162,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
return Equals(other);
}
- protected bool Equals(
+ protected virtual bool Equals(
DHParameters other)
{
return p.Equals(other.p)
diff --git a/crypto/src/crypto/parameters/ECDomainParameters.cs b/crypto/src/crypto/parameters/ECDomainParameters.cs
index 619971a6c..9d1544771 100644
--- a/crypto/src/crypto/parameters/ECDomainParameters.cs
+++ b/crypto/src/crypto/parameters/ECDomainParameters.cs
@@ -93,14 +93,13 @@ namespace Org.BouncyCastle.Crypto.Parameters
return Equals(other);
}
- protected bool Equals(
+ protected virtual bool Equals(
ECDomainParameters other)
{
return curve.Equals(other.curve)
&& g.Equals(other.g)
&& n.Equals(other.n)
- && h.Equals(other.h)
- && Arrays.AreEqual(seed, other.seed);
+ && h.Equals(other.h);
}
public override int GetHashCode()
@@ -108,9 +107,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
return curve.GetHashCode()
^ g.GetHashCode()
^ n.GetHashCode()
- ^ h.GetHashCode()
- ^ Arrays.GetHashCode(seed);
+ ^ h.GetHashCode();
}
}
-
}
diff --git a/crypto/src/crypto/parameters/MqvPrivateParameters.cs b/crypto/src/crypto/parameters/MqvPrivateParameters.cs
index 4bf33e347..9159cac12 100644
--- a/crypto/src/crypto/parameters/MqvPrivateParameters.cs
+++ b/crypto/src/crypto/parameters/MqvPrivateParameters.cs
@@ -21,22 +21,42 @@ namespace Org.BouncyCastle.Crypto.Parameters
ECPrivateKeyParameters ephemeralPrivateKey,
ECPublicKeyParameters ephemeralPublicKey)
{
- this.staticPrivateKey = staticPrivateKey;
- this.ephemeralPrivateKey = ephemeralPrivateKey;
- this.ephemeralPublicKey = ephemeralPublicKey;
+ if (staticPrivateKey == null)
+ throw new ArgumentNullException("staticPrivateKey");
+ if (ephemeralPrivateKey == null)
+ throw new ArgumentNullException("ephemeralPrivateKey");
+
+ ECDomainParameters parameters = staticPrivateKey.Parameters;
+ if (!parameters.Equals(ephemeralPrivateKey.Parameters))
+ throw new ArgumentException("Static and ephemeral private keys have different domain parameters");
+
+ if (ephemeralPublicKey == null)
+ {
+ ephemeralPublicKey = new ECPublicKeyParameters(
+ parameters.G.Multiply(ephemeralPrivateKey.D),
+ parameters);
+ }
+ else if (!parameters.Equals(ephemeralPublicKey.Parameters))
+ {
+ throw new ArgumentException("Ephemeral public key has different domain parameters");
+ }
+
+ this.staticPrivateKey = staticPrivateKey;
+ this.ephemeralPrivateKey = ephemeralPrivateKey;
+ this.ephemeralPublicKey = ephemeralPublicKey;
}
- public ECPrivateKeyParameters StaticPrivateKey
+ public virtual ECPrivateKeyParameters StaticPrivateKey
{
get { return staticPrivateKey; }
}
- public ECPrivateKeyParameters EphemeralPrivateKey
+ public virtual ECPrivateKeyParameters EphemeralPrivateKey
{
get { return ephemeralPrivateKey; }
}
- public ECPublicKeyParameters EphemeralPublicKey
+ public virtual ECPublicKeyParameters EphemeralPublicKey
{
get { return ephemeralPublicKey; }
}
diff --git a/crypto/src/crypto/parameters/MqvPublicParameters.cs b/crypto/src/crypto/parameters/MqvPublicParameters.cs
index a0e273ac4..239afa321 100644
--- a/crypto/src/crypto/parameters/MqvPublicParameters.cs
+++ b/crypto/src/crypto/parameters/MqvPublicParameters.cs
@@ -8,20 +8,27 @@ namespace Org.BouncyCastle.Crypto.Parameters
private readonly ECPublicKeyParameters staticPublicKey;
private readonly ECPublicKeyParameters ephemeralPublicKey;
- public MqvPublicParameters(
+ public MqvPublicParameters(
ECPublicKeyParameters staticPublicKey,
ECPublicKeyParameters ephemeralPublicKey)
{
- this.staticPublicKey = staticPublicKey;
+ if (staticPublicKey == null)
+ throw new ArgumentNullException("staticPublicKey");
+ if (ephemeralPublicKey == null)
+ throw new ArgumentNullException("ephemeralPublicKey");
+ if (!staticPublicKey.Parameters.Equals(ephemeralPublicKey.Parameters))
+ throw new ArgumentException("Static and ephemeral public keys have different domain parameters");
+
+ this.staticPublicKey = staticPublicKey;
this.ephemeralPublicKey = ephemeralPublicKey;
- }
+ }
- public ECPublicKeyParameters StaticPublicKey
+ public virtual ECPublicKeyParameters StaticPublicKey
{
get { return staticPublicKey; }
}
- public ECPublicKeyParameters EphemeralPublicKey
+ public virtual ECPublicKeyParameters EphemeralPublicKey
{
get { return ephemeralPublicKey; }
}
diff --git a/crypto/src/crypto/tls/TlsDHUtilities.cs b/crypto/src/crypto/tls/TlsDHUtilities.cs
index 019d084e3..7a44670fd 100644
--- a/crypto/src/crypto/tls/TlsDHUtilities.cs
+++ b/crypto/src/crypto/tls/TlsDHUtilities.cs
@@ -391,7 +391,8 @@ namespace Org.BouncyCastle.Crypto.Tls
public static bool AreCompatibleParameters(DHParameters a, DHParameters b)
{
- return a.P.Equals(b.P) && a.G.Equals(b.G);
+ return a.P.Equals(b.P) && a.G.Equals(b.G)
+ && (a.Q == null || b.Q == null || a.Q.Equals(b.Q));
}
public static byte[] CalculateDHBasicAgreement(DHPublicKeyParameters publicKey,
diff --git a/crypto/src/crypto/tls/TlsEccUtilities.cs b/crypto/src/crypto/tls/TlsEccUtilities.cs
index 706ebfd3c..a5c8fa910 100644
--- a/crypto/src/crypto/tls/TlsEccUtilities.cs
+++ b/crypto/src/crypto/tls/TlsEccUtilities.cs
@@ -279,8 +279,7 @@ namespace Org.BouncyCastle.Crypto.Tls
public static bool AreOnSameCurve(ECDomainParameters a, ECDomainParameters b)
{
- // TODO Move to ECDomainParameters.Equals() or other utility method?
- return a.Curve.Equals(b.Curve) && a.G.Equals(b.G) && a.N.Equals(b.N) && a.H.Equals(b.H);
+ return a != null && a.Equals(b);
}
public static bool IsSupportedNamedCurve(int namedCurve)
--
cgit 1.5.1
From 03753505e9907e37e4a7364914cb15acd248c998 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Fri, 29 Apr 2016 18:36:57 +0700
Subject: Fix XML comment
---
crypto/src/crypto/generators/BCrypt.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'crypto/src')
diff --git a/crypto/src/crypto/generators/BCrypt.cs b/crypto/src/crypto/generators/BCrypt.cs
index b21a8671f..af8029a1b 100644
--- a/crypto/src/crypto/generators/BCrypt.cs
+++ b/crypto/src/crypto/generators/BCrypt.cs
@@ -14,8 +14,8 @@ namespace Org.BouncyCastle.Crypto.Generators
* "A Future-Adaptable Password Scheme" of Niels Provos and David Mazières,
* see: https://www.usenix.org/legacy/events/usenix99/provos/provos_html/node1.html.
* In contrast to the paper, the order of key setup and salt setup is reversed:
- * state <- ExpandKey(state, 0, key)
- * state <- ExpandKey(state, 0, salt)
+ * state <- ExpandKey(state, 0, key)
+ * state %lt;- ExpandKey(state, 0, salt)
* This corresponds to the OpenBSD reference implementation of Bcrypt.
*
* Note:
--
cgit 1.5.1
From 6e8dbc336ca82ff68bc59a846749ccc8d3ab176e Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Fri, 29 Apr 2016 18:44:27 +0700
Subject: Port of HKDF from Java API
---
crypto/BouncyCastle.Android.csproj | 2 +
crypto/BouncyCastle.csproj | 2 +
crypto/BouncyCastle.iOS.csproj | 2 +
crypto/crypto.csproj | 15 +
crypto/src/crypto/generators/HKDFBytesGenerator.cs | 153 ++++++++++
crypto/src/crypto/parameters/HKDFParameters.cs | 119 ++++++++
crypto/test/UnitTests.csproj | 1 +
crypto/test/src/crypto/test/HKDFGeneratorTest.cs | 310 +++++++++++++++++++++
crypto/test/src/crypto/test/RegressionTest.cs | 1 +
9 files changed, 605 insertions(+)
create mode 100644 crypto/src/crypto/generators/HKDFBytesGenerator.cs
create mode 100644 crypto/src/crypto/parameters/HKDFParameters.cs
create mode 100644 crypto/test/src/crypto/test/HKDFGeneratorTest.cs
(limited to 'crypto/src')
diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj
index 0b6f376bf..309298614 100644
--- a/crypto/BouncyCastle.Android.csproj
+++ b/crypto/BouncyCastle.Android.csproj
@@ -639,6 +639,7 @@
+
@@ -668,6 +669,7 @@
+
diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj
index 5f0a58ad8..90c067007 100644
--- a/crypto/BouncyCastle.csproj
+++ b/crypto/BouncyCastle.csproj
@@ -633,6 +633,7 @@
+
@@ -662,6 +663,7 @@
+
diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj
index eeaf3bb12..88fb1747e 100644
--- a/crypto/BouncyCastle.iOS.csproj
+++ b/crypto/BouncyCastle.iOS.csproj
@@ -634,6 +634,7 @@
+
@@ -663,6 +664,7 @@
+
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index 6ab8faf50..580aa7390 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -3793,6 +3793,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
+
+
+
= 256)
+ {
+ throw new DataLengthException(
+ "HKDF cannot generate more than 255 blocks of HashLen size");
+ }
+ // special case for T(0): T(0) is empty, so no update
+ if (generatedBytes != 0)
+ {
+ hMacHash.BlockUpdate(currentT, 0, hashLen);
+ }
+ hMacHash.BlockUpdate(info, 0, info.Length);
+ hMacHash.Update((byte)n);
+ hMacHash.DoFinal(currentT, 0);
+ }
+
+ public virtual IDigest Digest
+ {
+ get { return hMacHash.GetUnderlyingDigest(); }
+ }
+
+ public virtual int GenerateBytes(byte[] output, int outOff, int len)
+ {
+ if (generatedBytes + len > 255 * hashLen)
+ {
+ throw new DataLengthException(
+ "HKDF may only be used for 255 * HashLen bytes of output");
+ }
+
+ if (generatedBytes % hashLen == 0)
+ {
+ ExpandNext();
+ }
+
+ // copy what is left in the currentT (1..hash
+ int toGenerate = len;
+ int posInT = generatedBytes % hashLen;
+ int leftInT = hashLen - generatedBytes % hashLen;
+ int toCopy = System.Math.Min(leftInT, toGenerate);
+ Array.Copy(currentT, posInT, output, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+
+ while (toGenerate > 0)
+ {
+ ExpandNext();
+ toCopy = System.Math.Min(hashLen, toGenerate);
+ Array.Copy(currentT, 0, output, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+ }
+
+ return len;
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/HKDFParameters.cs b/crypto/src/crypto/parameters/HKDFParameters.cs
new file mode 100644
index 000000000..6d1465e4c
--- /dev/null
+++ b/crypto/src/crypto/parameters/HKDFParameters.cs
@@ -0,0 +1,119 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ /**
+ * Parameter class for the HkdfBytesGenerator class.
+ */
+ public class HkdfParameters
+ : IDerivationParameters
+ {
+ private readonly byte[] ikm;
+ private readonly bool skipExpand;
+ private readonly byte[] salt;
+ private readonly byte[] info;
+
+ private HkdfParameters(byte[] ikm, bool skip, byte[] salt, byte[] info)
+ {
+ if (ikm == null)
+ throw new ArgumentNullException("ikm");
+
+ this.ikm = Arrays.Clone(ikm);
+ this.skipExpand = skip;
+
+ if (salt == null || salt.Length == 0)
+ {
+ this.salt = null;
+ }
+ else
+ {
+ this.salt = Arrays.Clone(salt);
+ }
+
+ if (info == null)
+ {
+ this.info = new byte[0];
+ }
+ else
+ {
+ this.info = Arrays.Clone(info);
+ }
+ }
+
+ /**
+ * Generates parameters for HKDF, specifying both the optional salt and
+ * optional info. Step 1: Extract won't be skipped.
+ *
+ * @param ikm the input keying material or seed
+ * @param salt the salt to use, may be null for a salt for hashLen zeros
+ * @param info the info to use, may be null for an info field of zero bytes
+ */
+ public HkdfParameters(byte[] ikm, byte[] salt, byte[] info)
+ : this(ikm, false, salt, info)
+ {
+ }
+
+ /**
+ * Factory method that makes the HKDF skip the extract part of the key
+ * derivation function.
+ *
+ * @param ikm the input keying material or seed, directly used for step 2:
+ * Expand
+ * @param info the info to use, may be null for an info field of zero bytes
+ * @return HKDFParameters that makes the implementation skip step 1
+ */
+ public static HkdfParameters SkipExtractParameters(byte[] ikm, byte[] info)
+ {
+ return new HkdfParameters(ikm, true, null, info);
+ }
+
+ public static HkdfParameters DefaultParameters(byte[] ikm)
+ {
+ return new HkdfParameters(ikm, false, null, null);
+ }
+
+ /**
+ * Returns the input keying material or seed.
+ *
+ * @return the keying material
+ */
+ public virtual byte[] GetIkm()
+ {
+ return Arrays.Clone(ikm);
+ }
+
+ /**
+ * Returns if step 1: extract has to be skipped or not
+ *
+ * @return true for skipping, false for no skipping of step 1
+ */
+ public virtual bool SkipExtract
+ {
+ get { return skipExpand; }
+ }
+
+ /**
+ * Returns the salt, or null if the salt should be generated as a byte array
+ * of HashLen zeros.
+ *
+ * @return the salt, or null
+ */
+ public virtual byte[] GetSalt()
+ {
+ return Arrays.Clone(salt);
+ }
+
+ /**
+ * Returns the info field, which may be empty (null is converted to empty).
+ *
+ * @return the info field, never null
+ */
+ public virtual byte[] GetInfo()
+ {
+ return Arrays.Clone(info);
+ }
+ }
+}
diff --git a/crypto/test/UnitTests.csproj b/crypto/test/UnitTests.csproj
index d3250d89a..b4c53092b 100644
--- a/crypto/test/UnitTests.csproj
+++ b/crypto/test/UnitTests.csproj
@@ -193,6 +193,7 @@
+
diff --git a/crypto/test/src/crypto/test/HKDFGeneratorTest.cs b/crypto/test/src/crypto/test/HKDFGeneratorTest.cs
new file mode 100644
index 000000000..d6e2149df
--- /dev/null
+++ b/crypto/test/src/crypto/test/HKDFGeneratorTest.cs
@@ -0,0 +1,310 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+ /**
+ * HKDF tests - vectors from RFC 5869, + 2 more, 101 and 102
+ */
+ [TestFixture]
+ public class HkdfGeneratorTest
+ : SimpleTest
+ {
+ public HkdfGeneratorTest()
+ {
+ }
+
+ private void CompareOkm(int test, byte[] calculatedOkm, byte[] testOkm)
+ {
+ if (!AreEqual(calculatedOkm, testOkm))
+ {
+ Fail("HKDF failed generator test " + test);
+ }
+ }
+
+ public override void PerformTest()
+ {
+ {
+ // === A.1. Test Case 1 - Basic test case with SHA-256 ===
+
+ IDigest hash = new Sha256Digest();
+ byte[] ikm = Hex.Decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
+ byte[] salt = Hex.Decode("000102030405060708090a0b0c");
+ byte[] info = Hex.Decode("f0f1f2f3f4f5f6f7f8f9");
+ int l = 42;
+ byte[] okm = new byte[l];
+
+ HkdfParameters parameters = new HkdfParameters(ikm, salt, info);
+
+ HkdfBytesGenerator hkdf = new HkdfBytesGenerator(hash);
+ hkdf.Init(parameters);
+ hkdf.GenerateBytes(okm, 0, l);
+
+ CompareOkm(1, okm, Hex.Decode(
+ "3cb25f25faacd57a90434f64d0362f2a" +
+ "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" +
+ "34007208d5b887185865"));
+ }
+
+ // === A.2. Test Case 2 - Test with SHA-256 and longer inputs/outputs
+ // ===
+ {
+ IDigest hash = new Sha256Digest();
+ byte[] ikm = Hex.Decode("000102030405060708090a0b0c0d0e0f"
+ + "101112131415161718191a1b1c1d1e1f"
+ + "202122232425262728292a2b2c2d2e2f"
+ + "303132333435363738393a3b3c3d3e3f"
+ + "404142434445464748494a4b4c4d4e4f");
+ byte[] salt = Hex.Decode("606162636465666768696a6b6c6d6e6f"
+ + "707172737475767778797a7b7c7d7e7f"
+ + "808182838485868788898a8b8c8d8e8f"
+ + "909192939495969798999a9b9c9d9e9f"
+ + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf");
+ byte[] info = Hex.Decode("b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
+ int l = 82;
+ byte[] okm = new byte[l];
+
+ HkdfParameters parameters = new HkdfParameters(ikm, salt, info);
+
+ HkdfBytesGenerator hkdf = new HkdfBytesGenerator(hash);
+ hkdf.Init(parameters);
+ hkdf.GenerateBytes(okm, 0, l);
+
+ CompareOkm(2, okm, Hex.Decode(
+ "b11e398dc80327a1c8e7f78c596a4934" +
+ "4f012eda2d4efad8a050cc4c19afa97c" +
+ "59045a99cac7827271cb41c65e590e09" +
+ "da3275600c2f09b8367793a9aca3db71" +
+ "cc30c58179ec3e87c14c01d5c1f3434f" +
+ "1d87"));
+ }
+
+ {
+ // === A.3. Test Case 3 - Test with SHA-256 and zero-length
+ // salt/info ===
+
+ // setting salt to an empty byte array means that the salt is set to
+ // HashLen zero valued bytes
+ // setting info to null generates an empty byte array as info
+ // structure
+
+ IDigest hash = new Sha256Digest();
+ byte[] ikm = Hex.Decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
+ byte[] salt = new byte[0];
+ byte[] info = null;
+ int l = 42;
+ byte[] okm = new byte[l];
+
+ HkdfParameters parameters = new HkdfParameters(ikm, salt, info);
+
+ HkdfBytesGenerator hkdf = new HkdfBytesGenerator(hash);
+ hkdf.Init(parameters);
+ hkdf.GenerateBytes(okm, 0, l);
+
+ CompareOkm(3, okm, Hex.Decode(
+ "8da4e775a563c18f715f802a063c5a31" +
+ "b8a11f5c5ee1879ec3454e5f3c738d2d" +
+ "9d201395faa4b61a96c8"));
+ }
+
+ {
+ // === A.4. Test Case 4 - Basic test case with SHA-1 ===
+
+ IDigest hash = new Sha1Digest();
+ byte[] ikm = Hex.Decode("0b0b0b0b0b0b0b0b0b0b0b");
+ byte[] salt = Hex.Decode("000102030405060708090a0b0c");
+ byte[] info = Hex.Decode("f0f1f2f3f4f5f6f7f8f9");
+ int l = 42;
+ byte[] okm = new byte[l];
+
+ HkdfParameters parameters = new HkdfParameters(ikm, salt, info);
+
+ HkdfBytesGenerator hkdf = new HkdfBytesGenerator(hash);
+ hkdf.Init(parameters);
+ hkdf.GenerateBytes(okm, 0, l);
+
+ CompareOkm(4, okm, Hex.Decode(
+ "085a01ea1b10f36933068b56efa5ad81" +
+ "a4f14b822f5b091568a9cdd4f155fda2" +
+ "c22e422478d305f3f896"));
+ }
+
+ // === A.5. Test Case 5 - Test with SHA-1 and longer inputs/outputs ===
+ {
+ IDigest hash = new Sha1Digest();
+ byte[] ikm = Hex.Decode("000102030405060708090a0b0c0d0e0f"
+ + "101112131415161718191a1b1c1d1e1f"
+ + "202122232425262728292a2b2c2d2e2f"
+ + "303132333435363738393a3b3c3d3e3f"
+ + "404142434445464748494a4b4c4d4e4f");
+ byte[] salt = Hex.Decode("606162636465666768696a6b6c6d6e6f"
+ + "707172737475767778797a7b7c7d7e7f"
+ + "808182838485868788898a8b8c8d8e8f"
+ + "909192939495969798999a9b9c9d9e9f"
+ + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf");
+ byte[] info = Hex.Decode("b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
+ int l = 82;
+ byte[] okm = new byte[l];
+
+ HkdfParameters parameters = new HkdfParameters(ikm, salt, info);
+
+ HkdfBytesGenerator hkdf = new HkdfBytesGenerator(hash);
+ hkdf.Init(parameters);
+ hkdf.GenerateBytes(okm, 0, l);
+
+ CompareOkm(5, okm, Hex.Decode(
+ "0bd770a74d1160f7c9f12cd5912a06eb" +
+ "ff6adcae899d92191fe4305673ba2ffe" +
+ "8fa3f1a4e5ad79f3f334b3b202b2173c" +
+ "486ea37ce3d397ed034c7f9dfeb15c5e" +
+ "927336d0441f4c4300e2cff0d0900b52" +
+ "d3b4"));
+ }
+
+ {
+ // === A.6. Test Case 6 - Test with SHA-1 and zero-length salt/info
+ // ===
+
+ // setting salt to null should generate a new salt of HashLen zero
+ // valued bytes
+
+ IDigest hash = new Sha1Digest();
+ byte[] ikm = Hex.Decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
+ byte[] salt = null;
+ byte[] info = new byte[0];
+ int l = 42;
+ byte[] okm = new byte[l];
+
+ HkdfParameters parameters = new HkdfParameters(ikm, salt, info);
+
+ HkdfBytesGenerator hkdf = new HkdfBytesGenerator(hash);
+ hkdf.Init(parameters);
+ hkdf.GenerateBytes(okm, 0, l);
+
+ CompareOkm(6, okm, Hex.Decode(
+ "0ac1af7002b3d761d1e55298da9d0506" +
+ "b9ae52057220a306e07b6b87e8df21d0" +
+ "ea00033de03984d34918"));
+ }
+
+ {
+ // === A.7. Test Case 7 - Test with SHA-1, salt not provided,
+ // zero-length info ===
+ // (salt defaults to HashLen zero octets)
+
+ // this test is identical to test 6 in all ways bar the IKM value
+
+ IDigest hash = new Sha1Digest();
+ byte[] ikm = Hex.Decode("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c");
+ byte[] salt = null;
+ byte[] info = new byte[0];
+ int l = 42;
+ byte[] okm = new byte[l];
+
+ HkdfParameters parameters = new HkdfParameters(ikm, salt, info);
+
+ HkdfBytesGenerator hkdf = new HkdfBytesGenerator(hash);
+ hkdf.Init(parameters);
+ hkdf.GenerateBytes(okm, 0, l);
+
+ CompareOkm(7, okm, Hex.Decode(
+ "2c91117204d745f3500d636a62f64f0a" +
+ "b3bae548aa53d423b0d1f27ebba6f5e5" +
+ "673a081d70cce7acfc48"));
+ }
+
+ {
+ // === A.101. Additional Test Case - Test with SHA-1, skipping extract
+ // zero-length info ===
+ // (salt defaults to HashLen zero octets)
+
+ // this test is identical to test 7 in all ways bar the IKM value
+ // which is set to the PRK value
+
+ IDigest hash = new Sha1Digest();
+ byte[] ikm = Hex.Decode("2adccada18779e7c2077ad2eb19d3f3e731385dd");
+ byte[] info = new byte[0];
+ int l = 42;
+ byte[] okm = new byte[l];
+
+ HkdfParameters parameters = HkdfParameters.SkipExtractParameters(ikm, info);
+
+ HkdfBytesGenerator hkdf = new HkdfBytesGenerator(hash);
+ hkdf.Init(parameters);
+ hkdf.GenerateBytes(okm, 0, l);
+
+ CompareOkm(101, okm, Hex.Decode(
+ "2c91117204d745f3500d636a62f64f0a" +
+ "b3bae548aa53d423b0d1f27ebba6f5e5" +
+ "673a081d70cce7acfc48"));
+ }
+
+ {
+ // === A.102. Additional Test Case - Test with SHA-1, maximum output ===
+ // (salt defaults to HashLen zero octets)
+
+ // this test is identical to test 7 in all ways bar the IKM value
+
+ IDigest hash = new Sha1Digest();
+ byte[] ikm = Hex.Decode("2adccada18779e7c2077ad2eb19d3f3e731385dd");
+ byte[] info = new byte[0];
+ int l = 255 * hash.GetDigestSize();
+ byte[] okm = new byte[l];
+
+ HkdfParameters parameters = HkdfParameters.SkipExtractParameters(ikm, info);
+
+ HkdfBytesGenerator hkdf = new HkdfBytesGenerator(hash);
+ hkdf.Init(parameters);
+ hkdf.GenerateBytes(okm, 0, l);
+
+ int zeros = 0;
+ for (int i = 0; i < hash.GetDigestSize(); i++)
+ {
+ if (okm[i] == 0)
+ {
+ zeros++;
+ }
+ }
+
+ if (zeros == hash.GetDigestSize())
+ {
+ Fail("HKDF failed generator test " + 102);
+ }
+ }
+ }
+
+ public override string Name
+ {
+ get { return "HKDF"; }
+ }
+
+ public static void Main(string[] args)
+ {
+ RunTest(new HkdfGeneratorTest());
+ }
+
+ [Test]
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
+}
diff --git a/crypto/test/src/crypto/test/RegressionTest.cs b/crypto/test/src/crypto/test/RegressionTest.cs
index 3611e4e63..ba6c341d4 100644
--- a/crypto/test/src/crypto/test/RegressionTest.cs
+++ b/crypto/test/src/crypto/test/RegressionTest.cs
@@ -90,6 +90,7 @@ namespace Org.BouncyCastle.Crypto.Tests
new Kdf1GeneratorTest(),
new Kdf2GeneratorTest(),
new Mgf1GeneratorTest(),
+ new HkdfGeneratorTest(),
new DHKekGeneratorTest(),
new ECDHKekGeneratorTest(),
new ShortenedDigestTest(),
--
cgit 1.5.1
From d80e68ea9c605433d5a3456d5c2c07476a1eaac2 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Fri, 29 Apr 2016 19:04:51 +0700
Subject: Added IsCertification methods.
---
crypto/src/openpgp/PgpSignature.cs | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
(limited to 'crypto/src')
diff --git a/crypto/src/openpgp/PgpSignature.cs b/crypto/src/openpgp/PgpSignature.cs
index 3bb6f2f0e..c8c541bef 100644
--- a/crypto/src/openpgp/PgpSignature.cs
+++ b/crypto/src/openpgp/PgpSignature.cs
@@ -84,6 +84,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
get { return sigPck.HashAlgorithm; }
}
+ /// Return true if this signature represents a certification.
+ public bool IsCertification()
+ {
+ return IsCertification(SignatureType);
+ }
+
public void InitVerify(
PgpPublicKey pubKey)
{
@@ -418,5 +424,24 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
throw new PgpException("exception preparing key.", e);
}
}
+
+ ///
+ /// Return true if the passed in signature type represents a certification, false if the signature type is not.
+ ///
+ ///
+ /// true if signatureType is a certification, false otherwise.
+ public static bool IsCertification(int signatureType)
+ {
+ switch (signatureType)
+ {
+ case DefaultCertification:
+ case NoCertification:
+ case CasualCertification:
+ case PositiveCertification:
+ return true;
+ default:
+ return false;
+ }
+ }
}
}
--
cgit 1.5.1
From bf135f987ab9b636bc583e7589c3270394d4b268 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Fri, 29 Apr 2016 21:53:39 +0700
Subject: Support GetInstance from byte[]
---
crypto/src/asn1/DerBitString.cs | 11 +++++++++++
crypto/test/src/asn1/test/BitStringTest.cs | 16 ++++++++++++++++
2 files changed, 27 insertions(+)
(limited to 'crypto/src')
diff --git a/crypto/src/asn1/DerBitString.cs b/crypto/src/asn1/DerBitString.cs
index a3c2cee01..26adc575b 100644
--- a/crypto/src/asn1/DerBitString.cs
+++ b/crypto/src/asn1/DerBitString.cs
@@ -28,6 +28,17 @@ namespace Org.BouncyCastle.Asn1
{
return (DerBitString) obj;
}
+ if (obj is byte[])
+ {
+ try
+ {
+ return (DerBitString)FromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new ArgumentException("encoding error in GetInstance: " + e.ToString());
+ }
+ }
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
diff --git a/crypto/test/src/asn1/test/BitStringTest.cs b/crypto/test/src/asn1/test/BitStringTest.cs
index f2ae3de97..35b7811bc 100644
--- a/crypto/test/src/asn1/test/BitStringTest.cs
+++ b/crypto/test/src/asn1/test/BitStringTest.cs
@@ -86,10 +86,26 @@ namespace Org.BouncyCastle.Asn1.Tests
//Fail("failed DL check");
Fail("failed BER check");
}
+ IAsn1String dl = BerBitString.GetInstance(dlData);
+
+ //IsTrue("DL test failed", dl is DLBitString);
+ IsTrue("BER test failed", dl is BerBitString);
if (!Arrays.AreEqual(derData, Asn1Object.FromByteArray(dlData).GetDerEncoded()))
{
Fail("failed DER check");
}
+ // TODO This test isn't applicable until we get the DL variants
+ //try
+ //{
+ // DerBitString.GetInstance(dlData);
+ // Fail("no exception");
+ //}
+ //catch (ArgumentException e)
+ //{
+ // // ignore
+ //}
+ IAsn1String der = DerBitString.GetInstance(derData);
+ IsTrue("DER test failed", der is DerBitString);
}
public override void PerformTest()
--
cgit 1.5.1
From a803651ae8ece3cb203bdaaee0cffef8f43689c7 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Sat, 7 May 2016 15:12:30 +0700
Subject: Update ECDomainParameters GetHashCode
---
crypto/src/crypto/parameters/ECDomainParameters.cs | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
(limited to 'crypto/src')
diff --git a/crypto/src/crypto/parameters/ECDomainParameters.cs b/crypto/src/crypto/parameters/ECDomainParameters.cs
index 9d1544771..732fbdfa4 100644
--- a/crypto/src/crypto/parameters/ECDomainParameters.cs
+++ b/crypto/src/crypto/parameters/ECDomainParameters.cs
@@ -104,10 +104,14 @@ namespace Org.BouncyCastle.Crypto.Parameters
public override int GetHashCode()
{
- return curve.GetHashCode()
- ^ g.GetHashCode()
- ^ n.GetHashCode()
- ^ h.GetHashCode();
+ int hc = curve.GetHashCode();
+ hc *= 37;
+ hc ^= g.GetHashCode();
+ hc *= 37;
+ hc ^= n.GetHashCode();
+ hc *= 37;
+ hc ^= h.GetHashCode();
+ return hc;
}
}
}
--
cgit 1.5.1
From 00904716e6219662a4f8c20d2d116bdc193e8070 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Sat, 7 May 2016 15:49:22 +0700
Subject: Port of improved app data splitting support from Java
---
crypto/src/crypto/tls/TlsProtocol.cs | 41 ++++++++++++++++++++++++++++++------
1 file changed, 35 insertions(+), 6 deletions(-)
(limited to 'crypto/src')
diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs
index 6e3bbbbdf..6d5c93f40 100644
--- a/crypto/src/crypto/tls/TlsProtocol.cs
+++ b/crypto/src/crypto/tls/TlsProtocol.cs
@@ -33,6 +33,13 @@ namespace Org.BouncyCastle.Crypto.Tls
protected const short CS_SERVER_FINISHED = 15;
protected const short CS_END = 16;
+ /*
+ * Different modes to handle the known IV weakness
+ */
+ protected const short ADS_MODE_1_Nsub1 = 0; // 1/n-1 record splitting
+ protected const short ADS_MODE_0_N = 1; // 0/n record splitting
+ protected const short ADS_MODE_0_N_FIRSTONLY = 2; // 0/n record splitting on first data fragment only
+
/*
* Queues for data from some protocols.
*/
@@ -52,7 +59,8 @@ namespace Org.BouncyCastle.Crypto.Tls
private volatile bool mClosed = false;
private volatile bool mFailedWithError = false;
private volatile bool mAppDataReady = false;
- private volatile bool mSplitApplicationDataRecords = true;
+ private volatile bool mAppDataSplitEnabled = true;
+ private volatile int mAppDataSplitMode = ADS_MODE_1_Nsub1;
private byte[] mExpectedVerifyData = null;
protected TlsSession mTlsSession = null;
@@ -175,7 +183,7 @@ namespace Org.BouncyCastle.Crypto.Tls
{
this.mRecordStream.FinaliseHandshake();
- this.mSplitApplicationDataRecords = !TlsUtilities.IsTlsV11(Context);
+ this.mAppDataSplitEnabled = !TlsUtilities.IsTlsV11(Context);
/*
* If this was an initial handshake, we are now ready to send and receive application data.
@@ -556,16 +564,29 @@ namespace Org.BouncyCastle.Crypto.Tls
* NOTE: Actually, implementations appear to have settled on 1/n-1 record splitting.
*/
- if (this.mSplitApplicationDataRecords)
+ if (this.mAppDataSplitEnabled)
{
/*
* Protect against known IV attack!
*
* DO NOT REMOVE THIS CODE, EXCEPT YOU KNOW EXACTLY WHAT YOU ARE DOING HERE.
*/
- SafeWriteRecord(ContentType.application_data, buf, offset, 1);
- ++offset;
- --len;
+ switch (mAppDataSplitMode)
+ {
+ case ADS_MODE_0_N:
+ SafeWriteRecord(ContentType.application_data, TlsUtilities.EmptyBytes, 0, 0);
+ break;
+ case ADS_MODE_0_N_FIRSTONLY:
+ this.mAppDataSplitEnabled = false;
+ SafeWriteRecord(ContentType.application_data, TlsUtilities.EmptyBytes, 0, 0);
+ break;
+ case ADS_MODE_1_Nsub1:
+ default:
+ SafeWriteRecord(ContentType.application_data, buf, offset, 1);
+ ++offset;
+ --len;
+ break;
+ }
}
if (len > 0)
@@ -579,6 +600,14 @@ namespace Org.BouncyCastle.Crypto.Tls
}
}
+ protected virtual void SetAppDataSplitMode(int appDataSplitMode)
+ {
+ if (appDataSplitMode < ADS_MODE_1_Nsub1 || appDataSplitMode > ADS_MODE_0_N_FIRSTONLY)
+ throw new ArgumentException("Illegal appDataSplitMode mode: " + appDataSplitMode, "appDataSplitMode");
+
+ this.mAppDataSplitMode = appDataSplitMode;
+ }
+
protected virtual void WriteHandshakeMessage(byte[] buf, int off, int len)
{
while (len > 0)
--
cgit 1.5.1
From 7cd18b2318fd14166d4e7af4b32852a41cf64e64 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Sat, 7 May 2016 18:33:54 +0700
Subject: Add CertificateType constants to (D)TLS
---
crypto/BouncyCastle.Android.csproj | 1 +
crypto/BouncyCastle.csproj | 1 +
crypto/BouncyCastle.iOS.csproj | 1 +
crypto/crypto.csproj | 5 +++++
crypto/src/crypto/tls/CertificateType.cs | 18 ++++++++++++++++++
5 files changed, 26 insertions(+)
create mode 100644 crypto/src/crypto/tls/CertificateType.cs
(limited to 'crypto/src')
diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj
index 309298614..13ca4f05c 100644
--- a/crypto/BouncyCastle.Android.csproj
+++ b/crypto/BouncyCastle.Android.csproj
@@ -963,6 +963,7 @@
+
diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj
index 90c067007..f72c9c527 100644
--- a/crypto/BouncyCastle.csproj
+++ b/crypto/BouncyCastle.csproj
@@ -957,6 +957,7 @@
+
diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj
index 88fb1747e..b3bf7b4fa 100644
--- a/crypto/BouncyCastle.iOS.csproj
+++ b/crypto/BouncyCastle.iOS.csproj
@@ -958,6 +958,7 @@
+
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index 580aa7390..fcb52bb20 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -4673,6 +4673,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
+
Date: Sun, 15 May 2016 06:02:10 +1000
Subject: removed obsolete annotation
---
crypto/src/crypto/generators/Pkcs12ParametersGenerator.cs | 2 --
crypto/src/crypto/generators/Pkcs5S1ParametersGenerator.cs | 2 --
crypto/src/crypto/generators/Pkcs5S2ParametersGenerator.cs | 2 --
3 files changed, 6 deletions(-)
(limited to 'crypto/src')
diff --git a/crypto/src/crypto/generators/Pkcs12ParametersGenerator.cs b/crypto/src/crypto/generators/Pkcs12ParametersGenerator.cs
index cbbfd1b3b..85543a038 100644
--- a/crypto/src/crypto/generators/Pkcs12ParametersGenerator.cs
+++ b/crypto/src/crypto/generators/Pkcs12ParametersGenerator.cs
@@ -163,7 +163,6 @@ namespace Org.BouncyCastle.Crypto.Generators
* @param keySize the size of the key we want (in bits)
* @return a KeyParameter object.
*/
- [Obsolete("Use version with 'algorithm' parameter")]
public override ICipherParameters GenerateDerivedParameters(
int keySize)
{
@@ -194,7 +193,6 @@ namespace Org.BouncyCastle.Crypto.Generators
* @param ivSize the size of the iv we want (in bits)
* @return a ParametersWithIV object.
*/
- [Obsolete("Use version with 'algorithm' parameter")]
public override ICipherParameters GenerateDerivedParameters(
int keySize,
int ivSize)
diff --git a/crypto/src/crypto/generators/Pkcs5S1ParametersGenerator.cs b/crypto/src/crypto/generators/Pkcs5S1ParametersGenerator.cs
index 8586e1ca9..9b39a5f42 100644
--- a/crypto/src/crypto/generators/Pkcs5S1ParametersGenerator.cs
+++ b/crypto/src/crypto/generators/Pkcs5S1ParametersGenerator.cs
@@ -62,7 +62,6 @@ namespace Org.BouncyCastle.Crypto.Generators
* @return a KeyParameter object.
* @exception ArgumentException if the key length larger than the base hash size.
*/
- [Obsolete("Use version with 'algorithm' parameter")]
public override ICipherParameters GenerateDerivedParameters(
int keySize)
{
@@ -96,7 +95,6 @@ namespace Org.BouncyCastle.Crypto.Generators
* @return a ParametersWithIV object.
* @exception ArgumentException if keySize + ivSize is larger than the base hash size.
*/
- [Obsolete("Use version with 'algorithm' parameter")]
public override ICipherParameters GenerateDerivedParameters(
int keySize,
int ivSize)
diff --git a/crypto/src/crypto/generators/Pkcs5S2ParametersGenerator.cs b/crypto/src/crypto/generators/Pkcs5S2ParametersGenerator.cs
index 10352abbc..0b0caa057 100644
--- a/crypto/src/crypto/generators/Pkcs5S2ParametersGenerator.cs
+++ b/crypto/src/crypto/generators/Pkcs5S2ParametersGenerator.cs
@@ -106,7 +106,6 @@ namespace Org.BouncyCastle.Crypto.Generators
* @param keySize the size of the key we want (in bits)
* @return a KeyParameter object.
*/
- [Obsolete("Use version with 'algorithm' parameter")]
public override ICipherParameters GenerateDerivedParameters(
int keySize)
{
@@ -133,7 +132,6 @@ namespace Org.BouncyCastle.Crypto.Generators
* @param ivSize the size of the iv we want (in bits)
* @return a ParametersWithIV object.
*/
- [Obsolete("Use version with 'algorithm' parameter")]
public override ICipherParameters GenerateDerivedParameters(
int keySize,
int ivSize)
--
cgit 1.5.1
From 3d68923d4ecb7379aebcdba65615524997460d02 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Thu, 26 May 2016 20:58:36 +0700
Subject: Improve ZInputStream/ZOutputStream constructors
---
crypto/src/util/zlib/ZInputStream.cs | 47 ++++++++++++++++++++++++++++-------
crypto/src/util/zlib/ZOutputStream.cs | 28 ++++++++++++++++-----
2 files changed, 60 insertions(+), 15 deletions(-)
(limited to 'crypto/src')
diff --git a/crypto/src/util/zlib/ZInputStream.cs b/crypto/src/util/zlib/ZInputStream.cs
index 4b7351555..434fe95c8 100644
--- a/crypto/src/util/zlib/ZInputStream.cs
+++ b/crypto/src/util/zlib/ZInputStream.cs
@@ -42,9 +42,16 @@ namespace Org.BouncyCastle.Utilities.Zlib
public class ZInputStream
: Stream
{
- private const int BufferSize = 512;
+ private static ZStream GetDefaultZStream(bool nowrap)
+ {
+ ZStream z = new ZStream();
+ z.inflateInit(nowrap);
+ return z;
+ }
+
+ private const int BufferSize = 512;
- protected ZStream z = new ZStream();
+ protected ZStream z;
protected int flushLevel = JZlib.Z_NO_FLUSH;
// TODO Allow custom buf
protected byte[] buf = new byte[BufferSize];
@@ -62,24 +69,46 @@ namespace Org.BouncyCastle.Utilities.Zlib
}
public ZInputStream(Stream input, bool nowrap)
+ : this(input, GetDefaultZStream(nowrap))
+ {
+ }
+
+ public ZInputStream(Stream input, ZStream z)
+ : base()
{
Debug.Assert(input.CanRead);
- this.input = input;
- this.z.inflateInit(nowrap);
- this.compress = false;
- this.z.next_in = buf;
+ if (z == null)
+ {
+ z = new ZStream();
+ }
+
+ if (z.istate == null && z.dstate == null)
+ {
+ z.inflateInit();
+ }
+
+ this.input = input;
+ this.compress = (z.istate == null);
+ this.z = z;
+ this.z.next_in = buf;
this.z.next_in_index = 0;
this.z.avail_in = 0;
}
- public ZInputStream(Stream input, int level)
+ public ZInputStream(Stream input, int level)
+ : this(input, level, false)
+ {
+ }
+
+ public ZInputStream(Stream input, int level, bool nowrap)
{
Debug.Assert(input.CanRead);
this.input = input;
- this.z.deflateInit(level);
- this.compress = true;
+ this.compress = true;
+ this.z = new ZStream();
+ this.z.deflateInit(level, nowrap);
this.z.next_in = buf;
this.z.next_in_index = 0;
this.z.avail_in = 0;
diff --git a/crypto/src/util/zlib/ZOutputStream.cs b/crypto/src/util/zlib/ZOutputStream.cs
index d9f005f69..1633b2d8f 100644
--- a/crypto/src/util/zlib/ZOutputStream.cs
+++ b/crypto/src/util/zlib/ZOutputStream.cs
@@ -42,7 +42,14 @@ namespace Org.BouncyCastle.Utilities.Zlib
public class ZOutputStream
: Stream
{
- private const int BufferSize = 512;
+ private static ZStream GetDefaultZStream(bool nowrap)
+ {
+ ZStream z = new ZStream();
+ z.inflateInit(nowrap);
+ return z;
+ }
+
+ private const int BufferSize = 512;
protected ZStream z;
protected int flushLevel = JZlib.Z_NO_FLUSH;
@@ -55,9 +62,14 @@ namespace Org.BouncyCastle.Utilities.Zlib
protected bool closed;
public ZOutputStream(Stream output)
- : this(output, null)
- {
- }
+ : this(output, false)
+ {
+ }
+
+ public ZOutputStream(Stream output, bool nowrap)
+ : this(output, GetDefaultZStream(nowrap))
+ {
+ }
public ZOutputStream(Stream output, ZStream z)
: base()
@@ -67,12 +79,16 @@ namespace Org.BouncyCastle.Utilities.Zlib
if (z == null)
{
z = new ZStream();
+ }
+
+ if (z.istate == null && z.dstate == null)
+ {
z.inflateInit();
}
this.output = output;
+ this.compress = (z.istate == null);
this.z = z;
- this.compress = false;
}
public ZOutputStream(Stream output, int level)
@@ -86,9 +102,9 @@ namespace Org.BouncyCastle.Utilities.Zlib
Debug.Assert(output.CanWrite);
this.output = output;
+ this.compress = true;
this.z = new ZStream();
this.z.deflateInit(level, nowrap);
- this.compress = true;
}
public sealed override bool CanRead { get { return false; } }
--
cgit 1.5.1
From 7f2f1a730caa23a811ed710d67feb8f6b2ebb9a5 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Fri, 28 Oct 2016 22:01:55 +0200
Subject: Throw excepton on unknown tag
---
crypto/src/asn1/ocsp/CertStatus.cs | 2 ++
1 file changed, 2 insertions(+)
(limited to 'crypto/src')
diff --git a/crypto/src/asn1/ocsp/CertStatus.cs b/crypto/src/asn1/ocsp/CertStatus.cs
index b524364c9..7dd99b844 100644
--- a/crypto/src/asn1/ocsp/CertStatus.cs
+++ b/crypto/src/asn1/ocsp/CertStatus.cs
@@ -48,6 +48,8 @@ namespace Org.BouncyCastle.Asn1.Ocsp
case 2:
value = DerNull.Instance;
break;
+ default:
+ throw new ArgumentException("Unknown tag encountered: " + choice.TagNo);
}
}
--
cgit 1.5.1
From 5f3830451fa08884b751b8de4f2ee8109ac3527f Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Thu, 10 Nov 2016 14:42:27 +0700
Subject: Fix possible NPE when cofactor != 1 (from bc-java)
---
crypto/src/math/ec/multiplier/WNafUtilities.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'crypto/src')
diff --git a/crypto/src/math/ec/multiplier/WNafUtilities.cs b/crypto/src/math/ec/multiplier/WNafUtilities.cs
index 5491297d7..7d565dfbd 100644
--- a/crypto/src/math/ec/multiplier/WNafUtilities.cs
+++ b/crypto/src/math/ec/multiplier/WNafUtilities.cs
@@ -423,7 +423,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
* 1) additions do not use the curve's A, B coefficients.
* 2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ...
*/
- if (ECAlgorithms.IsFpCurve(c) && c.FieldSize >= 64)
+ if (!twiceP.IsInfinity && ECAlgorithms.IsFpCurve(c) && c.FieldSize >= 64)
{
switch (c.CoordinateSystem)
{
--
cgit 1.5.1
From 0eca6bebcc0d1b29d8b73d4790d314a9719081d0 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Fri, 11 Nov 2016 22:30:03 +0700
Subject: EncryptionAlgorithm.NULL is a 'stream' cipher
---
crypto/src/crypto/tls/TlsUtilities.cs | 1 +
1 file changed, 1 insertion(+)
(limited to 'crypto/src')
diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs
index 25908d163..d51a8ff48 100644
--- a/crypto/src/crypto/tls/TlsUtilities.cs
+++ b/crypto/src/crypto/tls/TlsUtilities.cs
@@ -1246,6 +1246,7 @@ namespace Org.BouncyCastle.Crypto.Tls
case EncryptionAlgorithm.SEED_CBC:
return CipherType.block;
+ case EncryptionAlgorithm.NULL:
case EncryptionAlgorithm.RC4_40:
case EncryptionAlgorithm.RC4_128:
return CipherType.stream;
--
cgit 1.5.1
From bd844ab76865ffaad429d8f1795db1ccedac70b1 Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Mon, 14 Nov 2016 14:18:28 +0700
Subject: After receiving fatal alert, don't echo that alert to peer (from
bc-java)
- https://github.com/bcgit/bc-java/issues/148
- also explicitly invalidate session after fatal alert
---
crypto/src/crypto/tls/DtlsClientProtocol.cs | 16 +++++++++++---
crypto/src/crypto/tls/DtlsRecordLayer.cs | 12 +++++++++-
crypto/src/crypto/tls/DtlsServerProtocol.cs | 34 ++++++++++++++++++++++++++---
3 files changed, 55 insertions(+), 7 deletions(-)
(limited to 'crypto/src')
diff --git a/crypto/src/crypto/tls/DtlsClientProtocol.cs b/crypto/src/crypto/tls/DtlsClientProtocol.cs
index abb402077..90430d772 100644
--- a/crypto/src/crypto/tls/DtlsClientProtocol.cs
+++ b/crypto/src/crypto/tls/DtlsClientProtocol.cs
@@ -53,19 +53,29 @@ namespace Org.BouncyCastle.Crypto.Tls
}
catch (TlsFatalAlert fatalAlert)
{
- recordLayer.Fail(fatalAlert.AlertDescription);
+ AbortClientHandshake(state, recordLayer, fatalAlert.AlertDescription);
throw fatalAlert;
}
catch (IOException e)
{
- recordLayer.Fail(AlertDescription.internal_error);
+ AbortClientHandshake(state, recordLayer, AlertDescription.internal_error);
throw e;
}
catch (Exception e)
{
- recordLayer.Fail(AlertDescription.internal_error);
+ AbortClientHandshake(state, recordLayer, AlertDescription.internal_error);
throw new TlsFatalAlert(AlertDescription.internal_error, e);
}
+ finally
+ {
+ securityParameters.Clear();
+ }
+ }
+
+ internal virtual void AbortClientHandshake(ClientHandshakeState state, DtlsRecordLayer recordLayer, byte alertDescription)
+ {
+ recordLayer.Fail(alertDescription);
+ InvalidateSession(state);
}
internal virtual DtlsTransport ClientHandshake(ClientHandshakeState state, DtlsRecordLayer recordLayer)
diff --git a/crypto/src/crypto/tls/DtlsRecordLayer.cs b/crypto/src/crypto/tls/DtlsRecordLayer.cs
index 6796f4cbb..4a781b5b5 100644
--- a/crypto/src/crypto/tls/DtlsRecordLayer.cs
+++ b/crypto/src/crypto/tls/DtlsRecordLayer.cs
@@ -237,7 +237,7 @@ namespace Org.BouncyCastle.Crypto.Tls
if (alertLevel == AlertLevel.fatal)
{
- Fail(alertDescription);
+ Failed();
throw new TlsFatalAlert(alertDescription);
}
@@ -375,6 +375,16 @@ namespace Org.BouncyCastle.Crypto.Tls
}
}
+ internal virtual void Failed()
+ {
+ if (!mClosed)
+ {
+ mFailed = true;
+
+ CloseTransport();
+ }
+ }
+
internal virtual void Fail(byte alertDescription)
{
if (!mClosed)
diff --git a/crypto/src/crypto/tls/DtlsServerProtocol.cs b/crypto/src/crypto/tls/DtlsServerProtocol.cs
index d05af193c..fbf33045b 100644
--- a/crypto/src/crypto/tls/DtlsServerProtocol.cs
+++ b/crypto/src/crypto/tls/DtlsServerProtocol.cs
@@ -54,19 +54,29 @@ namespace Org.BouncyCastle.Crypto.Tls
}
catch (TlsFatalAlert fatalAlert)
{
- recordLayer.Fail(fatalAlert.AlertDescription);
+ AbortServerHandshake(state, recordLayer, fatalAlert.AlertDescription);
throw fatalAlert;
}
catch (IOException e)
{
- recordLayer.Fail(AlertDescription.internal_error);
+ AbortServerHandshake(state, recordLayer, AlertDescription.internal_error);
throw e;
}
catch (Exception e)
{
- recordLayer.Fail(AlertDescription.internal_error);
+ AbortServerHandshake(state, recordLayer, AlertDescription.internal_error);
throw new TlsFatalAlert(AlertDescription.internal_error, e);
}
+ finally
+ {
+ securityParameters.Clear();
+ }
+ }
+
+ internal virtual void AbortServerHandshake(ServerHandshakeState state, DtlsRecordLayer recordLayer, byte alertDescription)
+ {
+ recordLayer.Fail(alertDescription);
+ InvalidateSession(state);
}
internal virtual DtlsTransport ServerHandshake(ServerHandshakeState state, DtlsRecordLayer recordLayer)
@@ -263,6 +273,21 @@ namespace Org.BouncyCastle.Crypto.Tls
return new DtlsTransport(recordLayer);
}
+ protected virtual void InvalidateSession(ServerHandshakeState state)
+ {
+ if (state.sessionParameters != null)
+ {
+ state.sessionParameters.Clear();
+ state.sessionParameters = null;
+ }
+
+ if (state.tlsSession != null)
+ {
+ state.tlsSession.Invalidate();
+ state.tlsSession = null;
+ }
+ }
+
protected virtual byte[] GenerateCertificateRequest(ServerHandshakeState state, CertificateRequest certificateRequest)
{
MemoryStream buf = new MemoryStream();
@@ -650,6 +675,9 @@ namespace Org.BouncyCastle.Crypto.Tls
{
internal TlsServer server = null;
internal TlsServerContextImpl serverContext = null;
+ internal TlsSession tlsSession = null;
+ internal SessionParameters sessionParameters = null;
+ internal SessionParameters.Builder sessionParametersBuilder = null;
internal int[] offeredCipherSuites = null;
internal byte[] offeredCompressionMethods = null;
internal IDictionary clientExtensions = null;
--
cgit 1.5.1
From 84b2be3efb82184703e350c26d7f13330395c15b Mon Sep 17 00:00:00 2001
From: Peter Dettman
Date: Wed, 30 Nov 2016 05:36:43 +0700
Subject: Fix carry propagation bug in Nat???.Square methods
---
crypto/Readme.html | 14 +-
crypto/crypto.csproj | 10 ++
crypto/src/math/raw/Nat128.cs | 8 +-
crypto/src/math/raw/Nat160.cs | 16 +-
crypto/src/math/raw/Nat192.cs | 24 +--
crypto/src/math/raw/Nat224.cs | 32 ++--
crypto/src/math/raw/Nat256.cs | 40 ++---
crypto/test/UnitTests.csproj | 2 +
.../math/ec/custom/sec/test/SecP256R1FieldTest.cs | 181 +++++++++++++++++++++
.../math/ec/custom/sec/test/SecP384R1FieldTest.cs | 146 +++++++++++++++++
10 files changed, 412 insertions(+), 61 deletions(-)
create mode 100644 crypto/test/src/math/ec/custom/sec/test/SecP256R1FieldTest.cs
create mode 100644 crypto/test/src/math/ec/custom/sec/test/SecP384R1FieldTest.cs
(limited to 'crypto/src')
diff --git a/crypto/Readme.html b/crypto/Readme.html
index 0cbd91daa..b26937714 100644
--- a/crypto/Readme.html
+++ b/crypto/Readme.html
@@ -294,6 +294,18 @@ We state, where EC MQV has not otherwise been disabled or removed:
Release 1.8.2, Release Date TBD
+ Security Advisory
+
+ -
+ Carry propagation bugs in the implementation of squaring for several raw math classes have been fixed (Org.BouncyCastle.Math.Raw.Nat???).
+ These classes are used by our custom elliptic curve implementations (Org.BouncyCastle.Math.Ec.Custom.**), so there was the possibility
+ of rare (in general usage) spurious calculations for elliptic curve scalar multiplications. Such errors would have been detected with
+ high probability by the output validation for our scalar multipliers. We consider these bugs to be exploitable for static ECDH with
+ long-term keys, per "Practical realisation and elimination of an ECC-related software bug attack",
+ Brumley et.al.
+
+
+
IMPORTANT
-
@@ -381,7 +393,7 @@ We state, where EC MQV has not otherwise been disabled or removed:
- RFC 6637 ECDSA and ECDH support has been added to the OpenPGP API.
- Implementations of Threefish and Skein have been added.
- Implementation of the SM3 digest has been added.
- - Implementations of XSalsa20 and ChaCha have been added. Support for reduced round Salas20 has been added.
+ - Implementations of XSalsa20 and ChaCha have been added. Support for reduced round Salsa20 has been added.
- Support has been added for RFC 6979 Deterministic DSA/ECDSA.
- Support for the Poly1305 MAC has been added.
- GCM and GMAC now support tag lengths down to 32 bits.
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index fcb52bb20..6f1fdcf61 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -12054,6 +12054,16 @@
SubType = "Code"
BuildAction = "Compile"
/>
+
+
> 32); zz_4 &= M;
+ ulong zz_6 = zz[6] + (zz_5 >> 32); zz_5 &= M;
{
zz_3 += x_3 * x_0;
w = (uint)zz_3;
@@ -702,8 +702,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_3 = x[xOff + 3];
- ulong zz_5 = zz[zzOff + 5];
- ulong zz_6 = zz[zzOff + 6];
+ ulong zz_5 = zz[zzOff + 5] + (zz_4 >> 32); zz_4 &= M;
+ ulong zz_6 = zz[zzOff + 6] + (zz_5 >> 32); zz_5 &= M;
{
zz_3 += x_3 * x_0;
w = (uint)zz_3;
diff --git a/crypto/src/math/raw/Nat160.cs b/crypto/src/math/raw/Nat160.cs
index 153ac0a43..1fd00e576 100644
--- a/crypto/src/math/raw/Nat160.cs
+++ b/crypto/src/math/raw/Nat160.cs
@@ -604,8 +604,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_3 = x[3];
- ulong zz_5 = zz[5];
- ulong zz_6 = zz[6];
+ ulong zz_5 = zz[5] + (zz_4 >> 32); zz_4 &= M;
+ ulong zz_6 = zz[6] + (zz_5 >> 32); zz_5 &= M;
{
zz_3 += x_3 * x_0;
w = (uint)zz_3;
@@ -619,8 +619,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_4 = x[4];
- ulong zz_7 = zz[7];
- ulong zz_8 = zz[8];
+ ulong zz_7 = zz[7] + (zz_6 >> 32); zz_6 &= M;
+ ulong zz_8 = zz[8] + (zz_7 >> 32); zz_7 &= M;
{
zz_4 += x_4 * x_0;
w = (uint)zz_4;
@@ -699,8 +699,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_3 = x[xOff + 3];
- ulong zz_5 = zz[zzOff + 5];
- ulong zz_6 = zz[zzOff + 6];
+ ulong zz_5 = zz[zzOff + 5] + (zz_4 >> 32); zz_4 &= M;
+ ulong zz_6 = zz[zzOff + 6] + (zz_5 >> 32); zz_5 &= M;
{
zz_3 += x_3 * x_0;
w = (uint)zz_3;
@@ -714,8 +714,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_4 = x[xOff + 4];
- ulong zz_7 = zz[zzOff + 7];
- ulong zz_8 = zz[zzOff + 8];
+ ulong zz_7 = zz[zzOff + 7] + (zz_6 >> 32); zz_6 &= M;
+ ulong zz_8 = zz[zzOff + 8] + (zz_7 >> 32); zz_7 &= M;
{
zz_4 += x_4 * x_0;
w = (uint)zz_4;
diff --git a/crypto/src/math/raw/Nat192.cs b/crypto/src/math/raw/Nat192.cs
index 4797609ee..3099bafab 100644
--- a/crypto/src/math/raw/Nat192.cs
+++ b/crypto/src/math/raw/Nat192.cs
@@ -706,8 +706,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_3 = x[3];
- ulong zz_5 = zz[5];
- ulong zz_6 = zz[6];
+ ulong zz_5 = zz[5] + (zz_4 >> 32); zz_4 &= M;
+ ulong zz_6 = zz[6] + (zz_5 >> 32); zz_5 &= M;
{
zz_3 += x_3 * x_0;
w = (uint)zz_3;
@@ -721,8 +721,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_4 = x[4];
- ulong zz_7 = zz[7];
- ulong zz_8 = zz[8];
+ ulong zz_7 = zz[7] + (zz_6 >> 32); zz_6 &= M;
+ ulong zz_8 = zz[8] + (zz_7 >> 32); zz_7 &= M;
{
zz_4 += x_4 * x_0;
w = (uint)zz_4;
@@ -738,8 +738,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_5 = x[5];
- ulong zz_9 = zz[9];
- ulong zz_10 = zz[10];
+ ulong zz_9 = zz[9] + (zz_8 >> 32); zz_8 &= M;
+ ulong zz_10 = zz[10] + (zz_9 >> 32); zz_9 &= M;
{
zz_5 += x_5 * x_0;
w = (uint)zz_5;
@@ -822,8 +822,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_3 = x[xOff + 3];
- ulong zz_5 = zz[zzOff + 5];
- ulong zz_6 = zz[zzOff + 6];
+ ulong zz_5 = zz[zzOff + 5] + (zz_4 >> 32); zz_4 &= M;
+ ulong zz_6 = zz[zzOff + 6] + (zz_5 >> 32); zz_5 &= M;
{
zz_3 += x_3 * x_0;
w = (uint)zz_3;
@@ -837,8 +837,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_4 = x[xOff + 4];
- ulong zz_7 = zz[zzOff + 7];
- ulong zz_8 = zz[zzOff + 8];
+ ulong zz_7 = zz[zzOff + 7] + (zz_6 >> 32); zz_6 &= M;
+ ulong zz_8 = zz[zzOff + 8] + (zz_7 >> 32); zz_7 &= M;
{
zz_4 += x_4 * x_0;
w = (uint)zz_4;
@@ -854,8 +854,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_5 = x[xOff + 5];
- ulong zz_9 = zz[zzOff + 9];
- ulong zz_10 = zz[zzOff + 10];
+ ulong zz_9 = zz[zzOff + 9] + (zz_8 >> 32); zz_8 &= M;
+ ulong zz_10 = zz[zzOff + 10] + (zz_9 >> 32); zz_9 &= M;
{
zz_5 += x_5 * x_0;
w = (uint)zz_5;
diff --git a/crypto/src/math/raw/Nat224.cs b/crypto/src/math/raw/Nat224.cs
index 940e930ac..978caf265 100644
--- a/crypto/src/math/raw/Nat224.cs
+++ b/crypto/src/math/raw/Nat224.cs
@@ -786,8 +786,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_3 = x[3];
- ulong zz_5 = zz[5];
- ulong zz_6 = zz[6];
+ ulong zz_5 = zz[5] + (zz_4 >> 32); zz_4 &= M;
+ ulong zz_6 = zz[6] + (zz_5 >> 32); zz_5 &= M;
{
zz_3 += x_3 * x_0;
w = (uint)zz_3;
@@ -801,8 +801,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_4 = x[4];
- ulong zz_7 = zz[7];
- ulong zz_8 = zz[8];
+ ulong zz_7 = zz[7] + (zz_6 >> 32); zz_6 &= M;
+ ulong zz_8 = zz[8] + (zz_7 >> 32); zz_7 &= M;
{
zz_4 += x_4 * x_0;
w = (uint)zz_4;
@@ -818,8 +818,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_5 = x[5];
- ulong zz_9 = zz[9];
- ulong zz_10 = zz[10];
+ ulong zz_9 = zz[9] + (zz_8 >> 32); zz_8 &= M;
+ ulong zz_10 = zz[10] + (zz_9 >> 32); zz_9 &= M;
{
zz_5 += x_5 * x_0;
w = (uint)zz_5;
@@ -837,8 +837,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_6 = x[6];
- ulong zz_11 = zz[11];
- ulong zz_12 = zz[12];
+ ulong zz_11 = zz[11] + (zz_10 >> 32); zz_10 &= M;
+ ulong zz_12 = zz[12] + (zz_11 >> 32); zz_11 &= M;
{
zz_6 += x_6 * x_0;
w = (uint)zz_6;
@@ -925,8 +925,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_3 = x[xOff + 3];
- ulong zz_5 = zz[zzOff + 5];
- ulong zz_6 = zz[zzOff + 6];
+ ulong zz_5 = zz[zzOff + 5] + (zz_4 >> 32); zz_4 &= M;
+ ulong zz_6 = zz[zzOff + 6] + (zz_5 >> 32); zz_5 &= M;
{
zz_3 += x_3 * x_0;
w = (uint)zz_3;
@@ -940,8 +940,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_4 = x[xOff + 4];
- ulong zz_7 = zz[zzOff + 7];
- ulong zz_8 = zz[zzOff + 8];
+ ulong zz_7 = zz[zzOff + 7] + (zz_6 >> 32); zz_6 &= M;
+ ulong zz_8 = zz[zzOff + 8] + (zz_7 >> 32); zz_7 &= M;
{
zz_4 += x_4 * x_0;
w = (uint)zz_4;
@@ -957,8 +957,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_5 = x[xOff + 5];
- ulong zz_9 = zz[zzOff + 9];
- ulong zz_10 = zz[zzOff + 10];
+ ulong zz_9 = zz[zzOff + 9] + (zz_8 >> 32); zz_8 &= M;
+ ulong zz_10 = zz[zzOff + 10] + (zz_9 >> 32); zz_9 &= M;
{
zz_5 += x_5 * x_0;
w = (uint)zz_5;
@@ -976,8 +976,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_6 = x[xOff + 6];
- ulong zz_11 = zz[zzOff + 11];
- ulong zz_12 = zz[zzOff + 12];
+ ulong zz_11 = zz[zzOff + 11] + (zz_10 >> 32); zz_10 &= M;
+ ulong zz_12 = zz[zzOff + 12] + (zz_11 >> 32); zz_11 &= M;
{
zz_6 += x_6 * x_0;
w = (uint)zz_6;
diff --git a/crypto/src/math/raw/Nat256.cs b/crypto/src/math/raw/Nat256.cs
index 19455031a..09c751a5a 100644
--- a/crypto/src/math/raw/Nat256.cs
+++ b/crypto/src/math/raw/Nat256.cs
@@ -917,8 +917,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_3 = x[3];
- ulong zz_5 = zz[5];
- ulong zz_6 = zz[6];
+ ulong zz_5 = zz[5] + (zz_4 >> 32); zz_4 &= M;
+ ulong zz_6 = zz[6] + (zz_5 >> 32); zz_5 &= M;
{
zz_3 += x_3 * x_0;
w = (uint)zz_3;
@@ -932,8 +932,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_4 = x[4];
- ulong zz_7 = zz[7];
- ulong zz_8 = zz[8];
+ ulong zz_7 = zz[7] + (zz_6 >> 32); zz_6 &= M;
+ ulong zz_8 = zz[8] + (zz_7 >> 32); zz_7 &= M;
{
zz_4 += x_4 * x_0;
w = (uint)zz_4;
@@ -949,8 +949,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_5 = x[5];
- ulong zz_9 = zz[9];
- ulong zz_10 = zz[10];
+ ulong zz_9 = zz[9] + (zz_8 >> 32); zz_8 &= M;
+ ulong zz_10 = zz[10] + (zz_9 >> 32); zz_9 &= M;
{
zz_5 += x_5 * x_0;
w = (uint)zz_5;
@@ -968,8 +968,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_6 = x[6];
- ulong zz_11 = zz[11];
- ulong zz_12 = zz[12];
+ ulong zz_11 = zz[11] + (zz_10 >> 32); zz_10 &= M;
+ ulong zz_12 = zz[12] + (zz_11 >> 32); zz_11 &= M;
{
zz_6 += x_6 * x_0;
w = (uint)zz_6;
@@ -989,8 +989,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_7 = x[7];
- ulong zz_13 = zz[13];
- ulong zz_14 = zz[14];
+ ulong zz_13 = zz[13] + (zz_12 >> 32); zz_12 &= M;
+ ulong zz_14 = zz[14] + (zz_13 >> 32); zz_13 &= M;
{
zz_7 += x_7 * x_0;
w = (uint)zz_7;
@@ -1081,8 +1081,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_3 = x[xOff + 3];
- ulong zz_5 = zz[zzOff + 5];
- ulong zz_6 = zz[zzOff + 6];
+ ulong zz_5 = zz[zzOff + 5] + (zz_4 >> 32); zz_4 &= M;
+ ulong zz_6 = zz[zzOff + 6] + (zz_5 >> 32); zz_5 &= M;
{
zz_3 += x_3 * x_0;
w = (uint)zz_3;
@@ -1096,8 +1096,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_4 = x[xOff + 4];
- ulong zz_7 = zz[zzOff + 7];
- ulong zz_8 = zz[zzOff + 8];
+ ulong zz_7 = zz[zzOff + 7] + (zz_6 >> 32); zz_6 &= M;
+ ulong zz_8 = zz[zzOff + 8] + (zz_7 >> 32); zz_7 &= M;
{
zz_4 += x_4 * x_0;
w = (uint)zz_4;
@@ -1113,8 +1113,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_5 = x[xOff + 5];
- ulong zz_9 = zz[zzOff + 9];
- ulong zz_10 = zz[zzOff + 10];
+ ulong zz_9 = zz[zzOff + 9] + (zz_8 >> 32); zz_8 &= M;
+ ulong zz_10 = zz[zzOff + 10] + (zz_9 >> 32); zz_9 &= M;
{
zz_5 += x_5 * x_0;
w = (uint)zz_5;
@@ -1132,8 +1132,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_6 = x[xOff + 6];
- ulong zz_11 = zz[zzOff + 11];
- ulong zz_12 = zz[zzOff + 12];
+ ulong zz_11 = zz[zzOff + 11] + (zz_10 >> 32); zz_10 &= M;
+ ulong zz_12 = zz[zzOff + 12] + (zz_11 >> 32); zz_11 &= M;
{
zz_6 += x_6 * x_0;
w = (uint)zz_6;
@@ -1153,8 +1153,8 @@ namespace Org.BouncyCastle.Math.Raw
}
ulong x_7 = x[xOff + 7];
- ulong zz_13 = zz[zzOff + 13];
- ulong zz_14 = zz[zzOff + 14];
+ ulong zz_13 = zz[zzOff + 13] + (zz_12 >> 32); zz_12 &= M;
+ ulong zz_14 = zz[zzOff + 14] + (zz_13 >> 32); zz_13 &= M;
{
zz_7 += x_7 * x_0;
w = (uint)zz_7;
diff --git a/crypto/test/UnitTests.csproj b/crypto/test/UnitTests.csproj
index b4c53092b..fe4dd9583 100644
--- a/crypto/test/UnitTests.csproj
+++ b/crypto/test/UnitTests.csproj
@@ -312,6 +312,8 @@
+
+
diff --git a/crypto/test/src/math/ec/custom/sec/test/SecP256R1FieldTest.cs b/crypto/test/src/math/ec/custom/sec/test/SecP256R1FieldTest.cs
new file mode 100644
index 000000000..374b1ecd1
--- /dev/null
+++ b/crypto/test/src/math/ec/custom/sec/test/SecP256R1FieldTest.cs
@@ -0,0 +1,181 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.EC;
+using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec.Tests
+{
+ [TestFixture]
+ public class SecP256R1FieldTest
+ {
+ private static readonly SecureRandom Random = new SecureRandom();
+
+ private static readonly X9ECParameters DP = CustomNamedCurves
+ .GetByOid(SecObjectIdentifiers.SecP256r1);
+ private static readonly BigInteger Q = DP.Curve.Field.Characteristic;
+
+ [Test]
+ public void TestMultiply1()
+ {
+ int COUNT = 1000;
+
+ for (int i = 0; i < COUNT; ++i)
+ {
+ ECFieldElement x = GenerateMultiplyInput_Random();
+ ECFieldElement y = GenerateMultiplyInput_Random();
+
+ BigInteger X = x.ToBigInteger(), Y = y.ToBigInteger();
+ BigInteger R = X.Multiply(Y).Mod(Q);
+
+ ECFieldElement z = x.Multiply(y);
+ BigInteger Z = z.ToBigInteger();
+
+ Assert.AreEqual(R, Z);
+ }
+ }
+
+ [Test]
+ public void TestMultiply2()
+ {
+ int COUNT = 100;
+ ECFieldElement[] inputs = new ECFieldElement[COUNT];
+ BigInteger[] INPUTS = new BigInteger[COUNT];
+
+ for (int i = 0; i < inputs.Length; ++i)
+ {
+ inputs[i] = GenerateMultiplyInput_Random();
+ INPUTS[i] = inputs[i].ToBigInteger();
+ }
+
+ for (int j = 0; j < inputs.Length; ++j)
+ {
+ for (int k = 0; k < inputs.Length; ++k)
+ {
+ BigInteger R = INPUTS[j].Multiply(INPUTS[k]).Mod(Q);
+
+ ECFieldElement z = inputs[j].Multiply(inputs[k]);
+ BigInteger Z = z.ToBigInteger();
+
+ Assert.AreEqual(R, Z);
+ }
+ }
+ }
+
+ [Test]
+ public void TestSquare()
+ {
+ int COUNT = 1000;
+
+ for (int i = 0; i < COUNT; ++i)
+ {
+ ECFieldElement x = GenerateMultiplyInput_Random();
+
+ BigInteger X = x.ToBigInteger();
+ BigInteger R = X.Multiply(X).Mod(Q);
+
+ ECFieldElement z = x.Square();
+ BigInteger Z = z.ToBigInteger();
+
+ Assert.AreEqual(R, Z);
+ }
+ }
+
+ /**
+ * Test multiplication with specifically selected values that triggered a bug in the modular
+ * reduction in OpenSSL (last affected version 0.9.8g).
+ *
+ * See "Practical realisation and elimination of an ECC-related software bug attack", B. B.
+ * Brumley, M. Barbarosa, D. Page, F. Vercauteren.
+ */
+ [Test]
+ public void TestMultiply_OpenSSLBug()
+ {
+ int COUNT = 100;
+
+ for (int i = 0; i < COUNT; ++i)
+ {
+ ECFieldElement x = GenerateMultiplyInputA_OpenSSLBug();
+ ECFieldElement y = GenerateMultiplyInputB_OpenSSLBug();
+
+ BigInteger X = x.ToBigInteger(), Y = y.ToBigInteger();
+ BigInteger R = X.Multiply(Y).Mod(Q);
+
+ ECFieldElement z = x.Multiply(y);
+ BigInteger Z = z.ToBigInteger();
+
+ Assert.AreEqual(R, Z);
+ }
+ }
+
+ /**
+ * Test squaring with specifically selected values that triggered a bug in the modular reduction
+ * in OpenSSL (last affected version 0.9.8g).
+ *
+ * See "Practical realisation and elimination of an ECC-related software bug attack", B. B.
+ * Brumley, M. Barbarosa, D. Page, F. Vercauteren.
+ */
+ [Test]
+ public void TestSquare_OpenSSLBug()
+ {
+ int COUNT = 100;
+
+ for (int i = 0; i < COUNT; ++i)
+ {
+ ECFieldElement x = GenerateSquareInput_OpenSSLBug();
+
+ BigInteger X = x.ToBigInteger();
+ BigInteger R = X.Multiply(X).Mod(Q);
+
+ ECFieldElement z = x.Square();
+ BigInteger Z = z.ToBigInteger();
+
+ Assert.AreEqual(R, Z);
+ }
+ }
+
+ private ECFieldElement FE(BigInteger x)
+ {
+ return DP.Curve.FromBigInteger(x);
+ }
+
+ private ECFieldElement GenerateMultiplyInput_Random()
+ {
+ return FE(new BigInteger(DP.Curve.FieldSize + 32, Random).Mod(Q));
+ }
+
+ private ECFieldElement GenerateMultiplyInputA_OpenSSLBug()
+ {
+ uint[] x = Nat256.Create();
+ x[0] = (uint)Random.NextInt() >> 1;
+ x[4] = 3;
+ x[7] = 0xFFFFFFFF;
+
+ return FE(Nat256.ToBigInteger(x));
+ }
+
+ private ECFieldElement GenerateMultiplyInputB_OpenSSLBug()
+ {
+ uint[] x = Nat256.Create();
+ x[0] = (uint)Random.NextInt() >> 1;
+ x[3] = 1;
+ x[7] = 0xFFFFFFFF;
+
+ return FE(Nat256.ToBigInteger(x));
+ }
+
+ private ECFieldElement GenerateSquareInput_OpenSSLBug()
+ {
+ uint[] x = Nat256.Create();
+ x[0] = (uint)Random.NextInt() >> 1;
+ x[4] = 2;
+ x[7] = 0xFFFFFFFF;
+
+ return FE(Nat256.ToBigInteger(x));
+ }
+ }
+}
diff --git a/crypto/test/src/math/ec/custom/sec/test/SecP384R1FieldTest.cs b/crypto/test/src/math/ec/custom/sec/test/SecP384R1FieldTest.cs
new file mode 100644
index 000000000..86ec4894f
--- /dev/null
+++ b/crypto/test/src/math/ec/custom/sec/test/SecP384R1FieldTest.cs
@@ -0,0 +1,146 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.EC;
+using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec.Tests
+{
+ [TestFixture]
+ public class SecP384R1FieldTest
+ {
+ private static readonly SecureRandom Random = new SecureRandom();
+
+ private static readonly X9ECParameters DP = CustomNamedCurves
+ .GetByOid(SecObjectIdentifiers.SecP384r1);
+ private static readonly BigInteger Q = DP.Curve.Field.Characteristic;
+
+ [Test]
+ public void TestMultiply1()
+ {
+ int COUNT = 1000;
+
+ for (int i = 0; i < COUNT; ++i)
+ {
+ ECFieldElement x = GenerateMultiplyInput_Random();
+ ECFieldElement y = GenerateMultiplyInput_Random();
+
+ BigInteger X = x.ToBigInteger(), Y = y.ToBigInteger();
+ BigInteger R = X.Multiply(Y).Mod(Q);
+
+ ECFieldElement z = x.Multiply(y);
+ BigInteger Z = z.ToBigInteger();
+
+ Assert.AreEqual(R, Z);
+ }
+ }
+
+ [Test]
+ public void TestMultiply2()
+ {
+ int COUNT = 100;
+ ECFieldElement[] inputs = new ECFieldElement[COUNT];
+ BigInteger[] INPUTS = new BigInteger[COUNT];
+
+ for (int i = 0; i < inputs.Length; ++i)
+ {
+ inputs[i] = GenerateMultiplyInput_Random();
+ INPUTS[i] = inputs[i].ToBigInteger();
+ }
+
+ for (int j = 0; j < inputs.Length; ++j)
+ {
+ for (int k = 0; k < inputs.Length; ++k)
+ {
+ BigInteger R = INPUTS[j].Multiply(INPUTS[k]).Mod(Q);
+
+ ECFieldElement z = inputs[j].Multiply(inputs[k]);
+ BigInteger Z = z.ToBigInteger();
+
+ Assert.AreEqual(R, Z);
+ }
+ }
+ }
+
+ [Test]
+ public void TestSquare()
+ {
+ int COUNT = 1000;
+
+ for (int i = 0; i < COUNT; ++i)
+ {
+ ECFieldElement x = GenerateMultiplyInput_Random();
+
+ BigInteger X = x.ToBigInteger();
+ BigInteger R = X.Multiply(X).Mod(Q);
+
+ ECFieldElement z = x.Square();
+ BigInteger Z = z.ToBigInteger();
+
+ Assert.AreEqual(R, Z);
+ }
+ }
+
+ [Test]
+ public void TestSquare_CarryBug()
+ {
+ int COUNT = 100;
+
+ for (int i = 0; i < COUNT; ++i)
+ {
+ ECFieldElement x = GenerateSquareInput_CarryBug();
+
+ BigInteger X = x.ToBigInteger();
+ BigInteger R = X.Multiply(X).Mod(Q);
+
+ ECFieldElement z = x.Square();
+ BigInteger Z = z.ToBigInteger();
+
+ Assert.AreEqual(R, Z);
+ }
+ }
+
+ /*
+ * Based on another example input demonstrating the carry propagation bug in Nat192.square, as
+ * reported by Joseph Friel on dev-crypto.
+ */
+ [Test]
+ public void TestSquare_CarryBug_Reported()
+ {
+ ECFieldElement x = FE(new BigInteger("2fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", 16));
+
+ BigInteger X = x.ToBigInteger();
+ BigInteger R = X.Multiply(X).Mod(Q);
+
+ ECFieldElement z = x.Square();
+ BigInteger Z = z.ToBigInteger();
+
+ Assert.AreEqual(R, Z);
+ }
+
+ private ECFieldElement FE(BigInteger x)
+ {
+ return DP.Curve.FromBigInteger(x);
+ }
+
+ private ECFieldElement GenerateMultiplyInput_Random()
+ {
+ return FE(new BigInteger(DP.Curve.FieldSize + 32, Random).Mod(Q));
+ }
+
+ private ECFieldElement GenerateSquareInput_CarryBug()
+ {
+ uint[] x = Nat.Create(12);
+ x[0] = (uint)Random.NextInt() >> 1;
+ x[6] = 2;
+ x[10] = 0xFFFF0000;
+ x[11] = 0xFFFFFFFF;
+
+ return FE(Nat.ToBigInteger(12, x));
+ }
+ }
+}
--
cgit 1.5.1