diff --git a/crypto/src/crypto/tls/TlsAeadCipher.cs b/crypto/src/crypto/tls/TlsAeadCipher.cs
index 951e8663b..bff719db1 100644
--- a/crypto/src/crypto/tls/TlsAeadCipher.cs
+++ b/crypto/src/crypto/tls/TlsAeadCipher.cs
@@ -10,9 +10,13 @@ namespace Org.BouncyCastle.Crypto.Tls
public class TlsAeadCipher
: TlsCipher
{
+ public const int NONCE_RFC5288 = 1;
+ internal const int NONCE_DRAFT_ZAUNER_TLS_AES_OCB = 2;
+
protected readonly TlsContext context;
protected readonly int macSize;
- protected readonly int nonce_explicit_length;
+ // TODO SecurityParameters.record_iv_length
+ protected readonly int record_iv_length;
protected readonly IAeadBlockCipher encryptCipher;
protected readonly IAeadBlockCipher decryptCipher;
@@ -22,16 +26,32 @@ namespace Org.BouncyCastle.Crypto.Tls
/// <exception cref="IOException"></exception>
public TlsAeadCipher(TlsContext context, IAeadBlockCipher clientWriteCipher, IAeadBlockCipher serverWriteCipher,
int cipherKeySize, int macSize)
+ : this(context, clientWriteCipher, serverWriteCipher, cipherKeySize, macSize, NONCE_RFC5288)
+ {
+ }
+
+ /// <exception cref="IOException"></exception>
+ internal TlsAeadCipher(TlsContext context, IAeadBlockCipher clientWriteCipher, IAeadBlockCipher serverWriteCipher,
+ int cipherKeySize, int macSize, int nonceMode)
{
if (!TlsUtilities.IsTlsV12(context))
throw new TlsFatalAlert(AlertDescription.internal_error);
+ switch (nonceMode)
+ {
+ case NONCE_RFC5288:
+ this.record_iv_length = 8;
+ break;
+ case NONCE_DRAFT_ZAUNER_TLS_AES_OCB:
+ this.record_iv_length = 0;
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
this.context = context;
this.macSize = macSize;
- // NOTE: Valid for RFC 5288/6655 ciphers but may need review for other AEAD ciphers
- this.nonce_explicit_length = 8;
-
// TODO SecurityParameters.fixed_iv_length
int fixed_iv_length = 4;
@@ -73,7 +93,7 @@ namespace Org.BouncyCastle.Crypto.Tls
decryptKey = server_write_key;
}
- byte[] dummyNonce = new byte[fixed_iv_length + nonce_explicit_length];
+ byte[] dummyNonce = new byte[fixed_iv_length + 8];
this.encryptCipher.Init(true, new AeadParameters(encryptKey, 8 * macSize, dummyNonce));
this.decryptCipher.Init(false, new AeadParameters(decryptKey, 8 * macSize, dummyNonce));
@@ -82,17 +102,18 @@ namespace Org.BouncyCastle.Crypto.Tls
public virtual int GetPlaintextLimit(int ciphertextLimit)
{
// TODO We ought to be able to ask the decryptCipher (independently of it's current state!)
- return ciphertextLimit - macSize - nonce_explicit_length;
+ return ciphertextLimit - macSize - record_iv_length;
}
/// <exception cref="IOException"></exception>
public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
{
- byte[] nonce = new byte[this.encryptImplicitNonce.Length + nonce_explicit_length];
+ byte[] nonce = new byte[this.encryptImplicitNonce.Length + 8];
Array.Copy(encryptImplicitNonce, 0, nonce, 0, encryptImplicitNonce.Length);
/*
- * RFC 5288/6655 The nonce_explicit MAY be the 64-bit sequence number.
+ * 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).
*/
@@ -102,9 +123,12 @@ namespace Org.BouncyCastle.Crypto.Tls
int plaintextLength = len;
int ciphertextLength = encryptCipher.GetOutputSize(plaintextLength);
- byte[] output = new byte[nonce_explicit_length + ciphertextLength];
- Array.Copy(nonce, encryptImplicitNonce.Length, output, 0, nonce_explicit_length);
- int outputPos = nonce_explicit_length;
+ byte[] output = new byte[record_iv_length + ciphertextLength];
+ if (record_iv_length != 0)
+ {
+ Array.Copy(nonce, nonce.Length - record_iv_length, output, 0, record_iv_length);
+ }
+ int outputPos = record_iv_length;
byte[] additionalData = GetAdditionalData(seqNo, type, plaintextLength);
AeadParameters parameters = new AeadParameters(null, 8 * macSize, nonce, additionalData);
@@ -135,12 +159,20 @@ namespace Org.BouncyCastle.Crypto.Tls
if (GetPlaintextLimit(len) < 0)
throw new TlsFatalAlert(AlertDescription.decode_error);
- byte[] nonce = new byte[this.decryptImplicitNonce.Length + nonce_explicit_length];
+ 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);
+ //Array.Copy(ciphertext, offset, nonce, decryptImplicitNonce.Length, nonce_explicit_length);
+ if (record_iv_length == 0)
+ {
+ TlsUtilities.WriteUint64(seqNo, nonce, decryptImplicitNonce.Length);
+ }
+ else
+ {
+ Array.Copy(ciphertext, offset, nonce, nonce.Length - record_iv_length, record_iv_length);
+ }
- int ciphertextOffset = offset + nonce_explicit_length;
- int ciphertextLength = len - nonce_explicit_length;
+ int ciphertextOffset = offset + record_iv_length;
+ int ciphertextLength = len - record_iv_length;
int plaintextLength = decryptCipher.GetOutputSize(ciphertextLength);
byte[] output = new byte[plaintextLength];
|