public void GenerateKeyStream(byte[] key, byte[] iv, byte[] output) { if (output.Length % BLOCK_SIZE != 0) { throw new Exception("Output buffer size must be aligned to BLOCK_SIZE"); } var keyHandle = default(GCHandle); var ivHandle = default(GCHandle); var inputHandle = default(GCHandle); var outputHandle = default(GCHandle); try { var inputBlock = new byte[BLOCK_SIZE]; keyHandle = GCHandle.Alloc(key, GCHandleType.Pinned); ivHandle = GCHandle.Alloc(iv, GCHandleType.Pinned); inputHandle = GCHandle.Alloc(inputBlock, GCHandleType.Pinned); outputHandle = GCHandle.Alloc(output, GCHandleType.Pinned); if (OpenSsl.EVP_EncryptInit_ex(_ctx, OpenSsl.EVP_aes_128_ctr(), IntPtr.Zero, keyHandle.AddrOfPinnedObject(), ivHandle.AddrOfPinnedObject()) != 1) { throw new Exception($"Cannot initialize AES: {OpenSsl.GetLastError()}"); } int outputOffset = 0; while (outputOffset < output.Length) { int outputLength = 0; if (OpenSsl.EVP_EncryptUpdate(_ctx, IntPtr.Add(outputHandle.AddrOfPinnedObject(), outputOffset), ref outputLength, inputHandle.AddrOfPinnedObject(), BLOCK_SIZE) != 1) { throw new Exception($"Cannot encode AES: {OpenSsl.GetLastError()}"); } outputOffset += outputLength; } } finally { if (keyHandle.IsAllocated) { keyHandle.Free(); } if (ivHandle.IsAllocated) { ivHandle.Free(); } if (inputHandle.IsAllocated) { inputHandle.Free(); } if (outputHandle.IsAllocated) { outputHandle.Free(); } } }
public void GenerateSessionKey( byte[] masterKey, byte[] masterSalt, byte[] sessionKey, byte[] sessionSalt, byte[] sessionAuth ) { var keyHandle = default(GCHandle); var ivHandle = default(GCHandle); var inputHandle = default(GCHandle); var sessionKeyHandle = default(GCHandle); var sessionSaltHandle = default(GCHandle); var sessionAuthHandle = default(GCHandle); try { var inputBlock = new byte[BLOCK_SIZE]; var sessionIv = new byte[BLOCK_SIZE]; keyHandle = GCHandle.Alloc(masterKey, GCHandleType.Pinned); ivHandle = GCHandle.Alloc(sessionIv, GCHandleType.Pinned); inputHandle = GCHandle.Alloc(inputBlock, GCHandleType.Pinned); sessionKeyHandle = GCHandle.Alloc(sessionKey, GCHandleType.Pinned); sessionSaltHandle = GCHandle.Alloc(sessionSalt, GCHandleType.Pinned); sessionAuthHandle = GCHandle.Alloc(sessionAuth, GCHandleType.Pinned); Array.Copy(masterSalt, sessionIv, masterSalt.Length); if (OpenSsl.EVP_EncryptInit_ex(_ctx, OpenSsl.EVP_aes_128_ctr(), IntPtr.Zero, keyHandle.AddrOfPinnedObject(), ivHandle.AddrOfPinnedObject()) != 1) { throw new Exception($"Cannot initialize AES: {OpenSsl.GetLastError()}"); } int outputLength = 0; if (OpenSsl.EVP_EncryptUpdate(_ctx, sessionKeyHandle.AddrOfPinnedObject(), ref outputLength, inputHandle.AddrOfPinnedObject(), BLOCK_SIZE) != 1) { throw new Exception($"Cannot encode AES: {OpenSsl.GetLastError()}"); } sessionIv[7] ^= 0x02; if (OpenSsl.EVP_EncryptInit_ex(_ctx, OpenSsl.EVP_aes_128_ctr(), IntPtr.Zero, keyHandle.AddrOfPinnedObject(), ivHandle.AddrOfPinnedObject()) != 1) { throw new Exception($"Cannot initialize AES: {OpenSsl.GetLastError()}"); } outputLength = 0; if (OpenSsl.EVP_EncryptUpdate(_ctx, sessionSaltHandle.AddrOfPinnedObject(), ref outputLength, inputHandle.AddrOfPinnedObject(), BLOCK_SIZE) != 1) { throw new Exception($"Cannot encode AES: {OpenSsl.GetLastError()}"); } sessionIv[7] ^= 0x03; if (OpenSsl.EVP_EncryptInit_ex(_ctx, OpenSsl.EVP_aes_128_ctr(), IntPtr.Zero, keyHandle.AddrOfPinnedObject(), ivHandle.AddrOfPinnedObject()) != 1) { throw new Exception($"Cannot initialize AES: {OpenSsl.GetLastError()}"); } int outputOffset = 0; while (outputOffset < sessionAuth.Length) { outputLength = 0; if (OpenSsl.EVP_EncryptUpdate(_ctx, IntPtr.Add(sessionAuthHandle.AddrOfPinnedObject(), outputOffset), ref outputLength, inputHandle.AddrOfPinnedObject(), BLOCK_SIZE) != 1) { throw new Exception($"Cannot encode AES: {OpenSsl.GetLastError()}"); } outputOffset += outputLength; } } finally { if (keyHandle.IsAllocated) { keyHandle.Free(); } if (ivHandle.IsAllocated) { ivHandle.Free(); } if (inputHandle.IsAllocated) { inputHandle.Free(); } if (sessionKeyHandle.IsAllocated) { sessionKeyHandle.Free(); } if (sessionSaltHandle.IsAllocated) { sessionSaltHandle.Free(); } if (sessionAuthHandle.IsAllocated) { sessionAuthHandle.Free(); } } }