/// <summary> /// Click handler for the 'ResetPin' button. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void ResetPin_Click(object sender, RoutedEventArgs e) { if (!rootPage.ValidateTPMSmartCard()) { rootPage.NotifyUser("Use Scenario One to create a TPM virtual smart card.", NotifyType.ErrorMessage); return; } Button b = sender as Button; b.IsEnabled = false; try { SmartCard card = await rootPage.GetSmartCard(); SmartCardProvisioning provisioning = await SmartCardProvisioning.FromSmartCardAsync(card); rootPage.NotifyUser("Resetting smart card PIN...", NotifyType.StatusMessage); // When requesting a PIN reset, a SmartCardPinResetHandler must be // provided as an argument. This handler must use the challenge // it receives and the card's admin key to calculate and set the // response. bool result = await provisioning.RequestPinResetAsync( (pinResetSender, request) => { SmartCardPinResetDeferral deferral = request.GetDeferral(); try { IBuffer response = ChallengeResponseAlgorithm.CalculateResponse(request.Challenge, rootPage.AdminKey); request.SetResponse(response); } finally { deferral.Complete(); } }); if (result) { rootPage.NotifyUser("Smart card PIN reset operation completed.", NotifyType.StatusMessage); } else { rootPage.NotifyUser("Smart card PIN reset operation was canceled by the user.", NotifyType.StatusMessage); } } catch (Exception ex) { rootPage.NotifyUser("Resetting smart card PIN failed with exception: " + ex.ToString(), NotifyType.ErrorMessage); } finally { b.IsEnabled = true; } }
/// <summary> /// Click handler for the 'ChangeAdminKey' button. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void ChangeAdminKey_Click(object sender, RoutedEventArgs e) { if (!rootPage.ValidateTPMSmartCard()) { rootPage.NotifyUser("Use Scenario One to create a TPM virtual smart card.", NotifyType.ErrorMessage); return; } Button b = sender as Button; b.IsEnabled = false; try { IBuffer newadminkey = CryptographicBuffer.GenerateRandom(MainPage.ADMIN_KEY_LENGTH_IN_BYTES); SmartCard card = await rootPage.GetSmartCard(); SmartCardProvisioning provisioning = await SmartCardProvisioning.FromSmartCardAsync(card); rootPage.NotifyUser("Changing smart card admin key...", NotifyType.StatusMessage); using (SmartCardChallengeContext context = await provisioning.GetChallengeContextAsync()) { IBuffer response = ChallengeResponseAlgorithm.CalculateResponse(context.Challenge, rootPage.AdminKey); await context.ChangeAdministrativeKeyAsync(response, newadminkey); rootPage.AdminKey = newadminkey; } rootPage.NotifyUser("Smart card change admin key operation completed.", NotifyType.StatusMessage); } catch (Exception ex) { rootPage.NotifyUser("Changing smart card admin key operation failed with exception: " + ex.ToString(), NotifyType.ErrorMessage); } finally { b.IsEnabled = true; } }
/// <summary> /// Click handler for the 'VerifyResponse' button. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void VerifyResponse_Click(object sender, RoutedEventArgs e) { if (!rootPage.ValidateTPMSmartCard()) { rootPage.NotifyUser("Use Scenario One to create a TPM virtual smart card.", NotifyType.ErrorMessage); return; } Button b = sender as Button; b.IsEnabled = false; try { bool verifyResult = false; SmartCard card = await rootPage.GetSmartCard(); SmartCardProvisioning provisioning = await SmartCardProvisioning.FromSmartCardAsync(card); rootPage.NotifyUser("Verifying smart card response...", NotifyType.StatusMessage); using (SmartCardChallengeContext context = await provisioning.GetChallengeContextAsync()) { IBuffer response = ChallengeResponseAlgorithm.CalculateResponse(context.Challenge, rootPage.AdminKey); verifyResult = await context.VerifyResponseAsync(response); } rootPage.NotifyUser("Smart card response verification completed. Result: " + verifyResult.ToString(), NotifyType.StatusMessage); } catch (Exception ex) { rootPage.NotifyUser("Verifying smart card response operation failed with exception: " + ex.ToString(), NotifyType.ErrorMessage); } finally { b.IsEnabled = true; } }
/// <summary> /// Click handler for the 'create' button. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void Create_Click(object sender, RoutedEventArgs e) { Button b = sender as Button; b.IsEnabled = false; rootPage.NotifyUser("Creating TPM virtual smart card...", NotifyType.StatusMessage); try { SmartCardPinPolicy pinPolicy = ParsePinPolicy(); IBuffer adminkey = CryptographicBuffer.GenerateRandom(MainPage.ADMIN_KEY_LENGTH_IN_BYTES); SmartCardProvisioning provisioning = await SmartCardProvisioning.RequestVirtualSmartCardCreationAsync(FriendlyName.Text, adminkey, pinPolicy); // If card creation is cancelled by the user, // RequestVirtualSmartCard will return null instead of a // SmartCardProvisioning object. if (null == provisioning) { rootPage.NotifyUser("TPM virtual smart card creation was canceled by the user.", NotifyType.StatusMessage); b.IsEnabled = true; return; } // The following two lines are not directly related to TPM virtual // smart card creation, but are used to demonstrate how to handle // CardAdded events by registering an event handler with a // SmartCardReader object. Since we are using a TPM virtual smart // card in this case, the card cannot actually be added to or // removed from the reader, but a CardAdded event will fire as // soon as the event handler is added, since the card is already // inserted. // // We must retain a reference to the SmartCardReader object to // which we are adding the event handler. Hence we assign the // reader object associated with the SmartCardProvisioning we // received from RequestVirtualSmartCardCreationAsync to the // class's "reader" member. Then, we use += to add the // HandleCardAdded method as an event handler. The function // will be automatically boxed in a TypedEventHandler, but // the function signature match the template arguments for // the specific event - in this case, // <SmartCardReader, CardAddedEventArgs> reader = provisioning.SmartCard.Reader; reader.CardAdded += HandleCardAdded; // Store the reader's device ID and admin key to enable the // following scenarios in the sample. rootPage.SmartCardReaderDeviceId = provisioning.SmartCard.Reader.DeviceId; rootPage.AdminKey = adminkey; // Once RequestVirtualSmartCardCreationAsync has returned, the card // is already provisioned and ready to use. Therefore, the steps // in this using block are not actually necessary at this point. // However, should you want to re-provision the card in the future, // you would follow this sequence: acquire a challenge context, // calculate a response, and then call ProvisionAsync on the // challenge context with the calculated response. using (var context = await provisioning.GetChallengeContextAsync()) { IBuffer response = ChallengeResponseAlgorithm.CalculateResponse(context.Challenge, adminkey); await context.ProvisionAsync(response, true); } rootPage.NotifyUser("TPM virtual smart card is provisioned and ready for use.", NotifyType.StatusMessage); } catch (Exception ex) { // Two potentially common error scenarios when creating a TPM // virtual smart card are that the user's machine may not have // a TPM, or the TPM may not be ready for use. It is important // to explicitly check for these scenarios by checking the // HResult of any exceptions thrown by // RequestVirtualSmartCardCreationAsync and gracefully // providing a suitable message to the user. if (NTE_DEVICE_NOT_FOUND == ex.HResult) { rootPage.NotifyUser("We were unable to find a Trusted Platform Module on your machine. A TPM is required to use a TPM Virtual Smart Card.", NotifyType.ErrorMessage); } else if (NTE_DEVICE_NOT_READY == ex.HResult) { rootPage.NotifyUser("Your Trusted Platform Module is not ready for use. Please contact your administrator for assistance with initializing your TPM.", NotifyType.ErrorMessage); } else { rootPage.NotifyUser("TPM virtual smart card creation failed with exception: " + ex.ToString(), NotifyType.ErrorMessage); } } finally { b.IsEnabled = true; } }