/// <summary> /// Decrypt the keys that need to be sent to the enclave /// </summary> /// <param name="keysTobeSentToEnclave">Keys that need to sent to the enclave</param> /// <param name="serverName"></param> /// <returns></returns> private List <ColumnEncryptionKeyInfo> GetDecryptedKeysToBeSentToEnclave(Dictionary <int, SqlTceCipherInfoEntry> keysTobeSentToEnclave, string serverName) { List <ColumnEncryptionKeyInfo> decryptedKeysToBeSentToEnclave = new List <ColumnEncryptionKeyInfo>(); foreach (SqlTceCipherInfoEntry cipherInfo in keysTobeSentToEnclave.Values) { SqlClientSymmetricKey sqlClientSymmetricKey = null; SqlEncryptionKeyInfo? encryptionkeyInfoChosen = null; SqlSecurityUtility.DecryptSymmetricKey(cipherInfo, serverName, out sqlClientSymmetricKey, out encryptionkeyInfoChosen); if (sqlClientSymmetricKey == null) { throw SQL.NullArgumentInternal("sqlClientSymmetricKey", ClassName, GetDecryptedKeysToBeSentToEnclaveName); } if (cipherInfo.ColumnEncryptionKeyValues == null) { throw SQL.NullArgumentInternal("ColumnEncryptionKeyValues", ClassName, GetDecryptedKeysToBeSentToEnclaveName); } if (!(cipherInfo.ColumnEncryptionKeyValues.Count > 0)) { throw SQL.ColumnEncryptionKeysNotFound(); } //cipherInfo.CekId is always 0, hence used cipherInfo.ColumnEncryptionKeyValues[0].cekId. Even when cek has multiple ColumnEncryptionKeyValues //the cekid and the plaintext value will remain the same, what varies is the encrypted cek value, since the cek can be encrypted by //multiple CMKs decryptedKeysToBeSentToEnclave.Add(new ColumnEncryptionKeyInfo(sqlClientSymmetricKey.RootKey, cipherInfo.ColumnEncryptionKeyValues[0].databaseId, cipherInfo.ColumnEncryptionKeyValues[0].cekMdVersion, cipherInfo.ColumnEncryptionKeyValues[0].cekId)); } return(decryptedKeysToBeSentToEnclave); }
/// <summary> /// Constructor. /// </summary> /// <param name="sqlTceCipherInfoEntry"></param> /// <param name="ordinal"></param> /// <param name="cipherAlgorithmId"></param> /// <param name="cipherAlgorithmName"></param> /// <param name="encryptionType"></param> /// <param name="normalizationRuleVersion"></param> internal SqlCipherMetadata(SqlTceCipherInfoEntry?sqlTceCipherInfoEntry, ushort ordinal, byte cipherAlgorithmId, string cipherAlgorithmName, byte encryptionType, byte normalizationRuleVersion) { Debug.Assert(!sqlTceCipherInfoEntry.Equals(default(SqlTceCipherInfoEntry)), "sqlTceCipherInfoEntry should not be un-initialized."); _sqlTceCipherInfoEntry = sqlTceCipherInfoEntry; _ordinal = ordinal; _cipherAlgorithmId = cipherAlgorithmId; _cipherAlgorithmName = cipherAlgorithmName; _encryptionType = encryptionType; _normalizationRuleVersion = normalizationRuleVersion; _sqlEncryptionKeyInfo = null; }
/// <summary> /// <para> Decrypts the symmetric key and saves it in metadata. In addition, intializes /// the SqlClientEncryptionAlgorithm for rapid decryption.</para> /// </summary> internal static void DecryptSymmetricKey(SqlCipherMetadata md, string serverName) { Debug.Assert(md != null, "md should not be null in DecryptSymmetricKey."); SqlClientSymmetricKey symKey = null; SqlEncryptionKeyInfo? encryptionkeyInfoChosen = null; DecryptSymmetricKey(md.EncryptionInfo, serverName, out symKey, out encryptionkeyInfoChosen); // Given the symmetric key instantiate a SqlClientEncryptionAlgorithm object and cache it in metadata md.CipherAlgorithm = null; SqlClientEncryptionAlgorithm cipherAlgorithm = null; string algorithmName = ValidateAndGetEncryptionAlgorithmName(md.CipherAlgorithmId, md.CipherAlgorithmName); // may throw SqlClientEncryptionAlgorithmFactoryList.GetInstance().GetAlgorithm(symKey, md.EncryptionType, algorithmName, out cipherAlgorithm); // will validate algorithm name and type Debug.Assert(cipherAlgorithm != null); md.CipherAlgorithm = cipherAlgorithm; md.EncryptionKeyInfo = encryptionkeyInfoChosen; return; }
/// <summary> /// <para> Decrypts the symmetric key and saves it in metadata. In addition, intializes /// the SqlClientEncryptionAlgorithm for rapid decryption.</para> /// </summary> internal static void DecryptSymmetricKey(SqlCipherMetadata md, string serverName) { Debug.Assert(serverName != null, @"serverName should not be null in DecryptSymmetricKey."); Debug.Assert(md != null, "md should not be null in DecryptSymmetricKey."); Debug.Assert(md.EncryptionInfo.HasValue, "md.EncryptionInfo should not be null in DecryptSymmetricKey."); Debug.Assert(md.EncryptionInfo.Value.ColumnEncryptionKeyValues != null, "md.EncryptionInfo.ColumnEncryptionKeyValues should not be null in DecryptSymmetricKey."); SqlClientSymmetricKey symKey = null; SqlEncryptionKeyInfo? encryptionkeyInfoChosen = null; SqlSymmetricKeyCache cache = SqlSymmetricKeyCache.GetInstance(); Exception lastException = null; foreach (SqlEncryptionKeyInfo keyInfo in md.EncryptionInfo.Value.ColumnEncryptionKeyValues) { try { if (cache.GetKey(keyInfo, serverName, out symKey)) { encryptionkeyInfoChosen = keyInfo; break; } } catch (Exception e) { lastException = e; } } if (null == symKey) { Debug.Assert (null != lastException, "CEK decryption failed without raising exceptions"); throw lastException; } Debug.Assert(encryptionkeyInfoChosen.HasValue, "encryptionkeyInfoChosen must have a value."); // Given the symmetric key instantiate a SqlClientEncryptionAlgorithm object and cache it in metadata md.CipherAlgorithm = null; SqlClientEncryptionAlgorithm cipherAlgorithm = null; string algorithmName = ValidateAndGetEncryptionAlgorithmName(md.CipherAlgorithmId, md.CipherAlgorithmName); // may throw SqlClientEncryptionAlgorithmFactoryList.GetInstance().GetAlgorithm(symKey, md.EncryptionType, algorithmName, out cipherAlgorithm); // will validate algorithm name and type Debug.Assert(cipherAlgorithm != null); md.CipherAlgorithm = cipherAlgorithm; md.EncryptionKeyInfo = encryptionkeyInfoChosen; return; }
/// <summary> /// Decrypts the symmetric key and saves it in metadata. /// </summary> internal static void DecryptSymmetricKey(SqlTceCipherInfoEntry?sqlTceCipherInfoEntry, string serverName, out SqlClientSymmetricKey sqlClientSymmetricKey, out SqlEncryptionKeyInfo?encryptionkeyInfoChosen) { Debug.Assert(serverName != null, @"serverName should not be null in DecryptSymmetricKey."); Debug.Assert(sqlTceCipherInfoEntry.HasValue, "sqlTceCipherInfoEntry should not be null in DecryptSymmetricKey."); Debug.Assert(sqlTceCipherInfoEntry.Value.ColumnEncryptionKeyValues != null, "sqlTceCipherInfoEntry.ColumnEncryptionKeyValues should not be null in DecryptSymmetricKey."); sqlClientSymmetricKey = null; encryptionkeyInfoChosen = null; Exception lastException = null; SqlSymmetricKeyCache cache = SqlSymmetricKeyCache.GetInstance(); foreach (SqlEncryptionKeyInfo keyInfo in sqlTceCipherInfoEntry.Value.ColumnEncryptionKeyValues) { try { if (cache.GetKey(keyInfo, serverName, out sqlClientSymmetricKey)) { encryptionkeyInfoChosen = keyInfo; break; } } catch (Exception e) { lastException = e; } } if (null == sqlClientSymmetricKey) { Debug.Assert(null != lastException, "CEK decryption failed without raising exceptions"); throw lastException; } Debug.Assert(encryptionkeyInfoChosen.HasValue, "encryptionkeyInfoChosen must have a value."); }
/// <summary> /// Constructor. /// </summary> /// <param name="sqlTceCipherInfoEntry"></param> /// <param name="sqlClientEncryptionAlgorithm"></param> /// <param name="cipherAlgorithmId"></param> /// <param name="encryptionType"></param> /// <param name="normalizationRuleVersion"></param> internal SqlCipherMetadata (SqlTceCipherInfoEntry? sqlTceCipherInfoEntry, ushort ordinal, byte cipherAlgorithmId, string cipherAlgorithmName, byte encryptionType, byte normalizationRuleVersion) { Debug.Assert(!sqlTceCipherInfoEntry.Equals(default(SqlTceCipherInfoEntry)), "sqlTceCipherInfoEntry should not be un-initialized."); _sqlTceCipherInfoEntry = sqlTceCipherInfoEntry; _ordinal = ordinal; _cipherAlgorithmId = cipherAlgorithmId; _cipherAlgorithmName = cipherAlgorithmName; _encryptionType = encryptionType; _normalizationRuleVersion = normalizationRuleVersion; _sqlEncryptionKeyInfo = null; }