private SymmetricCipherAeadResult Decrypt(IAeadModeBlockCipherParameters param) { var ecbParams = new ModeBlockCipherParameters( BlockCipherDirections.Encrypt, param.Key, new BitString(_engine.BlockSizeBits) ); var ecb = _factory.GetStandardCipher(_engine, BlockCipherModesOfOperation.Ecb); var h = ecb.ProcessPayload(ecbParams); var j0 = _gcmInternals.Getj0(h.Result, param.Iv); var plainText = _gcmInternals.GCTR(_gcmInternals.inc_s(32, j0), param.Payload, param.Key); int u = 128 * plainText.BitLength.CeilingDivide(128) - plainText.BitLength; int v = 128 * param.AdditionalAuthenticatedData.BitLength.CeilingDivide(128) - param.AdditionalAuthenticatedData.BitLength; var decryptedBits = param.AdditionalAuthenticatedData.ConcatenateBits(new BitString(v)) .ConcatenateBits(param.Payload) .ConcatenateBits(new BitString(u)) .ConcatenateBits(BitString.To64BitString(param.AdditionalAuthenticatedData.BitLength)) .ConcatenateBits(BitString.To64BitString(param.Payload.BitLength)); var s = _gcmInternals.GHash(h.Result, decryptedBits); var tagPrime = _gcmInternals.GCTR(j0, s, param.Key).GetMostSignificantBits(param.Tag.BitLength); if (!param.Tag.Equals(tagPrime)) { return(new SymmetricCipherAeadResult(INVALID_TAG_MESSAGE)); } return(new SymmetricCipherAeadResult(plainText)); }
private SymmetricCipherAeadResult Encrypt(IAeadModeBlockCipherParameters param) { var ecbParams = new ModeBlockCipherParameters( BlockCipherDirections.Encrypt, param.Key, new BitString(_engine.BlockSizeBits) ); var ecb = _factory.GetStandardCipher(_engine, BlockCipherModesOfOperation.Ecb); var h = ecb.ProcessPayload(ecbParams); var j0 = _gcmInternals.Getj0(h.Result, param.Iv); var cipherText = _gcmInternals.GCTR(_gcmInternals.inc_s(32, j0), param.Payload, param.Key); int u = _engine.BlockSizeBits * cipherText.BitLength.CeilingDivide(_engine.BlockSizeBits) - cipherText.BitLength; int v = _engine.BlockSizeBits * param.AdditionalAuthenticatedData.BitLength.CeilingDivide(_engine.BlockSizeBits) - param.AdditionalAuthenticatedData.BitLength; var encryptedBits = param.AdditionalAuthenticatedData.ConcatenateBits(new BitString(v)) .ConcatenateBits(cipherText) .ConcatenateBits(new BitString(u)) .ConcatenateBits(BitString.To64BitString(param.AdditionalAuthenticatedData.BitLength)) .ConcatenateBits(BitString.To64BitString(cipherText.BitLength)); var s = _gcmInternals.GHash(h.Result, encryptedBits); var tag = _gcmInternals.GCTR(j0, s, param.Key).GetMostSignificantBits(param.TagLength); return(new SymmetricCipherAeadResult(cipherText, tag)); }
public SymmetricCipherAeadResult ProcessPayload(IAeadModeBlockCipherParameters param) { switch (param.Direction) { case BlockCipherDirections.Encrypt: return(Encrypt(param)); case BlockCipherDirections.Decrypt: return(Decrypt(param)); default: throw new ArgumentException(nameof(param.Direction)); } }
private SymmetricCipherAeadResult Encrypt(IAeadModeBlockCipherParameters param) { byte[] b = new byte[0]; byte[] ctr = new byte[_engine.BlockSizeBytes]; int r = 0; _ccmInternals.CCM_format_80211( ref b, param.Iv.ToBytes(), param.Iv.BitLength, param.Payload.ToBytes(), param.Payload.BitLength, param.AdditionalAuthenticatedData.ToBytes(), param.AdditionalAuthenticatedData.BitLength, param.TagLength, ref ctr, ref r ); // MAC b var cbcMacRijndael = _factory.GetStandardCipher(_engine, BlockCipherModesOfOperation.CbcMac); var cbcMacParam = new ModeBlockCipherParameters( BlockCipherDirections.Encrypt, new BitString(_engine.BlockSizeBits), param.Key, new BitString(b) ); var mac = new BitString(cbcMacRijndael.ProcessPayload(cbcMacParam) .Result .ToBytes() .Take(_engine.BlockSizeBytes) // mac is the first block .ToArray() ); // Encrypt Payload and MAC var counterRijndael = _factory.GetCounterCipher( _engine, new AdditiveCounter( _engine, new BitString(ctr) ) ); var counterParam = new ModeBlockCipherParameters( BlockCipherDirections.Encrypt, param.Key, mac ); // Tag - made up of the most significant bits of the length of the tag var T = counterRijndael.ProcessPayload(counterParam) .Result .GetMostSignificantBits(param.TagLength); int m = (param.Payload.BitLength + (_engine.BlockSizeBits - 1)) / _engine.BlockSizeBits; var payLoadAtBlockSize = param.Payload.ConcatenateBits( new BitString((m * _engine.BlockSizeBits) - param.Payload.BitLength) ); counterParam.Payload = payLoadAtBlockSize; // ct should be made up of the most significant bits of the length of the payload. BitString ct = m > 0 ? counterRijndael.ProcessPayload(counterParam).Result.GetMostSignificantBits(param.Payload.BitLength) : new BitString(0); // final return is made up of the CT contatenated with T return(new SymmetricCipherAeadResult(ct.ConcatenateBits(T), T)); }
private SymmetricCipherAeadResult Decrypt(IAeadModeBlockCipherParameters param) { byte[] ctr = null; int r = 0; _ccmInternals.CCM_counter_80211(param.Iv.ToBytes(), param.Iv.BitLength, ref ctr); // Decrypt cipherText and MAC int plen = param.Payload.BitLength - param.TagLength; int m = (plen + (_engine.BlockSizeBits - 1)) / _engine.BlockSizeBits + 1; // the length of encrypted payload + 1 block for MAC var tagPortion = new BitString( param.Payload.ToBytes() .Skip(plen / BITS_IN_BYTE) .Take(param.TagLength / BITS_IN_BYTE) .ToArray() ); var cipherTextPortion = new BitString( param.Payload.ToBytes().Take(plen / BITS_IN_BYTE).ToArray() ); // tagPortion should be exactly 16 bytes, bitString should be ended on a block boundary byte[] ct = tagPortion .ConcatenateBits( // add bits to hit the block byte boundary for tag new BitString(_engine.BlockSizeBits - tagPortion.BitLength) ) .ConcatenateBits(cipherTextPortion) .ConcatenateBits( new BitString( // Add bits to hit a block boundary (m * _engine.BlockSizeBits) - (_engine.BlockSizeBits + cipherTextPortion.BitLength) ) ) .ToBytes(); var counterRijndael = _factory.GetCounterCipher( _engine, new AdditiveCounter(_engine, new BitString(ctr)) ); var counterParam = new ModeBlockCipherParameters( BlockCipherDirections.Encrypt, param.Key, new BitString(ct) ); var pt = counterRijndael.ProcessPayload(counterParam); // Payload starts at 16th byte of PT var payload = new BitString(pt.Result.ToBytes().Skip(16).ToArray()); // The tag is the first Tlen/8 bytes of the PT var T = pt.Result.GetMostSignificantBits(param.TagLength); // Format the data byte[] b = null; _ccmInternals.CCM_format_80211( ref b, param.Iv.ToBytes(), param.Iv.BitLength, payload.ToBytes(), plen, param.AdditionalAuthenticatedData.ToBytes(), param.AdditionalAuthenticatedData.BitLength, param.TagLength, ref ctr, ref r ); // Calculate the MAC BitString iv = new BitString(_engine.BlockSizeBits); var cbcMacRijndael = _factory.GetStandardCipher(_engine, BlockCipherModesOfOperation.CbcMac); var macParam = new ModeBlockCipherParameters( BlockCipherDirections.Encrypt, iv, param.Key, new BitString(b) ); var mac = cbcMacRijndael.ProcessPayload(macParam); // Check calculated tag equals provided tag if (!mac.Result.GetMostSignificantBits(param.TagLength).Equals( T.GetMostSignificantBits(param.TagLength) )) { return(new SymmetricCipherAeadResult(INVALID_TAG_MESSAGE)); } return(new SymmetricCipherAeadResult(payload)); }
private SymmetricCipherAeadResult Encrypt(IAeadModeBlockCipherParameters param) { // Artificial limit. Specification has 2^36, but testing doesn't need that length. if (param.Payload.BitLength > 65536) { return(new SymmetricCipherAeadResult("Plaintext too long to encrypt. Must be under 65536 bits")); } if (param.Payload.BitLength % 8 != 0) { return(new SymmetricCipherAeadResult("Plaintext must be on a byte boundary")); } // Artificial limit. Specification has 2^36, but testing doesn't need that length. if (param.AdditionalAuthenticatedData.BitLength > 65536) { return(new SymmetricCipherAeadResult("AAD too long to encrypt. Must be under 65536 bits")); } if (param.AdditionalAuthenticatedData.BitLength % 8 != 0) { return(new SymmetricCipherAeadResult("AAD must be on a byte boundary")); } var(messageAuthKey, messageEncKey) = DeriveKeys(param.Key, param.Iv); var lengthBlock = LittleEndianify(BitString.To64BitString(param.AdditionalAuthenticatedData.BitLength)) .ConcatenateBits(LittleEndianify(BitString.To64BitString(param.Payload.BitLength))); var paddedPlaintext = RightPadToMultipleOf16Bytes(param.Payload); var paddedAad = RightPadToMultipleOf16Bytes(param.AdditionalAuthenticatedData); var polyValInput = paddedAad.ConcatenateBits(paddedPlaintext).ConcatenateBits(lengthBlock); var S_s = PolyVal(messageAuthKey, polyValInput).ToBytes(); var nonceBytes = param.Iv.ToBytes(); for (var i = 0; i < 12; i++) { S_s[i] ^= nonceBytes[i]; } S_s[15] &= 0x7f; var S_sBitString = new BitString(S_s); if (S_sBitString.BitLength % _engine.BlockSizeBits != 0) { return(new SymmetricCipherAeadResult("S BitString was not a multiple of the block size")); } var ecb = _factory.GetStandardCipher(_engine, BlockCipherModesOfOperation.Ecb); var tag = ecb.ProcessPayload ( new ModeBlockCipherParameters ( BlockCipherDirections.Encrypt, messageEncKey, S_sBitString ) ); if (!tag.Success) { return(new SymmetricCipherAeadResult("Unable to create tag")); } var counterBlock = tag.Result.ToBytes(); counterBlock[15] |= 0x80; var counterBitString = new BitString(counterBlock); var result = AesCtr(messageEncKey, counterBitString, param.Payload); return(new SymmetricCipherAeadResult(result.ConcatenateBits(tag.Result))); }
private SymmetricCipherAeadResult Decrypt(IAeadModeBlockCipherParameters param) { if (param.Payload.BitLength < 16 || param.Payload.BitLength > 65536 + 16) { return(new SymmetricCipherAeadResult("Ciphertext is too long or too short.")); } if (param.AdditionalAuthenticatedData.BitLength > 65536) { return(new SymmetricCipherAeadResult("AAD is too long")); } var(messageAuthKey, messageEncKey) = DeriveKeys(param.Key, param.Iv); var tag = param.Payload.Substring(0, 16 * 8); var cipherText = new BitString(0); if (tag.BitLength != param.Payload.BitLength) { cipherText = param.Payload.MSBSubstring(0, param.Payload.BitLength - tag.BitLength); } var counterBlock = tag.ToBytes(); counterBlock[15] |= 0x80; var counterBitString = new BitString(counterBlock); if (cipherText.BitLength % 8 != 0) { return(new SymmetricCipherAeadResult("Ciphertext was not a multiple of bytes")); } var plainText = AesCtr(messageEncKey, counterBitString, cipherText); var lengthBlock = LittleEndianify(BitString.To64BitString(param.AdditionalAuthenticatedData.BitLength)) .ConcatenateBits(LittleEndianify(BitString.To64BitString(plainText.BitLength))); var paddedPlaintext = RightPadToMultipleOf16Bytes(plainText); var paddedAad = RightPadToMultipleOf16Bytes(param.AdditionalAuthenticatedData); var polyValInput = paddedAad.ConcatenateBits(paddedPlaintext).ConcatenateBits(lengthBlock); var S_s = PolyVal(messageAuthKey, polyValInput).ToBytes(); var nonceBytes = param.Iv.ToBytes(); for (var i = 0; i < 12; i++) { S_s[i] ^= nonceBytes[i]; } S_s[15] &= 0x7f; var S_sBitString = new BitString(S_s); if (S_sBitString.BitLength % _engine.BlockSizeBits != 0) { return(new SymmetricCipherAeadResult("S BitString was not a multiple of the block size")); } var ecb = _factory.GetStandardCipher(_engine, BlockCipherModesOfOperation.Ecb); var expectedTag = ecb.ProcessPayload ( new ModeBlockCipherParameters ( BlockCipherDirections.Encrypt, messageEncKey, S_sBitString ) ); return(expectedTag.Result.Equals(tag) ? new SymmetricCipherAeadResult(plainText) : new SymmetricCipherAeadResult("Tags do not match")); }