]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
In PKINIT NSS crypto, support encrypted PEM keys
authorNalin Dahyabhai <nalin@dahyabhai.net>
Wed, 24 Apr 2013 19:29:27 +0000 (15:29 -0400)
committerGreg Hudson <ghudson@mit.edu>
Mon, 13 May 2013 05:59:35 +0000 (01:59 -0400)
When the PEM module is given an encrypted key, it changes its token
flags to indicate that a password is required (by setting needs-login)
to signal the application that we need to supply a password to decrypt
it.  Attempts to load any other items will fail until the flag is
cleared.

If we detect that the flag is set after we've attempted to load a
private key, attempt to "log in" to the "token" using a password.  Even
if we fail, the token will reset its needs-login flag, which is
necessary before we can import anything else.

src/plugins/preauth/pkinit/pkinit_crypto_nss.c

index 0c798b50d3ed90f401559ca410085deece947956..d5b49e7a194786d9ff2fb742a0e7763f05827b48 100644 (file)
@@ -2642,6 +2642,32 @@ crypto_load_files(krb5_context context,
             }
         }
 
+        /* "Log in" (provide an encryption password) if the PEM slot now
+         * requires it. */
+        PK11_TokenRefresh(slot);
+
+        /*
+         * Unlike most tokens, this one won't self-destruct if we throw wrong
+         * passwords at it, but it will cause the module to clear the
+         * needs-login flag so that we can continue importing PEM items.
+         */
+        if (!PK11_IsLoggedIn(slot, crypto_pwcb_prep(id_cryptoctx,
+                                                    context)) &&
+            PK11_NeedLogin(slot)) {
+            pkiDebug("%s: logging in to token \"%s\"\n",
+                     __FUNCTION__, PK11_GetTokenName(slot));
+            if (PK11_Authenticate(slot, PR_TRUE,
+                                  crypto_pwcb_prep(id_cryptoctx,
+                                                   context)) != SECSuccess) {
+                pkiDebug("%s: error logging into \"%s\": %s, skipping\n",
+                         __FUNCTION__, PK11_GetTokenName(slot),
+                         PORT_ErrorToName(PORT_GetError()));
+                status = SECFailure;
+                PK11_DestroyGenericObject(kobj->obj);
+                kobj->obj = NULL;
+            }
+        }
+
         /* If we loaded a key and a certificate, see if they match. */
         if (cobj != NULL && cobj->cert != NULL && kobj->obj != NULL) {
             key = PK11_FindPrivateKeyFromCert(slot, cobj->cert,