Beispiel #1
0
        private void MacTest(byte[] Key, byte[] Input, byte[] Expected)
        {
            byte[] hash = new byte[16];

            using (CMAC mac = new CMAC(new RHX()))
            {
                mac.Initialize(Key, null);
                mac.BlockUpdate(Input, 0, Input.Length);
                mac.DoFinal(hash, 0);
            }

            if (!Evaluate.AreEqual(Expected, hash))
            {
                throw new Exception("CMAC is not equal! Expected: " + HexConverter.ToString(Expected) + " Received: " + HexConverter.ToString(hash));
            }
        }
Beispiel #2
0
        private void CmacDescriptionTest()
        {
            CSPPrng rng = new CSPPrng();

            byte[] data = rng.GetBytes(rng.Next(100, 400));
            byte[] key  = rng.GetBytes(32);
            byte[] iv   = rng.GetBytes(16);
            CMAC   mac  = new CMAC(BlockCiphers.Rijndael);

            mac.Initialize(key, iv);
            byte[]         c1  = mac.ComputeMac(data);
            MacDescription mds = new MacDescription(32, BlockCiphers.Rijndael, IVSizes.V128, BlockSizes.B128, RoundCounts.R14);
            MacStream      mst = new MacStream(mds, new KeyParams(key, iv));

            mst.Initialize(new MemoryStream(data));
            byte[] c2 = mst.ComputeMac();

            if (!Evaluate.AreEqual(c1, c2))
            {
                throw new Exception("MacStreamTest: CMAC code arrays are not equal!");
            }
        }
Beispiel #3
0
        private void Process(ReadOnlySpan <byte> nonce, ReadOnlySpan <byte> input, Span <byte> output, Span <byte> tag, ReadOnlySpan <byte> associatedData, bool outputIsCiphertext)
        {
            using var encryptor = aes.CreateEncryptor();
            var tmp               = CryptoPool.Rent(16);
            var counter           = CryptoPool.Rent(16);
            var counterEnc        = CryptoPool.Rent(16);
            var nonceMac          = CryptoPool.Rent(16);
            var associatedDataMac = CryptoPool.Rent(16);
            var ciphertextMac     = CryptoPool.Rent(16);

            try
            {
                CryptographicOperations.ZeroMemory(tmp.AsSpan(0, 15));
                tmp[15] = 0; // N tag
                cmac.TransformBlock(tmp, 0, 16, null, 0);
                cmac.TryComputeHash(nonce, nonceMac, out var _);

                tmp[15] = 1; // H tag
                cmac.TransformBlock(tmp, 0, 16, null, 0);
                cmac.TryComputeHash(associatedData, associatedDataMac, out var _);

                cmac.Initialize();
                tmp[15] = 2; // C tag
                cmac.TransformBlock(tmp, 0, 16, null, 0);

                nonceMac.AsSpan().CopyTo(counter);
                while (input.Length >= 16)
                {
                    encryptor.TransformBlock(counter, 0, 16, counterEnc, 0);
                    if (outputIsCiphertext)
                    {
                        for (int i = 0; i < 16; i++)
                        {
                            tmp[i] = (byte)(input[i] ^ counterEnc[i]);
                        }
                        cmac.TransformBlock(tmp, 0, 16, null, 0);
                        tmp.AsSpan(0, 16).CopyTo(output);
                    }
                    else
                    {
                        input.Slice(0, 16).CopyTo(tmp);
                        cmac.TransformBlock(tmp, 0, 16, null, 0);
                        for (int i = 0; i < 16; i++)
                        {
                            output[i] = (byte)(input[i] ^ counterEnc[i]);
                        }
                    }
                    byte add = 1;
                    for (int i = 15; i >= 0; i--)
                    {
                        counter[i] += add;
                        add         = counter[i] == 0 ? 1 : 0;
                    }
                    input  = input.Slice(16);
                    output = output.Slice(16);
                }

                if (input.Length > 0)
                {
                    encryptor.TransformBlock(counter, 0, 16, counterEnc, 0);
                    if (outputIsCiphertext)
                    {
                        for (int i = 0; i < input.Length; i++)
                        {
                            tmp[i] = (byte)(input[i] ^ counterEnc[i]);
                        }
                        cmac.TransformBlock(tmp, 0, input.Length, null, 0);
                        tmp.AsSpan(0, input.Length).CopyTo(output);
                    }
                    else
                    {
                        input.CopyTo(tmp);
                        cmac.TransformBlock(tmp, 0, input.Length, null, 0);
                        for (int i = 0; i < input.Length; i++)
                        {
                            output[i] = (byte)(input[i] ^ counterEnc[i]);
                        }
                    }
                }

                cmac.TryComputeHash(Array.Empty <byte>(), ciphertextMac, out var _);

                for (int i = 0; i < tag.Length; i++)
                {
                    tag[i] = (byte)(nonceMac[i] ^ associatedDataMac[i] ^ ciphertextMac[i]);
                }
            }
            finally
            {
                cmac.Initialize();
                CryptoPool.Return(tmp, 16);
                CryptoPool.Return(counter, 16);
                CryptoPool.Return(counterEnc, 16);
                CryptoPool.Return(nonceMac, 16);
                CryptoPool.Return(associatedDataMac, 16);
                CryptoPool.Return(ciphertextMac, 16);
            }
        }