Exemple #1
0
        private void EnrollWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
        {
            string devName   = YubikeyPivManager.Instance.ListDevices().FirstOrDefault();
            bool   hasDevice = !string.IsNullOrEmpty(devName);

            if (!hasDevice)
            {
                throw new InvalidOperationException("No yubikey");
            }

            // 0. Get lock on yubikey
            using (YubikeyPivDevice dev = YubikeyPivManager.Instance.OpenDevice(devName))
            {
                // 1. Prep device info
                int     deviceId    = (int)dev.GetSerialNumber();
                string  neoFirmware = dev.GetVersion().ToString();
                Version pivFirmware;

                using (YubikeyPivDevice piv = YubikeyPivManager.Instance.OpenDevice(devName))
                    pivFirmware = piv.GetVersion();

                _enrollWorker.ReportProgress(1);

                // 2 - Generate PUK, prep PIN
                byte[] randomKey = Utilities.GenerateRandomKey();
                string puk       = Utilities.MapBytesToString(randomKey.Take(8).ToArray());

                string pin = txtPin.Text;

                _enrollWorker.ReportProgress(2);

                // 3 - Prep CA
                WindowsCertificate enrollmentAgent_std = WindowsCertStoreUtilities.FindCertificate(_settings.EnrollmentAgentCertificate);
                WindowsCertificate enrollmentAgent_adm = WindowsCertStoreUtilities.FindCertificate(_settings.EnrollmentAgentCertificate);
                string             ca         = _settings.CSREndpoint;
                string             caTemplate = _settings.EnrollmentCaTemplate;
                string             std_user   = txtStdUser.Text; //std
                string             adm_user   = txtAdmUser.Text; //adm

                if (enrollmentAgent_std == null)
                {
                    doWorkEventArgs.Cancel = true;
                    _enrollWorkerMessage   = "Unable to find the certificate with thumbprint: " + _settings.EnrollmentAgentCertificate;
                    return;
                }

                _enrollWorker.ReportProgress(3);

                // 4 - Prep Management Key
                // TODO: Consider a new key every time?
                byte[] mgmKey = _settings.EnrollmentManagementKey;

                _enrollWorker.ReportProgress(4);

                RSAParameters    publicKey_std = new RSAParameters();
                RSAParameters    publicKey_adm = new RSAParameters();
                X509Certificate2 std_cert;
                X509Certificate2 adm_cert;
                byte[]           chuid;

                using (YubikeyPivDevice pivTool = YubikeyPivManager.Instance.OpenDevice(devName))
                {
                    // 5 - Yubico: Reset device
                    pivTool.BlockPin();
                    pivTool.BlockPuk();
                    bool reset = pivTool.ResetDevice();

                    if (!reset)
                    {
                        doWorkEventArgs.Cancel = true;
                        _enrollWorkerMessage   = "Unable to reset the YubiKey";
                        return;
                    }

                    _enrollWorker.ReportProgress(5);

                    // 6 - Yubico: Management Key
                    bool authenticated = pivTool.Authenticate(YubikeyPivDevice.DefaultManagementKey);

                    if (!authenticated)
                    {
                        doWorkEventArgs.Cancel = true;
                        _enrollWorkerMessage   = "Unable to authenticate with the YubiKey";
                        return;
                    }

                    bool setMgmKey = pivTool.SetManagementKey(mgmKey);

                    if (!setMgmKey)
                    {
                        doWorkEventArgs.Cancel = true;
                        _enrollWorkerMessage   = "Unable to set the management key";
                        return;
                    }

                    _enrollWorker.ReportProgress(6);

                    // 7 - Yubico: Set CHUID
                    bool setChuid = pivTool.SetCHUID(Guid.NewGuid(), out chuid);

                    if (!setChuid)
                    {
                        doWorkEventArgs.Cancel = true;
                        _enrollWorkerMessage   = "Unable to set CHUID";
                        return;
                    }

                    _enrollWorker.ReportProgress(7);

                    // 8 - Yubico: PIN
                    int  tmp;
                    bool setPin = pivTool.ChangePin(YubikeyPivDevice.DefaultPin, pin, out tmp);

                    if (!setPin)
                    {
                        doWorkEventArgs.Cancel = true;
                        _enrollWorkerMessage   = "Unable to set the PIN code";
                        return;
                    }

                    _enrollWorker.ReportProgress(8);

                    // 9 - Yubico: PUK
                    bool setPuk = pivTool.ChangePuk(YubikeyPivDevice.DefaultPuk, puk, out tmp);

                    if (!setPuk)
                    {
                        doWorkEventArgs.Cancel = true;
                        _enrollWorkerMessage   = "Unable to set the PUK code";
                        return;
                    }

                    _enrollWorker.ReportProgress(9);

                    // 10 - Yubico: Generate Key
                    YubikeyAlgorithm algorithm = (YubikeyAlgorithm)drpAlgorithm.SelectedItem;


                    if (std_user != "")
                    {
                        try
                        {
                            pivTool.GenerateKey9a(algorithm.Value, out publicKey_std);
                        }
                        catch
                        {
                            doWorkEventArgs.Cancel = true;
                            _enrollWorkerMessage   = "Unable to generate a keypair for Standard User";
                            return;
                        }
                    }
                    if (adm_user != "")
                    {
                        try
                        {
                            pivTool.GenerateKey9d(algorithm.Value, out publicKey_adm);
                        }
                        catch
                        {
                            doWorkEventArgs.Cancel = true;
                            _enrollWorkerMessage   = "Unable to generate a keypair for Admin User";
                            return;
                        }
                    }

                    _enrollWorker.ReportProgress(10);
                }

                // 11 - Yubico: Make CSR
                string csr_std  = null;
                string csr_adm  = null;
                string csrError = null;

                if (std_user != "")
                {
                    try
                    {
                        MakeCsr_std(Utilities.ExportPublicKeyToPEMFormat(publicKey_std), pin, out csrError, out csr_std);
                    }
                    catch
                    {
                        doWorkEventArgs.Cancel = true;
                        _enrollWorkerMessage   = "Unable to generate a CSR for Standard User" + Environment.NewLine + csrError;
                        return;
                    }
                }

                if (adm_user != "")
                {
                    try
                    {
                        MakeCsr_adm(Utilities.ExportPublicKeyToPEMFormat(publicKey_adm), pin, out csrError, out csr_adm);
                    }
                    catch
                    {
                        doWorkEventArgs.Cancel = true;
                        _enrollWorkerMessage   = "Unable to generate a CSR for Admin User" + Environment.NewLine + csrError;
                        return;
                    }
                }

                _enrollWorker.ReportProgress(11);

                // 12 - Enroll
                string std_enrollError = null;
                string adm_enrollError = null;
                bool   std_enrolled    = true;
                bool   adm_enrolled    = true;

                if (std_user != "")
                {
                    std_enrolled = CertificateUtilities.Enroll(std_user, enrollmentAgent_std, ca, caTemplate, csr_std, out std_enrollError, out std_cert);
                }
                else
                {
                    std_cert = null;
                }

                if (adm_user != "")
                {
                    adm_enrolled = CertificateUtilities.Enroll(adm_user, enrollmentAgent_adm, ca, caTemplate, csr_adm, out adm_enrollError, out adm_cert);
                }
                else
                {
                    adm_cert = null;
                }

                if (!std_enrolled)
                {
                    doWorkEventArgs.Cancel = true;
                    _enrollWorkerMessage   = "Unable to enroll a certificate for Standard User." + Environment.NewLine + std_enrollError;
                    return;
                }
                if (!adm_enrolled)
                {
                    doWorkEventArgs.Cancel = true;
                    _enrollWorkerMessage   = "Unable to enroll a certificate for Admin User." + Environment.NewLine + adm_enrollError;
                    return;
                }

                _enrollWorker.ReportProgress(12);

                using (YubikeyPivDevice pivTool = YubikeyPivManager.Instance.OpenDevice(devName))
                {
                    // 13 - Yubico: Import Cert
                    bool authenticatedForCert = pivTool.Authenticate(mgmKey);

                    if (!authenticatedForCert)
                    {
                        doWorkEventArgs.Cancel = true;
                        _enrollWorkerMessage   = "Unable to authenticate prior to importing a certificate";
                        return;
                    }

                    if (std_user != "")
                    {
                        try
                        {
                            pivTool.SetCertificate9a(std_cert);
                        }
                        catch
                        {
                            doWorkEventArgs.Cancel = true;
                            _enrollWorkerMessage   = $"Unable to import a certificate";
                            return;
                        }
                    }

                    if (adm_user != "")
                    {
                        try
                        {
                            pivTool.SetCertificate9d(adm_cert);
                        }
                        catch
                        {
                            doWorkEventArgs.Cancel = true;
                            _enrollWorkerMessage   = $"Unable to import a certificate";
                            return;
                        }
                    }

                    _enrollWorker.ReportProgress(13);
                }

                // 14 - Create enrolled item for Standard User
                if (std_user != "")
                {
                    EnrolledYubikey newEnrollment_std = new EnrolledYubikey();
                    newEnrollment_std.DeviceSerial = deviceId;

                    newEnrollment_std.Certificate.Serial         = std_cert.SerialNumber;
                    newEnrollment_std.Certificate.Thumbprint     = std_cert.Thumbprint;
                    newEnrollment_std.Certificate.Subject        = std_cert.Subject;
                    newEnrollment_std.Certificate.Issuer         = std_cert.Issuer;
                    newEnrollment_std.Certificate.StartDate      = std_cert.NotBefore;
                    newEnrollment_std.Certificate.ExpireDate     = std_cert.NotAfter;
                    newEnrollment_std.Certificate.RawCertificate = std_cert.RawData;

                    newEnrollment_std.CA            = ca;
                    newEnrollment_std.Username      = std_user;
                    newEnrollment_std.Slot          = "Standard User";
                    newEnrollment_std.ManagementKey = mgmKey;
                    newEnrollment_std.PukKey        = puk;
                    newEnrollment_std.Chuid         = BitConverter.ToString(chuid).Replace("-", "");

                    newEnrollment_std.EnrolledAt = DateTime.UtcNow;

                    newEnrollment_std.YubikeyVersions.NeoFirmware = neoFirmware;
                    newEnrollment_std.YubikeyVersions.PivApplet   = pivFirmware.ToString();

                    _dataStore.Add(newEnrollment_std);
                }

                // 14 - Create enrolled item for Admin User
                if (adm_user != "")
                {
                    EnrolledYubikey newEnrollment_adm = new EnrolledYubikey();
                    newEnrollment_adm.DeviceSerial = deviceId;

                    newEnrollment_adm.Certificate.Serial         = adm_cert.SerialNumber;
                    newEnrollment_adm.Certificate.Thumbprint     = adm_cert.Thumbprint;
                    newEnrollment_adm.Certificate.Subject        = adm_cert.Subject;
                    newEnrollment_adm.Certificate.Issuer         = adm_cert.Issuer;
                    newEnrollment_adm.Certificate.StartDate      = adm_cert.NotBefore;
                    newEnrollment_adm.Certificate.ExpireDate     = adm_cert.NotAfter;
                    newEnrollment_adm.Certificate.RawCertificate = adm_cert.RawData;

                    newEnrollment_adm.CA            = ca;
                    newEnrollment_adm.Username      = adm_user;
                    newEnrollment_adm.Slot          = "Admin User";
                    newEnrollment_adm.ManagementKey = mgmKey;
                    newEnrollment_adm.PukKey        = puk;
                    newEnrollment_adm.Chuid         = BitConverter.ToString(chuid).Replace("-", "");

                    newEnrollment_adm.EnrolledAt = DateTime.UtcNow;

                    newEnrollment_adm.YubikeyVersions.NeoFirmware = neoFirmware;
                    newEnrollment_adm.YubikeyVersions.PivApplet   = pivFirmware.ToString();

                    _dataStore.Add(newEnrollment_adm);
                }

                _enrollWorker.ReportProgress(14);

                // 15 - Save store
                _dataStore.Save(MainForm.FileStore);

                _enrollWorker.ReportProgress(15);

                // Report
                doWorkEventArgs.Cancel = false;
                _enrollWorkerMessage   = "Success";
            }
        }