Projects/ResponderForPKINIT
Contents
Description
The addition of Projects/Responder support to libkrb5 allows clients to use a responder callback to answer questions posed by the password-based and OTP preauthentication mechanisms, all at once, and in doing so select which mechanisms can be used to send requests to a KDC.
Problem
Support for using responder callbacks has not been implemented for PKINIT. Applications which wish to continue to support PKINIT need to continue to provide a prompter callback, which reduces the usefulness of the responder callback machinery.
Proposal
Add support for filling in response items to the PKINIT plugin.
Expected Behavior
The naive expectation, that PKINIT will also make use of an application's responder callback, will be the correct one.
Design
Load identity information in two passes. The first will be done during the plugin's fill_response method, at which time the client will attempt to load all configured identities. Those which don't require a password or PIN to read their keying material will just succeed, and those which don't will be added to the list of identities which will be added to the response item set. The second pass will use answers from the response item set to load identities from their corresponding locations, or if there is no answer, attempt to use the prompter callback to solicit passwords and PINs, as it does now.
Tentative Implementation
- Teach crypto_load_certs() to change its behavior to return a specific error to indicate when a given identity's keying material was protected by a PIN or password.
- Break pkinit_identity_initialize() up into two passes, one which calls crypto_load_certs() with this flag and returns immediately, to suss out which identities have protected keying information, and one which works like the current version, except that it will skip over anything which was loaded in the first pass. Special care will be needed for "DIR" identities, as the two-pass logic will have to be applied at the level where it's resolved things down to individual "FILE" identities internally, and for "PKCS11" identities, which may only specify a module, but which will need to be able to unambiguously refer to specific tokens and/or slots.
- In pkinit_clnt.c, add a client_prep_questions method which calls the first pass of pkinit_identity_initialize(), and which puts together a list of the identities which couldn't be loaded, due to a PIN or password being required, and any PIN-related warnings, to pass to the responder callback. Suggested sample challenge for a pkinit question:
{"PKCS12:/path/to/blah": 0, "FILE:/path/to/cert,/path/to/key": 0, "PKCS11:module=opensc-pkcs11.so:slotid=1:token=My Card": 4}
Suggested sample answer:
{"PKCS12:/path/to/blah": "foo", "FILE:/path/to/cert,/path/to/key": "bar"}
The challenge is an object whose keys are identity names, with their associated values being numbers corresponding to token flags. These flags convey the status of a token's pin, and will be set to zero or more of the flags KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW, KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY, and KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED.
- In the second pass of pkinit_identity_initialize(), use values provided in the answer, if there is one, to load identity information from locations in the answer. If no answer was available, use the prompter callback, as is done now, to solicit PINs and passwords for identities listed in the challenge.
- Helper functions for parsing the challenge into a structure (krb5_responder_pkinit_get_challenge, krb5_responder_pkinit_challenge_free) and setting answers (krb5_responder_pkinit_set_answer) will also be added.
Testing
- We'll need to add authenticated-client cases to the PKINIT tests, using keying material that's encrypted.
- We'll need a test program that lets us specify both that a particular response item is expected, and which response to supply for it, and which does not supply a prompter callback.
- We'll need to run tests using both encrypted and unencrypted copies of the keying material.
- We'll need to opportunistically test with at least one software PKCS#11 module, if found.
Documentation
If we enumerate which in-tree preauth mechanisms use responder callbacks, PKINIT will need to be removed from a list of exceptions, if there is one, and added to the list of mechanisms which use responder callbacks.
Release notes
Like documentation, to whatever extent we note that PKINIT doesn't support responder callbacks, we'll need to correct the notes.