< Summary

Class:Microsoft.Azure.KeyVault.Cryptography.Algorithms.AesCbcHmacSha2
Assembly:Microsoft.Azure.KeyVault.Cryptography
File(s):C:\Git\azure-sdk-for-net\sdk\keyvault\Microsoft.Azure.KeyVault.Cryptography\src\Algorithms\AesCbcHmacSha2.cs
Covered lines:101
Uncovered lines:27
Coverable lines:128
Total lines:374
Line coverage:78.9% (101 of 128)
Covered branches:34
Total branches:46
Branch coverage:73.9% (34 of 46)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
Create(...)-100%100%
.ctor(...)-100%100%
CreateDecryptor(...)-55.56%50%
CreateEncryptor(...)-57.14%50%
GetAlgorithmParameters(...)-84%66.67%
.ctor(...)-100%100%
get_Tag()-100%100%
get_CanReuseTransform()-0%100%
get_CanTransformMultipleBlocks()-0%100%
get_InputBlockSize()-0%100%
get_OutputBlockSize()-0%100%
TransformBlock(...)-0%100%
TransformFinalBlock(...)-100%100%
Dispose()-100%100%
Dispose(...)-100%100%
.ctor(...)-100%100%
get_Tag()-100%100%
get_CanReuseTransform()-0%100%
get_CanTransformMultipleBlocks()-0%100%
get_InputBlockSize()-0%100%
get_OutputBlockSize()-0%100%
TransformBlock(...)-0%100%
TransformFinalBlock(...)-85.71%50%
Dispose()-100%100%
Dispose(...)-100%100%
ConvertToBigEndian(...)-100%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\keyvault\Microsoft.Azure.KeyVault.Cryptography\src\Algorithms\AesCbcHmacSha2.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License. See License.txt in the project root for
 3// license information.
 4
 5using System;
 6using System.Globalization;
 7using System.Security.Cryptography;
 8
 9namespace Microsoft.Azure.KeyVault.Cryptography.Algorithms
 10{
 11    /// <summary>
 12    /// Abstract base class for AESCBC-HMAC algorithms.
 13    /// </summary>
 14    public abstract class AesCbcHmacSha2 : SymmetricEncryptionAlgorithm
 15    {
 16        internal static Aes Create( byte[] key, byte[] iv )
 17        {
 1218            var aes = Aes.Create();
 19
 1220            aes.Mode    = CipherMode.CBC;
 1221            aes.Padding = PaddingMode.PKCS7;
 1222            aes.KeySize = key.Length * 8;
 1223            aes.Key     = key;
 1224            aes.IV      = iv;
 25
 1226            return aes;
 27        }
 28        protected AesCbcHmacSha2( string name )
 1229            : base( name )
 30        {
 1231        }
 32
 33        public override ICryptoTransform CreateDecryptor( byte[] key, byte[] iv, byte[] authenticationData, byte[] authe
 34        {
 635            if ( key == null )
 036                throw new CryptographicException( "No key material" );
 37
 638            if ( iv == null )
 039                throw new CryptographicException( "No initialization vector" );
 40
 641            if ( authenticationData == null )
 042                throw new CryptographicException( "No authentication data" );
 43
 644            if ( authenticationTag == null )
 045                throw new CryptographicException( "No authentication tag" );
 46
 47            // Create the Decryptor
 648            return new AesCbcHmacSha2Decryptor( Name, key, iv, authenticationData, authenticationTag );
 49        }
 50
 51        public override ICryptoTransform CreateEncryptor( byte[] key, byte[] iv, byte[] authenticationData )
 52        {
 653            if ( key == null )
 054                throw new CryptographicException( "No key material" );
 55
 656            if ( iv == null )
 057                throw new CryptographicException( "No initialization vector" );
 58
 659            if ( authenticationData == null )
 060                throw new CryptographicException( "No authentication data" );
 61
 62            // Create the Encryptor
 663            return new AesCbcHmacSha2Encryptor( Name, key, iv, authenticationData );
 64        }
 65
 66        private static void GetAlgorithmParameters( string algorithm, byte[] key, out byte[] aes_key, out byte[] hmac_ke
 67        {
 68            switch ( algorithm )
 69            {
 70                case Aes128CbcHmacSha256.AlgorithmName:
 71                    {
 472                        if ( ( key.Length << 3 ) < 256 )
 073                            throw new CryptographicException( string.Format( CultureInfo.CurrentCulture, "{0} key length
 74
 475                        hmac_key = new byte[128 >> 3];
 476                        aes_key  = new byte[128 >> 3];
 477                        Array.Copy( key, hmac_key, 128 >> 3 );
 478                        Array.Copy( key, 128 >> 3, aes_key, 0, 128 >> 3 );
 79
 480                        hmac = IncrementalHash.CreateHMAC( HashAlgorithmName.SHA256, hmac_key );
 81
 482                        break;
 83                    }
 84
 85                case Aes192CbcHmacSha384.AlgorithmName:
 86                    {
 487                        if ( ( key.Length << 3 ) < 384 )
 088                            throw new CryptographicException( string.Format( CultureInfo.CurrentCulture, "{0} key length
 89
 490                        hmac_key = new byte[192 >> 3];
 491                        aes_key  = new byte[192 >> 3];
 492                        Array.Copy( key, hmac_key, 192 >> 3 );
 493                        Array.Copy( key, 192 >> 3, aes_key, 0, 192 >> 3 );
 94
 495                        hmac = IncrementalHash.CreateHMAC( HashAlgorithmName.SHA384, hmac_key );
 96
 497                        break;
 98                    }
 99
 100                case Aes256CbcHmacSha512.AlgorithmName:
 101                    {
 4102                        if ( ( key.Length << 3 ) < 512 )
 0103                            throw new CryptographicException( string.Format( CultureInfo.CurrentCulture, "{0} key length
 104
 4105                        hmac_key = new byte[256 >> 3];
 4106                        aes_key  = new byte[256 >> 3];
 4107                        Array.Copy( key, hmac_key, 256 >> 3 );
 4108                        Array.Copy( key, 256 >> 3, aes_key, 0, 256 >> 3 );
 109
 4110                        hmac = IncrementalHash.CreateHMAC( HashAlgorithmName.SHA512, hmac_key );
 111
 4112                        break;
 113                    }
 114
 115                default:
 116                    {
 0117                        throw new CryptographicException( string.Format( CultureInfo.CurrentCulture, "Unsupported algori
 118                    }
 119            }
 120        }
 121
 122        class AesCbcHmacSha2Encryptor : IAuthenticatedCryptoTransform
 123        {
 124            readonly byte[]  _hmac_key;
 125
 126            readonly byte[]  _associated_data_length;
 127
 128            Aes              _aes;
 129            IncrementalHash  _hmac;
 130
 131            ICryptoTransform _inner;
 132            byte[]           _tag;
 133
 6134            internal AesCbcHmacSha2Encryptor( string name, byte[] key, byte[] iv, byte[] associatedData )
 135            {
 136                // Split the key to get the AES key, the HMAC key and the HMAC object
 137                byte[] aesKey;
 138
 6139                GetAlgorithmParameters( name, key, out aesKey, out _hmac_key, out _hmac );
 140
 141                // Create the AES provider
 6142                _aes = AesCbcHmacSha2.Create( aesKey, iv );
 143
 6144                _inner = _aes.CreateEncryptor();
 145
 6146                _associated_data_length = ConvertToBigEndian( associatedData.Length * 8 );
 147
 148                // Prime the hash.
 6149                _hmac.AppendData( associatedData );
 6150                _hmac.AppendData( iv );
 6151            }
 152
 153            public byte[] Tag
 154            {
 6155                get { return _tag; }
 156            }
 157
 158            public bool CanReuseTransform
 159            {
 0160              get { return _inner.CanReuseTransform; }
 161            }
 162
 163            public bool CanTransformMultipleBlocks
 164            {
 0165              get { return _inner.CanTransformMultipleBlocks; }
 166            }
 167
 168            public int InputBlockSize
 169            {
 0170              get { return _inner.InputBlockSize; }
 171            }
 172
 173            public int OutputBlockSize
 174            {
 0175              get { return _inner.OutputBlockSize; }
 176            }
 177
 178            public int TransformBlock( byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int out
 179            {
 180                // Encrypt the block
 0181                var result = _inner.TransformBlock( inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset );
 182
 183                // TODO: This is an inefficient copy
 0184                var data = outputBuffer.Take( outputOffset, result );
 185
 186                // Add it to the running hash
 0187                _hmac.AppendData( data );
 188
 0189                return result;
 190            }
 191
 192            public byte[] TransformFinalBlock( byte[] inputBuffer, int inputOffset, int inputCount )
 193            {
 194                // Encrypt the block
 6195                var result = _inner.TransformFinalBlock( inputBuffer, inputOffset, inputCount );
 196
 197                // Add it to the running hash
 6198                _hmac.AppendData( result );
 199
 200                // Add the associated_data_length bytes to the hash
 6201                _hmac.AppendData( _associated_data_length );
 202
 203                // Compute the tag
 6204                _tag = _hmac.GetHashAndReset().Take( _hmac_key.Length );
 205
 6206                return result;
 207            }
 208
 209            public void Dispose()
 210            {
 6211              Dispose( true );
 6212               GC.SuppressFinalize( this );
 6213            }
 214
 215            protected virtual void Dispose( bool disposing )
 216            {
 6217                if ( disposing )
 218                {
 6219                    if ( _inner != null )
 220                    {
 6221                        _inner.Dispose();
 6222                        _inner = null;
 223                    }
 224
 6225                    if ( _hmac != null )
 226                    {
 6227                        _hmac.Dispose();
 6228                        _hmac = null;
 229                    }
 230
 6231                    if ( _aes != null )
 232                    {
 6233                        _aes.Dispose();
 6234                        _aes = null;
 235                    }
 236                }
 6237            }
 238        }
 239
 240        class AesCbcHmacSha2Decryptor : IAuthenticatedCryptoTransform
 241        {
 242            readonly byte[]  _hmac_key;
 243
 244            readonly byte[]  _associated_data_length;
 245
 246            Aes              _aes;
 247            IncrementalHash  _hmac;
 248
 249            ICryptoTransform _inner;
 250            byte[]           _tag;
 251
 6252            internal AesCbcHmacSha2Decryptor( string name, byte[] key, byte[] iv, byte[] associatedData, byte[] authenti
 253            {
 254                // Split the key to get the AES key, the HMAC key and the HMAC object
 255                byte[] aesKey;
 256
 6257                GetAlgorithmParameters( name, key, out aesKey, out _hmac_key, out _hmac );
 258
 259                // Record the tag
 6260                _tag   = authenticationTag;
 261
 262                // Create the AES provider
 6263                _aes   = AesCbcHmacSha2.Create( aesKey, iv );
 6264                _inner = _aes.CreateDecryptor();
 265
 6266                _associated_data_length = ConvertToBigEndian( associatedData.Length * 8 );
 267
 268                // Prime the hash.
 6269                _hmac.AppendData( associatedData );
 6270                _hmac.AppendData( iv );
 6271            }
 272
 273            public byte[] Tag
 274            {
 6275                get { return _tag; }
 276            }
 277
 278            public bool CanReuseTransform
 279            {
 0280              get { return _inner.CanReuseTransform; }
 281            }
 282
 283            public bool CanTransformMultipleBlocks
 284            {
 0285              get { return _inner.CanTransformMultipleBlocks; }
 286            }
 287
 288            public int InputBlockSize
 289            {
 0290              get { return _inner.InputBlockSize; }
 291            }
 292
 293            public int OutputBlockSize
 294            {
 0295              get { return _inner.OutputBlockSize; }
 296            }
 297
 298            public int TransformBlock( byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int out
 299            {
 300                // TODO: This is an inefficient copy
 0301                var block = inputBuffer.Take( inputOffset, inputCount );
 302
 303                // Add the cipher text to the running hash
 0304                _hmac.AppendData( block );
 305
 306                // Decrypt the cipher text
 0307                return _inner.TransformBlock( inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset );
 308            }
 309
 310            public byte[] TransformFinalBlock( byte[] inputBuffer, int inputOffset, int inputCount )
 311            {
 312                // TODO: This is an inefficient copy
 6313                var block = inputBuffer.Take( inputOffset, inputCount );
 314
 315                // Add the cipher text to the running hash
 6316                _hmac.AppendData( block );
 317
 318                // Add the associated_data_length bytes to the hash
 6319                _hmac.AppendData( _associated_data_length );
 320
 321                // Compute the tag, then compare it against the expected value
 322                // perform transforming the final block
 6323                var tag = _hmac.GetHashAndReset().Take( _hmac_key.Length );
 324
 6325                if ( !tag.SequenceEqualConstantTime( _tag ) )
 0326                    throw new CryptographicException( "Data is no authentic" );
 327
 6328                return _inner.TransformFinalBlock( inputBuffer, inputOffset, inputCount );
 329            }
 330
 331            public void Dispose()
 332            {
 6333                Dispose( true );
 6334                GC.SuppressFinalize( this );
 6335            }
 336
 337            protected virtual void Dispose( bool disposing )
 338            {
 6339                if ( disposing )
 340                {
 6341                    if ( _inner != null )
 342                    {
 6343                        _inner.Dispose();
 6344                        _inner = null;
 345                    }
 346
 6347                    if ( _hmac != null )
 348                    {
 6349                        _hmac.Dispose();
 6350                        _hmac = null;
 351                    }
 352
 6353                    if ( _aes != null )
 354                    {
 6355                        _aes.Dispose();
 6356                        _aes = null;
 357                    }
 358                }
 6359            }
 360        }
 361
 362        static byte[] ConvertToBigEndian( Int64 i )
 363        {
 12364            byte[] temp = BitConverter.GetBytes( i );
 365
 12366            if ( BitConverter.IsLittleEndian )
 367            {
 12368                Array.Reverse( temp );
 369            }
 370
 12371            return temp;
 372        }
 373    }
 374}