using System; using System.Runtime.InteropServices; using System.Text; using System.Threading; namespace wolfSSL.CSharp { public class X509 { private const string wolfssl_dll = "wolfssl.dll"; [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] private extern static int wolfSSL_X509_get_pubkey_buffer(IntPtr x509, IntPtr buf, IntPtr bufSz); [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] private extern static IntPtr wolfSSL_X509_get_der(IntPtr x509, IntPtr bufSz); [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] private extern static void wolfSSL_X509_free(IntPtr x509); [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] private extern static int wc_DerToPem(IntPtr der, int derSz, IntPtr pem, int pemSz, int type); [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] private extern static IntPtr wolfSSL_X509_get_name_oneline(IntPtr x509Name, IntPtr buf, int bufSz); [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] private extern static IntPtr wolfSSL_X509_get_subject_name(IntPtr x509); [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] private extern static IntPtr wolfSSL_X509_get_issuer_name(IntPtr x509); private IntPtr x509; private int type; private bool isDynamic; /* public properties */ public string Issuer; public string Subject; /* enum from wolfssl */ private readonly int CERT_TYPE = 0; /// /// Creates a new X509 class /// /// Pointer to wolfSSL structure /// Should the lower level x509 be free'd? public X509(IntPtr x509, bool isDynamic) { IntPtr ret; this.type = wolfssl.SSL_FILETYPE_PEM; this.x509 = x509; ret = wolfSSL_X509_get_name_oneline( wolfSSL_X509_get_issuer_name(this.x509), IntPtr.Zero, 0); this.Issuer = Marshal.PtrToStringAnsi(ret); ret = wolfSSL_X509_get_name_oneline( wolfSSL_X509_get_subject_name(this.x509), IntPtr.Zero, 0); this.Subject = Marshal.PtrToStringAnsi(ret); this.isDynamic = isDynamic; } /// /// Free up the C level WOLFSSL_X509 struct if needed /// ~X509() { if (this.isDynamic) { wolfSSL_X509_free(this.x509); } } /// /// Used for getting the public key buffer /// /// DER public key on success public byte[] GetPublicKey() { if (this.x509 == IntPtr.Zero) { return null; } try { IntPtr bufSz; IntPtr buf; int keySz = 0; int ret; byte[] key = null; bufSz = Marshal.AllocHGlobal(4); /* pointer to 4 bytes */ ret = wolfSSL_X509_get_pubkey_buffer(this.x509, IntPtr.Zero, bufSz); if (ret == wolfssl.SUCCESS) { keySz = Marshal.ReadInt32(bufSz, 0); buf = Marshal.AllocHGlobal(keySz); ret = wolfSSL_X509_get_pubkey_buffer(this.x509, buf, bufSz); if (ret == wolfssl.SUCCESS) { key = new byte[keySz]; Marshal.Copy(buf, key, 0, keySz); } Marshal.FreeHGlobal(buf); } Marshal.FreeHGlobal(bufSz); return key; } catch (Exception e) { wolfssl.log(wolfssl.ERROR_LOG, "error getting public key" + e.ToString()); return null; } } /// /// Gets the X509 buffer /// /// X509 buffer on success public byte[] Export(int type) { if (this.x509 == IntPtr.Zero) return null; try { IntPtr bufSz; IntPtr buf; byte[] ret = null; bufSz = Marshal.AllocHGlobal(4); /* pointer to 4 bytes */ buf = wolfSSL_X509_get_der(this.x509, bufSz); if (buf != IntPtr.Zero) { int derSz = Marshal.ReadInt32(bufSz, 0); if (type == wolfssl.SSL_FILETYPE_ASN1) { ret = new byte[derSz]; Marshal.Copy(buf, ret, 0, derSz); } else if (type == wolfssl.SSL_FILETYPE_PEM) { int pemSz; pemSz = wc_DerToPem(buf, derSz, IntPtr.Zero, 0, CERT_TYPE); if (pemSz > 0) { IntPtr pem = Marshal.AllocHGlobal(pemSz); pemSz = wc_DerToPem(buf, derSz, pem, pemSz, CERT_TYPE); ret = new byte[pemSz]; Marshal.Copy(pem, ret, 0, pemSz); Marshal.FreeHGlobal(pem); } } else { wolfssl.log(wolfssl.ERROR_LOG, "unsupported export type"); } Marshal.FreeHGlobal(bufSz); return ret; } { wolfssl.log(wolfssl.ERROR_LOG, "unable to get buffer"); } Marshal.FreeHGlobal(bufSz); return ret; } catch (Exception e) { wolfssl.log(wolfssl.ERROR_LOG, "error getting x509 DER" + e.ToString()); return null; } } /// /// Gets the X509 buffer using this.type set (default PEM) /// /// X509 buffer on success public byte[] Export() { return Export(this.type); } /// /// Gets the X509 format /// /// X509 format on success public string GetFormat() { if (this.type == wolfssl.SSL_FILETYPE_PEM) { return "PEM"; } if (this.type == wolfssl.SSL_FILETYPE_ASN1) { return "DER"; } return "Unknown"; } } }