jdk/src/share/classes/sun/security/pkcs11/P11KeyStore.java
changeset 291 be2e0a87d658
parent 2 90ce3da70b43
child 2596 a1964c157e68
equal deleted inserted replaced
290:519d4185fbe2 291:be2e0a87d658
     1 /*
     1 /*
     2  * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
     2  * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Sun designates this
     7  * published by the Free Software Foundation.  Sun designates this
   154     private static class AliasInfo {
   154     private static class AliasInfo {
   155 
   155 
   156         // CKA_CLASS - entry type
   156         // CKA_CLASS - entry type
   157         private CK_ATTRIBUTE type = null;
   157         private CK_ATTRIBUTE type = null;
   158 
   158 
   159         // CKA_LABEL of cert
   159         // CKA_LABEL of cert and secret key
   160         private String label = null;
   160         private String label = null;
   161 
   161 
   162         // CKA_ID - of private key/cert
   162         // CKA_ID of the private key/cert pair
   163         private byte[] id = null;
   163         private byte[] id = null;
   164 
   164 
   165         // CKA_TRUSTED - true if cert is trusted
   165         // CKA_TRUSTED - true if cert is trusted
   166         private boolean trusted = false;
   166         private boolean trusted = false;
   167 
   167 
   869 
   869 
   870     private void login(CallbackHandler handler) throws LoginException {
   870     private void login(CallbackHandler handler) throws LoginException {
   871         if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {
   871         if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {
   872             token.provider.login(null, handler);
   872             token.provider.login(null, handler);
   873         } else {
   873         } else {
   874 
       
   875             // token supports protected authentication path
   874             // token supports protected authentication path
   876             // (external pin-pad, for example)
   875             // (external pin-pad, for example)
   877 
       
   878             if (handler != null &&
   876             if (handler != null &&
   879                 !token.config.getKeyStoreCompatibilityMode()) {
   877                 !token.config.getKeyStoreCompatibilityMode()) {
   880                 throw new LoginException("can not specify password if token " +
   878                 throw new LoginException("can not specify password if token " +
   881                                 "supports protected authentication path");
   879                                 "supports protected authentication path");
   882             }
   880             }
  1128 
  1126 
  1129                 KeyStore.SecretKeyEntry ske = (KeyStore.SecretKeyEntry)entry;
  1127                 KeyStore.SecretKeyEntry ske = (KeyStore.SecretKeyEntry)entry;
  1130                 SecretKey skey = ske.getSecretKey();
  1128                 SecretKey skey = ske.getSecretKey();
  1131 
  1129 
  1132                 try {
  1130                 try {
  1133                     // first see if the key already exists.
  1131                     // first check if the key already exists
  1134                     // if so, update the CKA_LABEL
  1132                     AliasInfo aliasInfo = aliasMap.get(alias);
  1135                     if (!updateSkey(alias)) {
  1133 
  1136 
  1134                     if (aliasInfo != null) {
  1137                         // key entry does not exist.
       
  1138                         // delete existing entry for alias and
       
  1139                         // create new secret key entry
       
  1140                         // (new entry might be a secret key
       
  1141                         // session object converted into a token object)
       
  1142 
       
  1143                         engineDeleteEntry(alias);
  1135                         engineDeleteEntry(alias);
  1144                         storeSkey(alias, ske);
       
  1145                     }
  1136                     }
       
  1137                     storeSkey(alias, ske);
       
  1138 
  1146                 } catch (PKCS11Exception pe) {
  1139                 } catch (PKCS11Exception pe) {
  1147                     throw new KeyStoreException(pe);
  1140                     throw new KeyStoreException(pe);
  1148                 }
  1141                 }
  1149 
  1142 
  1150             } else {
  1143             } else {
  1394             }
  1387             }
  1395             throw new KeyStoreException("unknown key type");
  1388             throw new KeyStoreException("unknown key type");
  1396         }
  1389         }
  1397     }
  1390     }
  1398 
  1391 
  1399     /**
       
  1400      * return true if update occurred
       
  1401      */
       
  1402     private boolean updateSkey(String alias)
       
  1403                 throws KeyStoreException, PKCS11Exception {
       
  1404 
       
  1405         Session session = null;
       
  1406         try {
       
  1407             session = token.getOpSession();
       
  1408 
       
  1409             // first update existing secret key CKA_LABEL
       
  1410 
       
  1411             THandle h = getTokenObject(session, ATTR_CLASS_SKEY, null, alias);
       
  1412             if (h.type != ATTR_CLASS_SKEY) {
       
  1413                 if (debug != null) {
       
  1414                     debug.println("did not find secret key " +
       
  1415                         "with CKA_LABEL [" + alias + "]");
       
  1416                 }
       
  1417                 return false;
       
  1418             }
       
  1419             CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
       
  1420                                 new CK_ATTRIBUTE(CKA_LABEL, alias) };
       
  1421             token.p11.C_SetAttributeValue(session.id(), h.handle, attrs);
       
  1422 
       
  1423             if (debug != null) {
       
  1424                 debug.println("updateSkey set new alias [" +
       
  1425                                 alias +
       
  1426                                 "] for secret key entry");
       
  1427             }
       
  1428 
       
  1429             return true;
       
  1430         } finally {
       
  1431             token.releaseSession(session);
       
  1432         }
       
  1433     }
       
  1434 
  1392 
  1435     /**
  1393     /**
  1436      * XXX  On ibutton, when you C_SetAttribute(CKA_ID) for a private key
  1394      * XXX  On ibutton, when you C_SetAttribute(CKA_ID) for a private key
  1437      *      it not only changes the CKA_ID of the private key,
  1395      *      it not only changes the CKA_ID of the private key,
  1438      *      it changes the CKA_ID of the corresponding cert too.
  1396      *      it changes the CKA_ID of the corresponding cert too.
  1530         } finally {
  1488         } finally {
  1531             token.releaseSession(session);
  1489             token.releaseSession(session);
  1532         }
  1490         }
  1533     }
  1491     }
  1534 
  1492 
  1535     private void updateP11Skey(String alias, P11Key key)
       
  1536                 throws PKCS11Exception {
       
  1537 
       
  1538         Session session = null;
       
  1539         try {
       
  1540             session = token.getOpSession();
       
  1541 
       
  1542             // session key - convert to token key and set CKA_LABEL
       
  1543 
       
  1544             CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
       
  1545                                 ATTR_TOKEN_TRUE,
       
  1546                                 new CK_ATTRIBUTE(CKA_LABEL, alias) };
       
  1547             token.p11.C_CopyObject(session.id(), key.keyID, attrs);
       
  1548             if (debug != null) {
       
  1549                     debug.println("updateP11Skey copied secret session key " +
       
  1550                                 "for [" +
       
  1551                                 alias +
       
  1552                                 "] to token entry");
       
  1553             }
       
  1554         } finally {
       
  1555             token.releaseSession(session);
       
  1556         }
       
  1557     }
       
  1558 
       
  1559     private void updateP11Pkey(String alias, CK_ATTRIBUTE attribute, P11Key key)
  1493     private void updateP11Pkey(String alias, CK_ATTRIBUTE attribute, P11Key key)
  1560                 throws PKCS11Exception {
  1494                 throws PKCS11Exception {
  1561 
  1495 
  1562         // if token key, update alias.
  1496         // if token key, update alias.
  1563         // if session key, convert to token key.
  1497         // if session key, convert to token key.
  1687 
  1621 
  1688     private void storeSkey(String alias, KeyStore.SecretKeyEntry ske)
  1622     private void storeSkey(String alias, KeyStore.SecretKeyEntry ske)
  1689                 throws PKCS11Exception, KeyStoreException {
  1623                 throws PKCS11Exception, KeyStoreException {
  1690 
  1624 
  1691         SecretKey skey = ske.getSecretKey();
  1625         SecretKey skey = ske.getSecretKey();
  1692         long keyType = CKK_GENERIC_SECRET;
  1626         // No need to specify CKA_CLASS, CKA_KEY_TYPE, CKA_VALUE since
  1693 
  1627         // they are handled in P11SecretKeyFactory.createKey() method.
  1694         if (skey instanceof P11Key && this.token == ((P11Key)skey).token) {
       
  1695             updateP11Skey(alias, (P11Key)skey);
       
  1696             return;
       
  1697         }
       
  1698 
       
  1699         if ("AES".equalsIgnoreCase(skey.getAlgorithm())) {
       
  1700             keyType = CKK_AES;
       
  1701         } else if ("Blowfish".equalsIgnoreCase(skey.getAlgorithm())) {
       
  1702             keyType = CKK_BLOWFISH;
       
  1703         } else if ("DES".equalsIgnoreCase(skey.getAlgorithm())) {
       
  1704             keyType = CKK_DES;
       
  1705         } else if ("DESede".equalsIgnoreCase(skey.getAlgorithm())) {
       
  1706             keyType = CKK_DES3;
       
  1707         } else if ("RC4".equalsIgnoreCase(skey.getAlgorithm()) ||
       
  1708                     "ARCFOUR".equalsIgnoreCase(skey.getAlgorithm())) {
       
  1709             keyType = CKK_RC4;
       
  1710         }
       
  1711 
       
  1712         CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
  1628         CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
  1713                 ATTR_SKEY_TOKEN_TRUE,
  1629             ATTR_SKEY_TOKEN_TRUE,
  1714                 ATTR_CLASS_SKEY,
  1630             ATTR_PRIVATE_TRUE,
  1715                 ATTR_PRIVATE_TRUE,
  1631             new CK_ATTRIBUTE(CKA_LABEL, alias),
  1716                 new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
  1632         };
  1717                 new CK_ATTRIBUTE(CKA_LABEL, alias),
       
  1718                 new CK_ATTRIBUTE(CKA_VALUE, skey.getEncoded()) };
       
  1719         attrs = token.getAttributes
       
  1720                 (TemplateManager.O_IMPORT, CKO_SECRET_KEY, keyType, attrs);
       
  1721 
       
  1722         // create the new entry
       
  1723         Session session = null;
       
  1724         try {
  1633         try {
  1725             session = token.getOpSession();
  1634             P11SecretKeyFactory.convertKey(token, skey, null, attrs);
  1726             token.p11.C_CreateObject(session.id(), attrs);
  1635         } catch (InvalidKeyException ike) {
  1727             if (debug != null) {
  1636             // re-throw KeyStoreException to match javadoc
  1728                 debug.println("storeSkey created token secret key for [" +
  1637             throw new KeyStoreException("Cannot convert to PKCS11 keys", ike);
  1729                                 alias +
  1638         }
  1730                                 "]");
  1639 
  1731             }
  1640         // update global alias map
  1732         } finally {
  1641         aliasMap.put(alias, new AliasInfo(alias));
  1733             token.releaseSession(session);
  1642 
       
  1643         if (debug != null) {
       
  1644             debug.println("storeSkey created token secret key for [" +
       
  1645                           alias + "]");
  1734         }
  1646         }
  1735     }
  1647     }
  1736 
  1648 
  1737     private static CK_ATTRIBUTE[] addAttribute(CK_ATTRIBUTE[] attrs, CK_ATTRIBUTE attr) {
  1649     private static CK_ATTRIBUTE[] addAttribute(CK_ATTRIBUTE[] attrs, CK_ATTRIBUTE attr) {
  1738         int n = attrs.length;
  1650         int n = attrs.length;
  2490 
  2402 
  2491             // create list secret key CKA_LABELS -
  2403             // create list secret key CKA_LABELS -
  2492             // if there are duplicates (either between secret keys,
  2404             // if there are duplicates (either between secret keys,
  2493             // or between a secret key and another object),
  2405             // or between a secret key and another object),
  2494             // throw an exception
  2406             // throw an exception
  2495             HashSet<String> sKeySet = new HashSet<String>();
  2407             HashMap<String, AliasInfo> sKeyMap =
       
  2408                     new HashMap<String, AliasInfo>();
  2496 
  2409 
  2497             attrs = new CK_ATTRIBUTE[] {
  2410             attrs = new CK_ATTRIBUTE[] {
  2498                 ATTR_SKEY_TOKEN_TRUE,
  2411                 ATTR_SKEY_TOKEN_TRUE,
  2499                 ATTR_CLASS_SKEY,
  2412                 ATTR_CLASS_SKEY,
  2500             };
  2413             };
  2505                 token.p11.C_GetAttributeValue(session.id(), handle, attrs);
  2418                 token.p11.C_GetAttributeValue(session.id(), handle, attrs);
  2506                 if (attrs[0].pValue != null) {
  2419                 if (attrs[0].pValue != null) {
  2507 
  2420 
  2508                     // there is a CKA_LABEL
  2421                     // there is a CKA_LABEL
  2509                     String cka_label = new String(attrs[0].getCharArray());
  2422                     String cka_label = new String(attrs[0].getCharArray());
  2510                     if (!sKeySet.contains(cka_label)) {
  2423                     if (sKeyMap.get(cka_label) == null) {
  2511                         sKeySet.add(cka_label);
  2424                         sKeyMap.put(cka_label, new AliasInfo(cka_label));
  2512                     } else {
  2425                     } else {
  2513                         throw new KeyStoreException("invalid KeyStore state: " +
  2426                         throw new KeyStoreException("invalid KeyStore state: " +
  2514                                 "found multiple secret keys sharing same " +
  2427                                 "found multiple secret keys sharing same " +
  2515                                 "CKA_LABEL [" +
  2428                                 "CKA_LABEL [" +
  2516                                 cka_label +
  2429                                 cka_label +
  2521 
  2434 
  2522             // update global aliasMap with alias mappings
  2435             // update global aliasMap with alias mappings
  2523             ArrayList<AliasInfo> matchedCerts =
  2436             ArrayList<AliasInfo> matchedCerts =
  2524                                 mapPrivateKeys(pkeyIDs, certMap);
  2437                                 mapPrivateKeys(pkeyIDs, certMap);
  2525             boolean sharedLabel = mapCerts(matchedCerts, certMap);
  2438             boolean sharedLabel = mapCerts(matchedCerts, certMap);
  2526             mapSecretKeys(sKeySet);
  2439             mapSecretKeys(sKeyMap);
  2527 
  2440 
  2528             return sharedLabel;
  2441             return sharedLabel;
  2529 
  2442 
  2530         } finally {
  2443         } finally {
  2531             token.releaseSession(session);
  2444             token.releaseSession(session);
  2545      */
  2458      */
  2546     private ArrayList<AliasInfo> mapPrivateKeys(ArrayList<byte[]> pkeyIDs,
  2459     private ArrayList<AliasInfo> mapPrivateKeys(ArrayList<byte[]> pkeyIDs,
  2547                         HashMap<String, HashSet<AliasInfo>> certMap)
  2460                         HashMap<String, HashSet<AliasInfo>> certMap)
  2548                 throws PKCS11Exception, CertificateException {
  2461                 throws PKCS11Exception, CertificateException {
  2549 
  2462 
  2550         // global alias map
  2463         // reset global alias map
  2551         aliasMap = new HashMap<String, AliasInfo>();
  2464         aliasMap = new HashMap<String, AliasInfo>();
  2552 
  2465 
  2553         // list of matched certs that we will return
  2466         // list of matched certs that we will return
  2554         ArrayList<AliasInfo> matchedCerts = new ArrayList<AliasInfo>();
  2467         ArrayList<AliasInfo> matchedCerts = new ArrayList<AliasInfo>();
  2555 
  2468 
  2720 
  2633 
  2721     /**
  2634     /**
  2722      * If the secret key shares a CKA_LABEL with another entry,
  2635      * If the secret key shares a CKA_LABEL with another entry,
  2723      * throw an exception
  2636      * throw an exception
  2724      */
  2637      */
  2725     private void mapSecretKeys(HashSet<String> sKeySet)
  2638     private void mapSecretKeys(HashMap<String, AliasInfo> sKeyMap)
  2726                 throws KeyStoreException {
  2639                 throws KeyStoreException {
  2727         for (String label : sKeySet) {
  2640         for (String label : sKeyMap.keySet()) {
  2728             if (!aliasMap.containsKey(label)) {
  2641             if (aliasMap.containsKey(label)) {
  2729                 aliasMap.put(label, new AliasInfo(label));
       
  2730             } else {
       
  2731                 throw new KeyStoreException("invalid KeyStore state: " +
  2642                 throw new KeyStoreException("invalid KeyStore state: " +
  2732                         "found secret key sharing CKA_LABEL [" +
  2643                         "found secret key sharing CKA_LABEL [" +
  2733                         label +
  2644                         label +
  2734                         "] with another token object");
  2645                         "] with another token object");
  2735             }
  2646             }
  2736         }
  2647         }
       
  2648         aliasMap.putAll(sKeyMap);
  2737     }
  2649     }
  2738 
  2650 
  2739     private void dumpTokenMap() {
  2651     private void dumpTokenMap() {
  2740         Set<String> aliases = aliasMap.keySet();
  2652         Set<String> aliases = aliasMap.keySet();
  2741         System.out.println("Token Alias Map:");
  2653         System.out.println("Token Alias Map:");