Exemplo n.º 1
0
        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));
        }
Exemplo n.º 2
0
        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));
        }
Exemplo n.º 3
0
        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));
            }
        }
Exemplo n.º 4
0
        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));
        }
Exemplo n.º 5
0
        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));
        }
Exemplo n.º 6
0
        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)));
        }
Exemplo n.º 7
0
        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"));
        }