1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 // 6 // This file is one of a group of files (AesCng.cs, TripleDESCng.cs) that are almost identical except 7 // for the algorithm name. If you make a change to this file, there's a good chance you'll have to make 8 // the same change to the other files so please check. This is a pain but given that the contracts demand 9 // that each of these derive from a different class, it can't be helped. 10 // 11 12 using Internal.Cryptography; 13 using Internal.NativeCrypto; 14 15 namespace System.Security.Cryptography 16 { 17 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350")] // We are providing the implementation for 3DES not consuming it 18 public sealed class TripleDESCng : TripleDES, ICngSymmetricAlgorithm 19 { TripleDESCng()20 public TripleDESCng() 21 { 22 _core = new CngSymmetricAlgorithmCore(this); 23 } 24 TripleDESCng(string keyName)25 public TripleDESCng(string keyName) 26 : this(keyName, CngProvider.MicrosoftSoftwareKeyStorageProvider) 27 { 28 } 29 TripleDESCng(string keyName, CngProvider provider)30 public TripleDESCng(string keyName, CngProvider provider) 31 : this(keyName, provider, CngKeyOpenOptions.None) 32 { 33 } 34 TripleDESCng(string keyName, CngProvider provider, CngKeyOpenOptions openOptions)35 public TripleDESCng(string keyName, CngProvider provider, CngKeyOpenOptions openOptions) 36 { 37 _core = new CngSymmetricAlgorithmCore(this, keyName, provider, openOptions); 38 } 39 40 public override byte[] Key 41 { 42 get 43 { 44 return _core.GetKeyIfExportable(); 45 } 46 set 47 { 48 _core.SetKey(value); 49 } 50 } 51 52 public override int KeySize 53 { 54 get 55 { 56 return base.KeySize; 57 } 58 59 set 60 { 61 _core.SetKeySize(value, this); 62 } 63 } 64 CreateDecryptor()65 public override ICryptoTransform CreateDecryptor() 66 { 67 // Do not change to CreateDecryptor(this.Key, this.IV). this.Key throws if a non-exportable hardware key is being used. 68 return _core.CreateDecryptor(); 69 } 70 CreateDecryptor(byte[] rgbKey, byte[] rgbIV)71 public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV) 72 { 73 return _core.CreateDecryptor(rgbKey, rgbIV); 74 } 75 CreateEncryptor()76 public override ICryptoTransform CreateEncryptor() 77 { 78 // Do not change to CreateEncryptor(this.Key, this.IV). this.Key throws if a non-exportable hardware key is being used. 79 return _core.CreateEncryptor(); 80 } 81 CreateEncryptor(byte[] rgbKey, byte[] rgbIV)82 public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV) 83 { 84 return _core.CreateEncryptor(rgbKey, rgbIV); 85 } 86 GenerateKey()87 public override void GenerateKey() 88 { 89 _core.GenerateKey(); 90 } 91 GenerateIV()92 public override void GenerateIV() 93 { 94 _core.GenerateIV(); 95 } 96 Dispose(bool disposing)97 protected override void Dispose(bool disposing) 98 { 99 base.Dispose(disposing); 100 } 101 102 byte[] ICngSymmetricAlgorithm.BaseKey { get { return base.Key; } set { base.Key = value; } } 103 int ICngSymmetricAlgorithm.BaseKeySize { get { return base.KeySize; } set { base.KeySize = value; } } 104 ICngSymmetricAlgorithm.IsWeakKey(byte[] key)105 bool ICngSymmetricAlgorithm.IsWeakKey(byte[] key) 106 { 107 return TripleDES.IsWeakKey(key); 108 } 109 ICngSymmetricAlgorithm.GetEphemeralModeHandle()110 SafeAlgorithmHandle ICngSymmetricAlgorithm.GetEphemeralModeHandle() 111 { 112 return TripleDesBCryptModes.GetSharedHandle(Mode); 113 } 114 ICngSymmetricAlgorithm.GetNCryptAlgorithmIdentifier()115 string ICngSymmetricAlgorithm.GetNCryptAlgorithmIdentifier() 116 { 117 return Interop.NCrypt.NCRYPT_3DES_ALGORITHM; 118 } 119 ICngSymmetricAlgorithm.PreprocessKey(byte[] key)120 byte[] ICngSymmetricAlgorithm.PreprocessKey(byte[] key) 121 { 122 if (key.Length == 16) 123 { 124 // Cng does not support Two-Key Triple DES, so manually support it here for consistency with System.Security.Cryptography.Algorithms. 125 // Two-Key Triple DES contains two 8-byte keys {K1}{K2} with {K1} appended to make {K1}{K2}{K1}. 126 byte[] newkey = new byte[24]; 127 Array.Copy(key, 0, newkey, 0, 16); 128 Array.Copy(key, 0, newkey, 16, 8); 129 return newkey; 130 } 131 132 return key; 133 } 134 135 private CngSymmetricAlgorithmCore _core; 136 } 137 } 138