summary refs log tree commit diff
path: root/crypto/src/crypto/modes/KCcmBlockCipher.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/crypto/modes/KCcmBlockCipher.cs')
-rw-r--r--crypto/src/crypto/modes/KCcmBlockCipher.cs185
1 files changed, 175 insertions, 10 deletions
diff --git a/crypto/src/crypto/modes/KCcmBlockCipher.cs b/crypto/src/crypto/modes/KCcmBlockCipher.cs

index afa68a794..db86cf890 100644 --- a/crypto/src/crypto/modes/KCcmBlockCipher.cs +++ b/crypto/src/crypto/modes/KCcmBlockCipher.cs
@@ -248,6 +248,9 @@ namespace Org.BouncyCastle.Crypto.Modes Check.DataLength(input, inOff, len, "input buffer too short"); Check.OutputLength(output, outOff, len, "output buffer too short"); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return ProcessPacket(input.AsSpan(inOff, len), output.AsSpan(outOff)); +#else if (associatedText.Length > 0) { byte[] aad = associatedText.GetBuffer(); @@ -268,7 +271,7 @@ namespace Org.BouncyCastle.Crypto.Modes int totalLength = len; while (totalLength > 0) { - ProcessBlock(input, inOff, len, output, outOff); + ProcessBlock(input, inOff, output, outOff); totalLength -= engine.GetBlockSize(); inOff += engine.GetBlockSize(); outOff += engine.GetBlockSize(); @@ -302,7 +305,7 @@ namespace Org.BouncyCastle.Crypto.Modes for (int blockNum = 0; blockNum<blocks; blockNum++) { - ProcessBlock(input, inOff, len, output, outOff); + ProcessBlock(input, inOff, output, outOff); inOff += engine.GetBlockSize(); outOff += engine.GetBlockSize(); @@ -350,43 +353,190 @@ namespace Org.BouncyCastle.Crypto.Modes return len - macSize; } +#endif } - private void ProcessBlock(byte[] input, int inOff, int len, byte[] output, int outOff) +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public int ProcessPacket(ReadOnlySpan<byte> input, Span<byte> output) { + int len = input.Length; + Check.OutputLength(output, len, "output buffer too short"); + + if (associatedText.Length > 0) + { + byte[] aad = associatedText.GetBuffer(); + int aadLen = Convert.ToInt32(associatedText.Length); + + int dataLen = Convert.ToInt32(data.Length) - (forEncryption ? 0 : macSize); + + ProcessAAD(aad, 0, aadLen, dataLen); + } + + int blockSize = engine.GetBlockSize(), index = 0; + if (forEncryption) + { + Check.DataLength(len % blockSize != 0, "partial blocks not supported"); + + CalculateMac(input); + engine.ProcessBlock(nonce, s); + + int totalLength = len; + while (totalLength > 0) + { + ProcessBlock(input[index..], output[index..]); + totalLength -= blockSize; + index += blockSize; + } + + for (int byteIndex = 0; byteIndex < counter.Length; byteIndex++) + { + s[byteIndex] += counter[byteIndex]; + } + + engine.ProcessBlock(s, buffer); + + for (int byteIndex = 0; byteIndex < macSize; byteIndex++) + { + output[index + byteIndex] = (byte)(buffer[byteIndex] ^ macBlock[byteIndex]); + } + + Array.Copy(macBlock, 0, mac, 0, macSize); + + Reset(); + + return len + macSize; + } + else + { + Check.DataLength((len - macSize) % blockSize != 0, "partial blocks not supported"); + + engine.ProcessBlock(nonce, 0, s, 0); + + int blocks = len / engine.GetBlockSize(); + + for (int blockNum = 0; blockNum < blocks; blockNum++) + { + ProcessBlock(input[index..], output[index..]); + index += blockSize; + } + + if (len > index) + { + for (int byteIndex = 0; byteIndex < counter.Length; byteIndex++) + { + s[byteIndex] += counter[byteIndex]; + } + + engine.ProcessBlock(s, buffer); + + for (int byteIndex = 0; byteIndex < macSize; byteIndex++) + { + output[index + byteIndex] = (byte)(buffer[byteIndex] ^ input[index + byteIndex]); + } + index += macSize; + } + + for (int byteIndex = 0; byteIndex < counter.Length; byteIndex++) + { + s[byteIndex] += counter[byteIndex]; + } + + engine.ProcessBlock(s, buffer); + + output[(index - macSize)..index].CopyTo(buffer); + CalculateMac(output[..(index - macSize)]); + + Array.Copy(macBlock, 0, mac, 0, macSize); + + Span<byte> calculatedMac = stackalloc byte[macSize]; + + buffer.AsSpan(0, macSize).CopyTo(calculatedMac); + + if (!Arrays.ConstantTimeAreEqual(mac.AsSpan(0, macSize), calculatedMac)) + throw new InvalidCipherTextException("mac check failed"); + + Reset(); + + return len - macSize; + } + } +#endif + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + private void CalculateMac(ReadOnlySpan<byte> authText) + { + int blockSize = engine.GetBlockSize(); + + while (!authText.IsEmpty) + { + for (int byteIndex = 0; byteIndex < blockSize; byteIndex++) + { + macBlock[byteIndex] ^= authText[byteIndex]; + } + + engine.ProcessBlock(macBlock, macBlock); + + authText = authText[blockSize..]; + } + } + + private void ProcessBlock(ReadOnlySpan<byte> input, Span<byte> output) + { for (int byteIndex = 0; byteIndex < counter.Length; byteIndex++) { s[byteIndex] += counter[byteIndex]; } - engine.ProcessBlock(s, 0, buffer, 0); + engine.ProcessBlock(s, buffer); - for (int byteIndex = 0; byteIndex < engine.GetBlockSize(); byteIndex++) + int blockSize = engine.GetBlockSize(); + for (int byteIndex = 0; byteIndex < blockSize; byteIndex++) { - output[outOff + byteIndex] = (byte)(buffer[byteIndex] ^ input[inOff + byteIndex]); + output[byteIndex] = (byte)(buffer[byteIndex] ^ input[byteIndex]); } } - +#else private void CalculateMac(byte[] authText, int authOff, int len) { + int blockSize = engine.GetBlockSize(); int totalLen = len; while (totalLen > 0) { - for (int byteIndex = 0; byteIndex < engine.GetBlockSize(); byteIndex++) + for (int byteIndex = 0; byteIndex < blockSize; byteIndex++) { macBlock[byteIndex] ^= authText[authOff + byteIndex]; } engine.ProcessBlock(macBlock, 0, macBlock, 0); - totalLen -= engine.GetBlockSize(); - authOff += engine.GetBlockSize(); + totalLen -= blockSize; + authOff += blockSize; } } + private void ProcessBlock(byte[] input, int inOff, byte[] output, int outOff) + { + + for (int byteIndex = 0; byteIndex < counter.Length; byteIndex++) + { + s[byteIndex] += counter[byteIndex]; + } + + engine.ProcessBlock(s, 0, buffer, 0); + + for (int byteIndex = 0; byteIndex < engine.GetBlockSize(); byteIndex++) + { + output[outOff + byteIndex] = (byte)(buffer[byteIndex] ^ input[inOff + byteIndex]); + } + } +#endif + public virtual int DoFinal(byte[] output, int outOff) { +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return DoFinal(output.AsSpan(outOff)); +#else byte[] buf = data.GetBuffer(); int bufLen = Convert.ToInt32(data.Length); @@ -395,8 +545,23 @@ namespace Org.BouncyCastle.Crypto.Modes Reset(); return len; +#endif } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual int DoFinal(Span<byte> output) + { + byte[] buf = data.GetBuffer(); + int bufLen = Convert.ToInt32(data.Length); + + int len = ProcessPacket(buf.AsSpan(0, bufLen), output); + + Reset(); + + return len; + } +#endif + public virtual byte[] GetMac() { return Arrays.Clone(mac);