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 using System; 6 using System.Diagnostics; 7 using System.Security.Cryptography; 8 9 namespace Internal.Cryptography 10 { 11 internal static class Helpers 12 { CloneByteArray(this byte[] src)13 public static byte[] CloneByteArray(this byte[] src) 14 { 15 if (src == null) 16 { 17 return null; 18 } 19 20 return (byte[])(src.Clone()); 21 } 22 CloneKeySizesArray(this KeySizes[] src)23 public static KeySizes[] CloneKeySizesArray(this KeySizes[] src) 24 { 25 return (KeySizes[])(src.Clone()); 26 } 27 UsesIv(this CipherMode cipherMode)28 public static bool UsesIv(this CipherMode cipherMode) 29 { 30 return cipherMode != CipherMode.ECB; 31 } 32 GetCipherIv(this CipherMode cipherMode, byte[] iv)33 public static byte[] GetCipherIv(this CipherMode cipherMode, byte[] iv) 34 { 35 if (cipherMode.UsesIv()) 36 { 37 if (iv == null) 38 { 39 throw new CryptographicException(SR.Cryptography_MissingIV); 40 } 41 42 return iv; 43 } 44 45 return null; 46 } 47 IsLegalSize(this int size, KeySizes[] legalSizes)48 public static bool IsLegalSize(this int size, KeySizes[] legalSizes) 49 { 50 for (int i = 0; i < legalSizes.Length; i++) 51 { 52 KeySizes currentSizes = legalSizes[i]; 53 54 // If a cipher has only one valid key size, MinSize == MaxSize and SkipSize will be 0 55 if (currentSizes.SkipSize == 0) 56 { 57 if (currentSizes.MinSize == size) 58 return true; 59 } 60 else if (size >= currentSizes.MinSize && size <= currentSizes.MaxSize) 61 { 62 // If the number is in range, check to see if it's a legal increment above MinSize 63 int delta = size - currentSizes.MinSize; 64 65 // While it would be unusual to see KeySizes { 10, 20, 5 } and { 11, 14, 1 }, it could happen. 66 // So don't return false just because this one doesn't match. 67 if (delta % currentSizes.SkipSize == 0) 68 { 69 return true; 70 } 71 } 72 } 73 return false; 74 } 75 GenerateRandom(int count)76 public static byte[] GenerateRandom(int count) 77 { 78 byte[] buffer = new byte[count]; 79 using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) 80 { 81 rng.GetBytes(buffer); 82 } 83 return buffer; 84 } 85 86 // encodes the integer i into a 4-byte array, in big endian. WriteInt(uint i, byte[] arr, int offset)87 public static void WriteInt(uint i, byte[] arr, int offset) 88 { 89 unchecked 90 { 91 Debug.Assert(arr != null); 92 Debug.Assert(arr.Length >= offset + sizeof(uint)); 93 94 arr[offset] = (byte)(i >> 24); 95 arr[offset + 1] = (byte)(i >> 16); 96 arr[offset + 2] = (byte)(i >> 8); 97 arr[offset + 3] = (byte)i; 98 } 99 } 100 FixupKeyParity(this byte[] key)101 public static byte[] FixupKeyParity(this byte[] key) 102 { 103 byte[] oddParityKey = new byte[key.Length]; 104 for (int index = 0; index < key.Length; index++) 105 { 106 // Get the bits we are interested in 107 oddParityKey[index] = (byte)(key[index] & 0xfe); 108 109 // Get the parity of the sum of the previous bits 110 byte tmp1 = (byte)((oddParityKey[index] & 0xF) ^ (oddParityKey[index] >> 4)); 111 byte tmp2 = (byte)((tmp1 & 0x3) ^ (tmp1 >> 2)); 112 byte sumBitsMod2 = (byte)((tmp2 & 0x1) ^ (tmp2 >> 1)); 113 114 // We need to set the last bit in oddParityKey[index] to the negation 115 // of the last bit in sumBitsMod2 116 if (sumBitsMod2 == 0) 117 oddParityKey[index] |= 1; 118 } 119 return oddParityKey; 120 } 121 ConvertIntToByteArray(uint value, byte[] dest)122 internal static void ConvertIntToByteArray(uint value, byte[] dest) 123 { 124 Debug.Assert(dest != null); 125 Debug.Assert(dest.Length == 4); 126 dest[0] = (byte)((value & 0xFF000000) >> 24); 127 dest[1] = (byte)((value & 0xFF0000) >> 16); 128 dest[2] = (byte)((value & 0xFF00) >> 8); 129 dest[3] = (byte)(value & 0xFF); 130 } 131 } 132 } 133 134