/** * Callback method from _scanKeychain. If a trusted certificate is found, this method will be * called. */ private void createTrustedCertEntry( String alias, long keychainItemRef, long creationDate, byte[] derStream) { TrustedCertEntry tce = new TrustedCertEntry(); try { CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream input = new ByteArrayInputStream(derStream); X509Certificate cert = (X509Certificate) cf.generateCertificate(input); input.close(); tce.cert = cert; tce.certRef = keychainItemRef; // Make a creation date. if (creationDate != 0) tce.date = new Date(creationDate); else tce.date = new Date(); int uniqueVal = 1; String originalAlias = alias; while (entries.containsKey(alias.toLowerCase())) { alias = originalAlias + " " + uniqueVal; uniqueVal++; } entries.put(alias.toLowerCase(), tce); } catch (Exception e) { // The certificate will be skipped. System.err.println("KeychainStore Ignored Exception: " + e); } }
/** * Assigns the given certificate to the given alias. * * <p>If the given alias already exists in this keystore and identifies a <i>trusted certificate * entry</i>, the certificate associated with it is overridden by the given certificate. * * @param alias the alias name * @param cert the certificate * @exception KeyStoreException if the given alias already exists and does not identify a * <i>trusted certificate entry</i>, or this operation fails for some other reason. */ public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException { permissionCheck(); synchronized (entries) { Object entry = entries.get(alias.toLowerCase()); if ((entry != null) && (entry instanceof KeyEntry)) { throw new KeyStoreException("Cannot overwrite key entry with certificate"); } // This will be slow, but necessary. Enumerate the values and then see if the cert matches // the one in the trusted cert entry. // Security framework doesn't support the same certificate twice in a keychain. Collection<Object> allValues = entries.values(); for (Object value : allValues) { if (value instanceof TrustedCertEntry) { TrustedCertEntry tce = (TrustedCertEntry) value; if (tce.cert.equals(cert)) { throw new KeyStoreException( "Keychain does not support mulitple copies of same certificate."); } } } TrustedCertEntry trustedCertEntry = new TrustedCertEntry(); trustedCertEntry.cert = cert; trustedCertEntry.date = new Date(); String lowerAlias = alias.toLowerCase(); if (entries.get(lowerAlias) != null) { deletedEntries.put(lowerAlias, entries.get(lowerAlias)); } entries.put(lowerAlias, trustedCertEntry); addedEntries.put(lowerAlias, trustedCertEntry); } }
/** * Stores this keystore to the given output stream, and protects its integrity with the given * password. * * @param stream Ignored. the output stream to which this keystore is written. * @param password the password to generate the keystore integrity check * @exception IOException if there was an I/O problem with data * @exception NoSuchAlgorithmException if the appropriate data integrity algorithm could not be * found * @exception CertificateException if any of the certificates included in the keystore data could * not be stored */ public void engineStore(OutputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException { permissionCheck(); // Delete items that do have a keychain item ref. for (Enumeration<String> e = deletedEntries.keys(); e.hasMoreElements(); ) { String alias = e.nextElement(); Object entry = deletedEntries.get(alias); if (entry instanceof TrustedCertEntry) { if (((TrustedCertEntry) entry).certRef != 0) { _removeItemFromKeychain(((TrustedCertEntry) entry).certRef); _releaseKeychainItemRef(((TrustedCertEntry) entry).certRef); } } else { Certificate certElem; KeyEntry keyEntry = (KeyEntry) entry; if (keyEntry.chain != null) { for (int i = 0; i < keyEntry.chain.length; i++) { if (keyEntry.chainRefs[i] != 0) { _removeItemFromKeychain(keyEntry.chainRefs[i]); _releaseKeychainItemRef(keyEntry.chainRefs[i]); } } if (keyEntry.keyRef != 0) { _removeItemFromKeychain(keyEntry.keyRef); _releaseKeychainItemRef(keyEntry.keyRef); } } } } // Add all of the certs or keys in the added entries. // No need to check for 0 refs, as they are in the added list. for (Enumeration<String> e = addedEntries.keys(); e.hasMoreElements(); ) { String alias = e.nextElement(); Object entry = addedEntries.get(alias); if (entry instanceof TrustedCertEntry) { TrustedCertEntry tce = (TrustedCertEntry) entry; Certificate certElem; certElem = tce.cert; tce.certRef = addCertificateToKeychain(alias, certElem); } else { KeyEntry keyEntry = (KeyEntry) entry; if (keyEntry.chain != null) { for (int i = 0; i < keyEntry.chain.length; i++) { keyEntry.chainRefs[i] = addCertificateToKeychain(alias, keyEntry.chain[i]); } keyEntry.keyRef = _addItemToKeychain(alias, false, keyEntry.protectedPrivKey, keyEntry.password); } } } // Clear the added and deletedEntries hashtables here, now that we're done with the updates. // For the deleted entries, we freed up the native references above. deletedEntries.clear(); addedEntries.clear(); }