securebb-win-demos/PKCS11 Certificate Storage (WinForms)/pkcs11certificatestorage.cs

637 lines
22 KiB
C#
Raw Normal View History

2024-08-08 13:09:34 +06:00
/*
* SecureBlackbox 2024 .NET Edition - Sample Project
*
* This sample project demonstrates the usage of SecureBlackbox in a
* simple, straightforward way. It is not intended to be a complete
* application. Error handling and other checks are simplified for clarity.
*
* www.nsoftware.com/secureblackbox
*
* This code is subject to the terms and conditions specified in the
* corresponding product license agreement which outlines the authorized
* usage and restrictions.
*
*/
using System;
using System.Windows.Forms;
using nsoftware.SecureBlackbox;
namespace PKCS11CertificateStorage
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class frmMain : System.Windows.Forms.Form
{
private System.Windows.Forms.MainMenu MainMenu;
private System.Windows.Forms.OpenFileDialog OpenDialog;
private System.Windows.Forms.OpenFileDialog OpenDialogCert;
private System.Windows.Forms.ImageList ImageList;
private System.Windows.Forms.MenuItem menuItem1;
private System.Windows.Forms.MenuItem menuItem6;
private System.Windows.Forms.MenuItem mnuOpenStorage;
private System.Windows.Forms.MenuItem mnuCloseStorage;
private System.Windows.Forms.MenuItem mnuExit;
private FolderBrowserDialog folderBrowserDialog;
private MenuItem mnuSaveStorage;
private Panel panelMain;
private Label label1;
private Panel panel1;
private Panel panel3;
private ListView lvCerts;
private ColumnHeader chSubject;
private ColumnHeader chIssuer;
private ColumnHeader chValidFrom;
private ColumnHeader chValidTo;
private ColumnHeader chAlgorithm;
private Panel panel2;
private Button btnProcessFiles;
private Button btnRemoveCert;
private Button btnOpen;
private ComboBox cbSlots;
private Label lbAvailableSlots;
private Button btnAddCert;
private System.ComponentModel.IContainer components;
public frmMain()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
certstorage = new CertificateStorage();
certstorage.OnPasswordNeeded += new CertificateStorage.OnPasswordNeededHandler(DoPasswordNeeded);
SetupButtons();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
if (certstorage.Opened)
certstorage.Close(false);
certstorage.Dispose();
components.Dispose();
frmPIN.Dispose();
frmProcessor.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmMain));
this.MainMenu = new System.Windows.Forms.MainMenu(this.components);
this.menuItem1 = new System.Windows.Forms.MenuItem();
this.mnuOpenStorage = new System.Windows.Forms.MenuItem();
this.mnuSaveStorage = new System.Windows.Forms.MenuItem();
this.mnuCloseStorage = new System.Windows.Forms.MenuItem();
this.menuItem6 = new System.Windows.Forms.MenuItem();
this.mnuExit = new System.Windows.Forms.MenuItem();
this.OpenDialog = new System.Windows.Forms.OpenFileDialog();
this.OpenDialogCert = new System.Windows.Forms.OpenFileDialog();
this.ImageList = new System.Windows.Forms.ImageList(this.components);
this.folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
this.panelMain = new System.Windows.Forms.Panel();
this.label1 = new System.Windows.Forms.Label();
this.panel1 = new System.Windows.Forms.Panel();
this.panel3 = new System.Windows.Forms.Panel();
this.lvCerts = new System.Windows.Forms.ListView();
this.chSubject = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.chIssuer = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.chValidFrom = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.chValidTo = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.chAlgorithm = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.panel2 = new System.Windows.Forms.Panel();
this.btnProcessFiles = new System.Windows.Forms.Button();
this.btnRemoveCert = new System.Windows.Forms.Button();
this.btnOpen = new System.Windows.Forms.Button();
this.cbSlots = new System.Windows.Forms.ComboBox();
this.lbAvailableSlots = new System.Windows.Forms.Label();
this.btnAddCert = new System.Windows.Forms.Button();
this.panelMain.SuspendLayout();
this.panel1.SuspendLayout();
this.panel3.SuspendLayout();
this.panel2.SuspendLayout();
this.SuspendLayout();
//
// MainMenu
//
this.MainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuItem1});
//
// menuItem1
//
this.menuItem1.Index = 0;
this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.mnuOpenStorage,
this.mnuSaveStorage,
this.mnuCloseStorage,
this.menuItem6,
this.mnuExit});
this.menuItem1.Text = "File";
//
// mnuOpenStorage
//
this.mnuOpenStorage.Index = 0;
this.mnuOpenStorage.Text = "Open storage...";
this.mnuOpenStorage.Click += new System.EventHandler(this.mnuOpenStorage_Click);
//
// mnuSaveStorage
//
this.mnuSaveStorage.Index = 1;
this.mnuSaveStorage.Text = "Save and close storage";
this.mnuSaveStorage.Click += new System.EventHandler(this.mnuSaveStorage_Click);
//
// mnuCloseStorage
//
this.mnuCloseStorage.Index = 2;
this.mnuCloseStorage.Text = "Close storage";
this.mnuCloseStorage.Click += new System.EventHandler(this.mnuCloseStorage_Click);
//
// menuItem6
//
this.menuItem6.Index = 3;
this.menuItem6.Text = "-";
//
// mnuExit
//
this.mnuExit.Index = 4;
this.mnuExit.Text = "Exit";
this.mnuExit.Click += new System.EventHandler(this.mnuExit_Click);
//
// OpenDialog
//
this.OpenDialog.Filter = "PKCS #11 Library (*.dll)|*.dll";
this.OpenDialog.InitialDirectory = ".";
this.OpenDialog.Title = "Please select PKCS #11 Library file";
//
// OpenDialogCert
//
this.OpenDialogCert.Filter = "PKCS#12 Certificate (*.pfx)|*.pfx";
this.OpenDialogCert.InitialDirectory = ".";
//
// ImageList
//
this.ImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("ImageList.ImageStream")));
this.ImageList.TransparentColor = System.Drawing.Color.Magenta;
this.ImageList.Images.SetKeyName(0, "");
this.ImageList.Images.SetKeyName(1, "");
this.ImageList.Images.SetKeyName(2, "");
this.ImageList.Images.SetKeyName(3, "");
//
// panelMain
//
this.panelMain.Controls.Add(this.label1);
this.panelMain.Dock = System.Windows.Forms.DockStyle.Top;
this.panelMain.Location = new System.Drawing.Point(0, 0);
this.panelMain.Name = "panelMain";
this.panelMain.Size = new System.Drawing.Size(604, 30);
this.panelMain.TabIndex = 4;
//
// label1
//
this.label1.AutoSize = true;
this.label1.ForeColor = System.Drawing.SystemColors.Highlight;
this.label1.Location = new System.Drawing.Point(10, 10);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(449, 13);
this.label1.TabIndex = 0;
this.label1.Text = "This sample illustrates the use of CertificateStorage component for work with PKC" +
"S11 storage.";
//
// panel1
//
this.panel1.Controls.Add(this.panel3);
this.panel1.Controls.Add(this.panel2);
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(0, 30);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(604, 300);
this.panel1.TabIndex = 5;
//
// panel3
//
this.panel3.Controls.Add(this.lvCerts);
this.panel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel3.Location = new System.Drawing.Point(0, 65);
this.panel3.Name = "panel3";
this.panel3.Size = new System.Drawing.Size(604, 235);
this.panel3.TabIndex = 5;
//
// lvCerts
//
this.lvCerts.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.chSubject,
this.chIssuer,
this.chValidFrom,
this.chValidTo,
this.chAlgorithm});
this.lvCerts.Dock = System.Windows.Forms.DockStyle.Fill;
this.lvCerts.FullRowSelect = true;
this.lvCerts.Location = new System.Drawing.Point(0, 0);
this.lvCerts.MultiSelect = false;
this.lvCerts.Name = "lvCerts";
this.lvCerts.Size = new System.Drawing.Size(604, 235);
this.lvCerts.SmallImageList = this.ImageList;
this.lvCerts.TabIndex = 4;
this.lvCerts.UseCompatibleStateImageBehavior = false;
this.lvCerts.View = System.Windows.Forms.View.Details;
this.lvCerts.SelectedIndexChanged += new System.EventHandler(this.lvCerts_SelectedIndexChanged);
//
// chSubject
//
this.chSubject.Text = "Subject";
this.chSubject.Width = 150;
//
// chIssuer
//
this.chIssuer.Text = "Issuer";
this.chIssuer.Width = 150;
//
// chValidFrom
//
this.chValidFrom.Text = "Valid from";
this.chValidFrom.Width = 80;
//
// chValidTo
//
this.chValidTo.Text = "Valid to";
this.chValidTo.Width = 80;
//
// chAlgorithm
//
this.chAlgorithm.Text = "Algorithm";
this.chAlgorithm.Width = 100;
//
// panel2
//
this.panel2.Controls.Add(this.btnProcessFiles);
this.panel2.Controls.Add(this.btnRemoveCert);
this.panel2.Controls.Add(this.btnOpen);
this.panel2.Controls.Add(this.cbSlots);
this.panel2.Controls.Add(this.lbAvailableSlots);
this.panel2.Controls.Add(this.btnAddCert);
this.panel2.Dock = System.Windows.Forms.DockStyle.Top;
this.panel2.Location = new System.Drawing.Point(0, 0);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(604, 65);
this.panel2.TabIndex = 4;
//
// btnProcessFiles
//
this.btnProcessFiles.Enabled = false;
this.btnProcessFiles.Location = new System.Drawing.Point(496, 30);
this.btnProcessFiles.Name = "btnProcessFiles";
this.btnProcessFiles.Size = new System.Drawing.Size(88, 25);
this.btnProcessFiles.TabIndex = 5;
this.btnProcessFiles.Text = "Process Files";
this.btnProcessFiles.Click += new System.EventHandler(this.btnProcessFiles_Click);
//
// btnRemoveCert
//
this.btnRemoveCert.Location = new System.Drawing.Point(376, 30);
this.btnRemoveCert.Name = "btnRemoveCert";
this.btnRemoveCert.Size = new System.Drawing.Size(112, 25);
this.btnRemoveCert.TabIndex = 4;
this.btnRemoveCert.Text = "Remove Certificate";
this.btnRemoveCert.Click += new System.EventHandler(this.btnRemoveCert_Click);
//
// btnOpen
//
this.btnOpen.Location = new System.Drawing.Point(184, 30);
this.btnOpen.Name = "btnOpen";
this.btnOpen.Size = new System.Drawing.Size(75, 25);
this.btnOpen.TabIndex = 2;
this.btnOpen.Text = "Open";
this.btnOpen.Click += new System.EventHandler(this.btnOpen_Click);
//
// cbSlots
//
this.cbSlots.Location = new System.Drawing.Point(16, 32);
this.cbSlots.Name = "cbSlots";
this.cbSlots.Size = new System.Drawing.Size(160, 21);
this.cbSlots.TabIndex = 1;
//
// lbAvailableSlots
//
this.lbAvailableSlots.Location = new System.Drawing.Point(16, 8);
this.lbAvailableSlots.Name = "lbAvailableSlots";
this.lbAvailableSlots.Size = new System.Drawing.Size(100, 13);
this.lbAvailableSlots.TabIndex = 0;
this.lbAvailableSlots.Text = "Available slots:";
//
// btnAddCert
//
this.btnAddCert.Location = new System.Drawing.Point(272, 30);
this.btnAddCert.Name = "btnAddCert";
this.btnAddCert.Size = new System.Drawing.Size(96, 25);
this.btnAddCert.TabIndex = 3;
this.btnAddCert.Text = "Add Certificate";
this.btnAddCert.Click += new System.EventHandler(this.btnAddCert_Click);
//
// frmMain
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(604, 330);
this.Controls.Add(this.panel1);
this.Controls.Add(this.panelMain);
this.Menu = this.MainMenu;
this.Name = "frmMain";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "PKCS11 Certificate storage demo";
this.panelMain.ResumeLayout(false);
this.panelMain.PerformLayout();
this.panel1.ResumeLayout(false);
this.panel3.ResumeLayout(false);
this.panel2.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new frmMain());
}
frmPIN frmPIN = new frmPIN();
frmProcessor frmProcessor = new frmProcessor();
CertificateStorage certstorage;
string storageFilename = "";
string certPassword = "";
private void DoPasswordNeeded(object sender, CertificateStoragePasswordNeededEventArgs e)
{
e.Password = certPassword;
}
private void mnuOpenStorage_Click(object sender, System.EventArgs e)
{
if (OpenDialog.ShowDialog() == DialogResult.OK)
{
storageFilename = OpenDialog.FileName;
OpenStorage();
}
}
private void mnuSaveStorage_Click(object sender, EventArgs e)
{
CloseStorage(true);
}
private void mnuCloseStorage_Click(object sender, System.EventArgs e)
{
CloseStorage(false);
}
private void mnuExit_Click(object sender, System.EventArgs e)
{
CloseStorage(false);
Application.Exit();
}
public int StrToIntDef(string s, int @default)
{
int number;
if (int.TryParse(s, out number))
return number;
return @default;
}
private void OpenStorage()
{
CloseStorage(false);
cbSlots.Items.Add("<Please select a slot>");
try
{
certstorage.Open("pkcs11:///" + storageFilename + "?slot=-1");
int slotCount = StrToIntDef(certstorage.Config("PKCS11SlotCount"), 0);
for (int i = 0; i < slotCount; i++)
{
cbSlots.Items.Add(certstorage.Config("PKCS11SlotDescription[" + i.ToString() + "]"));
}
cbSlots.SelectedIndex = 0;
}
catch (Exception E)
{
CloseStorage(false);
MessageBox.Show("Error opening storage: " + storageFilename + "\r\n" + E.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
SetupButtons();
}
private void CloseStorage(bool save)
{
if (certstorage.Opened)
certstorage.Close(save);
cbSlots.Items.Clear();
lvCerts.Items.Clear();
SetupButtons();
}
private void SetupButtons()
{
btnAddCert.Enabled = certstorage.Opened && (StrToIntDef(certstorage.Config("PKCS11ActiveSlot"), -1) >= 0);
btnRemoveCert.Enabled = certstorage.Opened && (StrToIntDef(certstorage.Config("PKCS11ActiveSlot"), -1) >= 0);
mnuSaveStorage.Enabled = certstorage.Opened;
mnuCloseStorage.Enabled = certstorage.Opened;
btnOpen.Enabled = certstorage.Opened;
}
private void AddCertificate()
{
if (OpenDialogCert.ShowDialog() == DialogResult.OK)
{
if (RequestPassword("Password request", "Please enter password for certificate:", out certPassword))
{
try
{
certstorage.ImportFromFile(OpenDialogCert.FileName, certPassword, false);
}
catch (Exception E)
{
MessageBox.Show("Failed to load certificate, error " +E.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
RefreshCertificates();
}
}
}
private void RemoveCertificate()
{
string S;
if ((lvCerts.SelectedIndices.Count > 0) && (lvCerts.SelectedIndices[0] < certstorage.Certificates.Count))
{
Certificate Cert = certstorage.Certificates[lvCerts.SelectedIndices[0]];
S = "Subject: " + Cert.Subject + "\r\nIssuer: " + Cert.Issuer;
if (MessageBox.Show("The following certificate will be deleted:\r\n" + S, "", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
certstorage.Remove(lvCerts.SelectedIndices[0]);
RefreshCertificates();
}
}
}
private void OpenSlot()
{
string Pin;
string RO;
// Checking whether we can establish a new session
if (cbSlots.SelectedIndex <= 0)
return;
if (certstorage.Config("PKCS11SlotTokenPresent[" + (cbSlots.SelectedIndex - 1).ToString() + "]").ToUpper() != "TRUE")
{
MessageBox.Show("Token not found in specified slot", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (certstorage.Config("PKCS11SlotReadOnly[" + (cbSlots.SelectedIndex - 1).ToString() + "]").ToUpper() == "TRUE")
{
RO = "&readonly=1";
}
else
{
RO = "&readonly=0";
}
if (RequestPassword("PIN request", "Please enter your PIN:", out Pin))
{
if (certstorage.Opened)
certstorage.Close(false);
try
{
certstorage.Open("pkcs11://user:" + Pin + "@/" + storageFilename + "?slot=" + (cbSlots.SelectedIndex - 1).ToString() + RO);
RefreshCertificates();
SetupButtons();
}
catch (Exception E)
{
MessageBox.Show("Error opening slot:" + E.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
OpenStorage();
return;
}
}
}
private void RefreshCertificates()
{
Certificate Cert;
ListViewItem Item;
lvCerts.Items.Clear();
for (int i = 0; i < certstorage.Certificates.Count; i++)
{
Cert = certstorage.Certificates[i];
Item = lvCerts.Items.Add("");
Item.ImageIndex = 3;
// Subject
Item.Text = Cert.Subject;
// Issuer
Item.SubItems.Add(Cert.Issuer);
// Validity period
Item.SubItems.Add(Cert.ValidFrom);
Item.SubItems.Add(Cert.ValidTo);
// Algorithm
Item.SubItems.Add(Cert.KeyAlgorithm + " (" + Cert.PublicKeyBytes.ToString() + " bits)");
}
}
private Boolean RequestPassword(string Caption, string Prompt, out string Pass)
{
frmPIN.lbPrompt.Text = Prompt;
frmPIN.Text = Caption;
frmPIN.edPIN.Text = "";
frmPIN.edPIN.Focus();
Pass = "";
if (frmPIN.ShowDialog() == DialogResult.OK)
{
Pass = frmPIN.edPIN.Text;
return true;
}
else
return false;
}
private void ProcessFiles()
{
if ((lvCerts.SelectedIndices.Count > 0) && (lvCerts.SelectedIndices[0] < certstorage.Certificates.Count))
{
frmProcessor.Cert = certstorage.Certificates[lvCerts.SelectedIndices[0]];
frmProcessor.ShowDialog();
}
}
private void btnOpen_Click(object sender, System.EventArgs e)
{
OpenSlot();
}
private void btnAddCert_Click(object sender, System.EventArgs e)
{
AddCertificate();
}
private void btnRemoveCert_Click(object sender, System.EventArgs e)
{
if (lvCerts.SelectedIndices.Count > 0)
RemoveCertificate();
}
private void btnProcessFiles_Click(object sender, System.EventArgs e)
{
if (lvCerts.SelectedIndices.Count > 0)
ProcessFiles();
}
private void lvCerts_SelectedIndexChanged(object sender, System.EventArgs e)
{
btnRemoveCert.Enabled = (lvCerts.SelectedIndices.Count > 0);
btnProcessFiles.Enabled = (lvCerts.SelectedIndices.Count > 0);
}
}
}