logo_kerberos.gif

Difference between revisions of "Projects/ResponderForPKINIT"

From K5Wiki
Jump to: navigation, search
(Testing)
(Tentative Implementation)
 
(One intermediate revision by the same user not shown)
Line 25: Line 25:
 
* 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.
 
* 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.
 
* 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, to pass to the responder callback. Suggested sample challenge for a ''pkinit'' question:
+
* 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:
{"identities": ["PKCS12:/path/to/blah", "FILE:/path/to/cert,/path/to/key"], 'token-flags':{}}
+
{"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:
 
Suggested sample answer:
{"identities": {"PKCS12:/path/to/blah": "foo", "FILE:/path/to/cert,/path/to/key": "bar"}}
+
{"PKCS12:/path/to/blah": "foo", "FILE:/path/to/cert,/path/to/key": "bar"}
   
The ''token-flags'' object a subset of the members of ''identities'' as keys, and numbers corresponding to token flags as their values. 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''.
+
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.
 
* 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 at most one answer (''krb5_responder_pkinit_set_answer'') will also be added.
+
* 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==
 
==Testing==

Latest revision as of 09:29, 18 July 2013

This is an early stage project for MIT Kerberos. It is being fleshed out by its proponents. Feel free to help flesh out the details of this project. After the project is ready, it will be presented for review and approval.


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.