src/java.base/macosx/classes/apple/security/KeychainStore.java
author redestad
Wed, 17 Jul 2019 12:35:46 +0200
changeset 55693 9a97b1393e72
parent 55063 51c699875f7c
permissions -rw-r--r--
8227587: Add internal privileged System.loadLibrary Reviewed-by: rriggs, mchung, chegar
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     1
/*
53684
3f054fd85646 8218553: Enhance keystore load debug output
coffeys
parents: 47216
diff changeset
     2
 * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     4
 *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    10
 *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    15
 * accompanied this code).
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    16
 *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    20
 *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    23
 * questions.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    24
 */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    25
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    26
package apple.security;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    27
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    28
import java.io.*;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    29
import java.security.*;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    30
import java.security.cert.*;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    31
import java.security.cert.Certificate;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    32
import java.security.spec.*;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    33
import java.util.*;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    34
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    35
import javax.crypto.*;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    36
import javax.crypto.spec.*;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    37
import javax.security.auth.x500.*;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    38
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    39
import sun.security.pkcs.*;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    40
import sun.security.pkcs.EncryptedPrivateKeyInfo;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    41
import sun.security.util.*;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    42
import sun.security.x509.*;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    43
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    44
/**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    45
 * This class provides the keystore implementation referred to as "KeychainStore".
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    46
 * It uses the current user's keychain as its backing storage, and does NOT support
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    47
 * a file-based implementation.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    48
 */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    49
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    50
public final class KeychainStore extends KeyStoreSpi {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    51
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    52
    // Private keys and their supporting certificate chains
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    53
    // If a key came from the keychain it has a SecKeyRef and one or more
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    54
    // SecCertificateRef.  When we delete the key we have to delete all of the corresponding
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    55
    // native objects.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    56
    class KeyEntry {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    57
        Date date; // the creation date of this entry
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    58
        byte[] protectedPrivKey;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    59
        char[] password;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    60
        long keyRef;  // SecKeyRef for this key
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    61
        Certificate chain[];
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    62
        long chainRefs[];  // SecCertificateRefs for this key's chain.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    63
    };
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    64
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    65
    // Trusted certificates
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    66
    class TrustedCertEntry {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    67
        Date date; // the creation date of this entry
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    68
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    69
        Certificate cert;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    70
        long certRef;  // SecCertificateRef for this key
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    71
    };
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    72
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    73
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    74
     * Entries that have been deleted.  When something calls engineStore we'll
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    75
     * remove them from the keychain.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    76
     */
25762
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
    77
    private Hashtable<String, Object> deletedEntries = new Hashtable<>();
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    78
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    79
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    80
     * Entries that have been added.  When something calls engineStore we'll
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    81
     * add them to the keychain.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    82
     */
25762
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
    83
    private Hashtable<String, Object> addedEntries = new Hashtable<>();
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    84
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    85
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    86
     * Private keys and certificates are stored in a hashtable.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    87
     * Hash entries are keyed by alias names.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    88
     */
25762
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
    89
    private Hashtable<String, Object> entries = new Hashtable<>();
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    90
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    91
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    92
     * Algorithm identifiers and corresponding OIDs for the contents of the PKCS12 bag we get from the Keychain.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    93
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    94
    private static final int keyBag[]  = {1, 2, 840, 113549, 1, 12, 10, 1, 2};
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    95
    private static final int pbeWithSHAAnd3KeyTripleDESCBC[] =     {1, 2, 840, 113549, 1, 12, 1, 3};
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    96
    private static ObjectIdentifier PKCS8ShroudedKeyBag_OID;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    97
    private static ObjectIdentifier pbeWithSHAAnd3KeyTripleDESCBC_OID;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    98
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    99
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   100
     * Constnats used in PBE decryption.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   101
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   102
    private static final int iterationCount = 1024;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   103
    private static final int SALT_LEN = 20;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   104
53684
3f054fd85646 8218553: Enhance keystore load debug output
coffeys
parents: 47216
diff changeset
   105
    private static final Debug debug = Debug.getInstance("keystore");
3f054fd85646 8218553: Enhance keystore load debug output
coffeys
parents: 47216
diff changeset
   106
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   107
    static {
55693
9a97b1393e72 8227587: Add internal privileged System.loadLibrary
redestad
parents: 55063
diff changeset
   108
        jdk.internal.loader.BootLoader.loadLibrary("osxsecurity");
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   109
        try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   110
            PKCS8ShroudedKeyBag_OID = new ObjectIdentifier(keyBag);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   111
            pbeWithSHAAnd3KeyTripleDESCBC_OID = new ObjectIdentifier(pbeWithSHAAnd3KeyTripleDESCBC);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   112
        } catch (IOException ioe) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   113
            // should not happen
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   114
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   115
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   116
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   117
    private static void permissionCheck() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   118
        SecurityManager sec = System.getSecurityManager();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   119
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   120
        if (sec != null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   121
            sec.checkPermission(new RuntimePermission("useKeychainStore"));
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   122
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   123
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   124
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   125
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   126
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   127
     * Verify the Apple provider in the constructor.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   128
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   129
     * @exception SecurityException if fails to verify
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   130
     * its own integrity
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   131
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   132
    public KeychainStore() { }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   133
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   134
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   135
        * Returns the key associated with the given alias, using the given
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   136
     * password to recover it.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   137
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   138
     * @param alias the alias name
27291
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   139
     * @param password the password for recovering the key. This password is
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   140
     *        used internally as the key is exported in a PKCS12 format.
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   141
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   142
     * @return the requested key, or null if the given alias does not exist
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   143
     * or does not identify a <i>key entry</i>.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   144
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   145
     * @exception NoSuchAlgorithmException if the algorithm for recovering the
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   146
     * key cannot be found
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   147
     * @exception UnrecoverableKeyException if the key cannot be recovered
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   148
     * (e.g., the given password is wrong).
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   149
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   150
    public Key engineGetKey(String alias, char[] password)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   151
        throws NoSuchAlgorithmException, UnrecoverableKeyException
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   152
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   153
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   154
27291
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   155
        // An empty password is rejected by MacOS API, no private key data
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   156
        // is exported. If no password is passed (as is the case when
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   157
        // this implementation is used as browser keystore in various
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   158
        // deployment scenarios like Webstart, JFX and applets), create
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   159
        // a dummy password so MacOS API is happy.
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   160
        if (password == null || password.length == 0) {
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   161
            // Must not be a char array with only a 0, as this is an empty
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   162
            // string.
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   163
            if (random == null) {
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   164
                random = new SecureRandom();
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   165
            }
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   166
            password = Long.toString(random.nextLong()).toCharArray();
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   167
        }
42769f9ca831 8062264: KeychainStore requires non-null password to be supplied when retrieving a private key
vinnie
parents: 25859
diff changeset
   168
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   169
        Object entry = entries.get(alias.toLowerCase());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   170
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   171
        if (entry == null || !(entry instanceof KeyEntry)) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   172
            return null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   173
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   174
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   175
        // This call gives us a PKCS12 bag, with the key inside it.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   176
        byte[] exportedKeyInfo = _getEncodedKeyData(((KeyEntry)entry).keyRef, password);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   177
        if (exportedKeyInfo == null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   178
            return null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   179
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   180
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   181
        PrivateKey returnValue = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   182
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   183
        try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   184
            byte[] pkcs8KeyData = fetchPrivateKeyFromBag(exportedKeyInfo);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   185
            byte[] encryptedKey;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   186
            AlgorithmParameters algParams;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   187
            ObjectIdentifier algOid;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   188
            try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   189
                // get the encrypted private key
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   190
                EncryptedPrivateKeyInfo encrInfo = new EncryptedPrivateKeyInfo(pkcs8KeyData);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   191
                encryptedKey = encrInfo.getEncryptedData();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   192
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   193
                // parse Algorithm parameters
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   194
                DerValue val = new DerValue(encrInfo.getAlgorithm().encode());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   195
                DerInputStream in = val.toDerInputStream();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   196
                algOid = in.getOID();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   197
                algParams = parseAlgParameters(in);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   198
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   199
            } catch (IOException ioe) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   200
                UnrecoverableKeyException uke =
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   201
                new UnrecoverableKeyException("Private key not stored as "
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   202
                                              + "PKCS#8 EncryptedPrivateKeyInfo: " + ioe);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   203
                uke.initCause(ioe);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   204
                throw uke;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   205
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   206
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   207
            // Use JCE to decrypt the data using the supplied password.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   208
            SecretKey skey = getPBEKey(password);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   209
            Cipher cipher = Cipher.getInstance(algOid.toString());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   210
            cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   211
            byte[] decryptedPrivateKey = cipher.doFinal(encryptedKey);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   212
            PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(decryptedPrivateKey);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   213
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   214
             // Parse the key algorithm and then use a JCA key factory to create the private key.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   215
            DerValue val = new DerValue(decryptedPrivateKey);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   216
            DerInputStream in = val.toDerInputStream();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   217
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   218
            // Ignore this -- version should be 0.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   219
            int i = in.getInteger();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   220
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   221
            // Get the Algorithm ID next
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   222
            DerValue[] value = in.getSequence(2);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   223
            AlgorithmId algId = new AlgorithmId(value[0].getOID());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   224
            String algName = algId.getName();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   225
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   226
            // Get a key factory for this algorithm.  It's likely to be 'RSA'.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   227
            KeyFactory kfac = KeyFactory.getInstance(algName);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   228
            returnValue = kfac.generatePrivate(kspec);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   229
        } catch (Exception e) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   230
            UnrecoverableKeyException uke =
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   231
            new UnrecoverableKeyException("Get Key failed: " +
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   232
                                          e.getMessage());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   233
            uke.initCause(e);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   234
            throw uke;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   235
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   236
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   237
        return returnValue;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   238
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   239
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   240
    private native byte[] _getEncodedKeyData(long secKeyRef, char[] password);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   241
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   242
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   243
     * Returns the certificate chain associated with the given alias.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   244
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   245
     * @param alias the alias name
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   246
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   247
     * @return the certificate chain (ordered with the user's certificate first
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   248
                                      * and the root certificate authority last), or null if the given alias
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   249
     * does not exist or does not contain a certificate chain (i.e., the given
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   250
                                                               * alias identifies either a <i>trusted certificate entry</i> or a
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   251
                                                               * <i>key entry</i> without a certificate chain).
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   252
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   253
    public Certificate[] engineGetCertificateChain(String alias) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   254
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   255
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   256
        Object entry = entries.get(alias.toLowerCase());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   257
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   258
        if (entry != null && entry instanceof KeyEntry) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   259
            if (((KeyEntry)entry).chain == null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   260
                return null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   261
            } else {
22584
eed64ee05369 8032733: Fix cast lint warnings in client libraries
darcy
parents: 14342
diff changeset
   262
                return ((KeyEntry)entry).chain.clone();
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   263
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   264
        } else {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   265
            return null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   266
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   267
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   268
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   269
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   270
     * Returns the certificate associated with the given alias.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   271
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   272
     * <p>If the given alias name identifies a
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   273
     * <i>trusted certificate entry</i>, the certificate associated with that
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   274
     * entry is returned. If the given alias name identifies a
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   275
     * <i>key entry</i>, the first element of the certificate chain of that
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   276
     * entry is returned, or null if that entry does not have a certificate
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   277
     * chain.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   278
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   279
     * @param alias the alias name
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   280
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   281
     * @return the certificate, or null if the given alias does not exist or
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   282
     * does not contain a certificate.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   283
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   284
    public Certificate engineGetCertificate(String alias) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   285
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   286
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   287
        Object entry = entries.get(alias.toLowerCase());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   288
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   289
        if (entry != null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   290
            if (entry instanceof TrustedCertEntry) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   291
                return ((TrustedCertEntry)entry).cert;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   292
            } else {
27498
b565dded1ead 8046777: apple.security.KeychainStore has a problem searching for identities
vinnie
parents: 27291
diff changeset
   293
                KeyEntry ke = (KeyEntry)entry;
b565dded1ead 8046777: apple.security.KeychainStore has a problem searching for identities
vinnie
parents: 27291
diff changeset
   294
                if (ke.chain == null || ke.chain.length == 0) {
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   295
                    return null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   296
                }
27498
b565dded1ead 8046777: apple.security.KeychainStore has a problem searching for identities
vinnie
parents: 27291
diff changeset
   297
                return ke.chain[0];
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   298
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   299
        } else {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   300
            return null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   301
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   302
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   303
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   304
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   305
        * Returns the creation date of the entry identified by the given alias.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   306
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   307
     * @param alias the alias name
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   308
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   309
     * @return the creation date of this entry, or null if the given alias does
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   310
     * not exist
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   311
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   312
    public Date engineGetCreationDate(String alias) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   313
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   314
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   315
        Object entry = entries.get(alias.toLowerCase());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   316
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   317
        if (entry != null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   318
            if (entry instanceof TrustedCertEntry) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   319
                return new Date(((TrustedCertEntry)entry).date.getTime());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   320
            } else {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   321
                return new Date(((KeyEntry)entry).date.getTime());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   322
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   323
        } else {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   324
            return null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   325
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   326
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   327
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   328
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   329
        * Assigns the given key to the given alias, protecting it with the given
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   330
     * password.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   331
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   332
     * <p>If the given key is of type <code>java.security.PrivateKey</code>,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   333
     * it must be accompanied by a certificate chain certifying the
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   334
     * corresponding public key.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   335
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   336
     * <p>If the given alias already exists, the keystore information
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   337
     * associated with it is overridden by the given key (and possibly
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   338
                                                          * certificate chain).
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   339
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   340
     * @param alias the alias name
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   341
     * @param key the key to be associated with the alias
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   342
     * @param password the password to protect the key
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   343
     * @param chain the certificate chain for the corresponding public
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   344
     * key (only required if the given key is of type
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   345
            * <code>java.security.PrivateKey</code>).
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   346
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   347
     * @exception KeyStoreException if the given key cannot be protected, or
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   348
     * this operation fails for some other reason
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   349
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   350
    public void engineSetKeyEntry(String alias, Key key, char[] password,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   351
                                  Certificate[] chain)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   352
        throws KeyStoreException
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   353
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   354
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   355
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   356
        synchronized(entries) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   357
            try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   358
                KeyEntry entry = new KeyEntry();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   359
                entry.date = new Date();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   360
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   361
                if (key instanceof PrivateKey) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   362
                    if ((key.getFormat().equals("PKCS#8")) ||
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   363
                        (key.getFormat().equals("PKCS8"))) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   364
                        entry.protectedPrivKey = encryptPrivateKey(key.getEncoded(), password);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   365
                        entry.password = password.clone();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   366
                    } else {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   367
                        throw new KeyStoreException("Private key is not encoded as PKCS#8");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   368
                    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   369
                } else {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   370
                    throw new KeyStoreException("Key is not a PrivateKey");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   371
                }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   372
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   373
                // clone the chain
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   374
                if (chain != null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   375
                    if ((chain.length > 1) && !validateChain(chain)) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   376
                        throw new KeyStoreException("Certificate chain does not validate");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   377
                    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   378
22584
eed64ee05369 8032733: Fix cast lint warnings in client libraries
darcy
parents: 14342
diff changeset
   379
                    entry.chain = chain.clone();
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   380
                    entry.chainRefs = new long[entry.chain.length];
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   381
                }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   382
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   383
                String lowerAlias = alias.toLowerCase();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   384
                if (entries.get(lowerAlias) != null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   385
                    deletedEntries.put(lowerAlias, entries.get(lowerAlias));
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   386
                }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   387
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   388
                entries.put(lowerAlias, entry);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   389
                addedEntries.put(lowerAlias, entry);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   390
            } catch (Exception nsae) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   391
                KeyStoreException ke = new KeyStoreException("Key protection algorithm not found: " + nsae);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   392
                ke.initCause(nsae);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   393
                throw ke;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   394
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   395
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   396
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   397
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   398
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   399
        * Assigns the given key (that has already been protected) to the given
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   400
     * alias.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   401
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   402
     * <p>If the protected key is of type
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   403
     * <code>java.security.PrivateKey</code>, it must be accompanied by a
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   404
     * certificate chain certifying the corresponding public key. If the
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   405
     * underlying keystore implementation is of type <code>jks</code>,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   406
     * <code>key</code> must be encoded as an
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   407
     * <code>EncryptedPrivateKeyInfo</code> as defined in the PKCS #8 standard.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   408
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   409
     * <p>If the given alias already exists, the keystore information
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   410
     * associated with it is overridden by the given key (and possibly
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   411
                                                          * certificate chain).
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   412
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   413
     * @param alias the alias name
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   414
     * @param key the key (in protected format) to be associated with the alias
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   415
     * @param chain the certificate chain for the corresponding public
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   416
     * key (only useful if the protected key is of type
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   417
            * <code>java.security.PrivateKey</code>).
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   418
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   419
     * @exception KeyStoreException if this operation fails.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   420
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   421
    public void engineSetKeyEntry(String alias, byte[] key,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   422
                                  Certificate[] chain)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   423
        throws KeyStoreException
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   424
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   425
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   426
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   427
        synchronized(entries) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   428
            // key must be encoded as EncryptedPrivateKeyInfo as defined in
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   429
            // PKCS#8
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   430
            KeyEntry entry = new KeyEntry();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   431
            try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   432
                EncryptedPrivateKeyInfo privateKey = new EncryptedPrivateKeyInfo(key);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   433
                entry.protectedPrivKey = privateKey.getEncoded();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   434
            } catch (IOException ioe) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   435
                throw new KeyStoreException("key is not encoded as "
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   436
                                            + "EncryptedPrivateKeyInfo");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   437
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   438
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   439
            entry.date = new Date();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   440
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   441
            if ((chain != null) &&
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   442
                (chain.length != 0)) {
22584
eed64ee05369 8032733: Fix cast lint warnings in client libraries
darcy
parents: 14342
diff changeset
   443
                entry.chain = chain.clone();
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   444
                entry.chainRefs = new long[entry.chain.length];
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   445
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   446
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   447
            String lowerAlias = alias.toLowerCase();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   448
            if (entries.get(lowerAlias) != null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   449
                deletedEntries.put(lowerAlias, entries.get(alias));
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   450
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   451
            entries.put(lowerAlias, entry);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   452
            addedEntries.put(lowerAlias, entry);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   453
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   454
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   455
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   456
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   457
        * Assigns the given certificate to the given alias.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   458
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   459
     * <p>If the given alias already exists in this keystore and identifies a
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   460
     * <i>trusted certificate entry</i>, the certificate associated with it is
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   461
     * overridden by the given certificate.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   462
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   463
     * @param alias the alias name
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   464
     * @param cert the certificate
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   465
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   466
     * @exception KeyStoreException if the given alias already exists and does
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   467
     * not identify a <i>trusted certificate entry</i>, or this operation
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   468
     * fails for some other reason.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   469
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   470
    public void engineSetCertificateEntry(String alias, Certificate cert)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   471
        throws KeyStoreException
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   472
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   473
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   474
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   475
        synchronized(entries) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   476
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   477
            Object entry = entries.get(alias.toLowerCase());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   478
            if ((entry != null) && (entry instanceof KeyEntry)) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   479
                throw new KeyStoreException
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   480
                ("Cannot overwrite key entry with certificate");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   481
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   482
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   483
            // This will be slow, but necessary.  Enumerate the values and then see if the cert matches the one in the trusted cert entry.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   484
            // Security framework doesn't support the same certificate twice in a keychain.
25762
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
   485
            Collection<Object> allValues = entries.values();
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   486
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   487
            for (Object value : allValues) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   488
                if (value instanceof TrustedCertEntry) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   489
                    TrustedCertEntry tce = (TrustedCertEntry)value;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   490
                    if (tce.cert.equals(cert)) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   491
                        throw new KeyStoreException("Keychain does not support mulitple copies of same certificate.");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   492
                    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   493
                }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   494
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   495
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   496
            TrustedCertEntry trustedCertEntry = new TrustedCertEntry();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   497
            trustedCertEntry.cert = cert;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   498
            trustedCertEntry.date = new Date();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   499
            String lowerAlias = alias.toLowerCase();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   500
            if (entries.get(lowerAlias) != null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   501
                deletedEntries.put(lowerAlias, entries.get(lowerAlias));
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   502
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   503
            entries.put(lowerAlias, trustedCertEntry);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   504
            addedEntries.put(lowerAlias, trustedCertEntry);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   505
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   506
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   507
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   508
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   509
        * Deletes the entry identified by the given alias from this keystore.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   510
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   511
     * @param alias the alias name
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   512
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   513
     * @exception KeyStoreException if the entry cannot be removed.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   514
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   515
    public void engineDeleteEntry(String alias)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   516
        throws KeyStoreException
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   517
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   518
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   519
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   520
        synchronized(entries) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   521
            Object entry = entries.remove(alias.toLowerCase());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   522
            deletedEntries.put(alias.toLowerCase(), entry);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   523
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   524
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   525
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   526
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   527
        * Lists all the alias names of this keystore.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   528
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   529
     * @return enumeration of the alias names
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   530
     */
25762
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
   531
    public Enumeration<String> engineAliases() {
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   532
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   533
        return entries.keys();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   534
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   535
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   536
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   537
        * Checks if the given alias exists in this keystore.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   538
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   539
     * @param alias the alias name
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   540
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   541
     * @return true if the alias exists, false otherwise
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   542
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   543
    public boolean engineContainsAlias(String alias) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   544
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   545
        return entries.containsKey(alias.toLowerCase());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   546
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   547
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   548
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   549
        * Retrieves the number of entries in this keystore.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   550
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   551
     * @return the number of entries in this keystore
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   552
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   553
    public int engineSize() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   554
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   555
        return entries.size();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   556
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   557
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   558
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   559
        * Returns true if the entry identified by the given alias is a
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   560
     * <i>key entry</i>, and false otherwise.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   561
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   562
     * @return true if the entry identified by the given alias is a
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   563
     * <i>key entry</i>, false otherwise.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   564
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   565
    public boolean engineIsKeyEntry(String alias) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   566
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   567
        Object entry = entries.get(alias.toLowerCase());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   568
        if ((entry != null) && (entry instanceof KeyEntry)) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   569
            return true;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   570
        } else {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   571
            return false;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   572
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   573
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   574
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   575
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   576
        * Returns true if the entry identified by the given alias is a
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   577
     * <i>trusted certificate entry</i>, and false otherwise.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   578
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   579
     * @return true if the entry identified by the given alias is a
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   580
     * <i>trusted certificate entry</i>, false otherwise.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   581
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   582
    public boolean engineIsCertificateEntry(String alias) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   583
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   584
        Object entry = entries.get(alias.toLowerCase());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   585
        if ((entry != null) && (entry instanceof TrustedCertEntry)) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   586
            return true;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   587
        } else {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   588
            return false;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   589
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   590
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   591
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   592
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   593
        * Returns the (alias) name of the first keystore entry whose certificate
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   594
     * matches the given certificate.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   595
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   596
     * <p>This method attempts to match the given certificate with each
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   597
     * keystore entry. If the entry being considered
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   598
     * is a <i>trusted certificate entry</i>, the given certificate is
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   599
     * compared to that entry's certificate. If the entry being considered is
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   600
     * a <i>key entry</i>, the given certificate is compared to the first
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   601
     * element of that entry's certificate chain (if a chain exists).
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   602
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   603
     * @param cert the certificate to match with.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   604
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   605
     * @return the (alias) name of the first entry with matching certificate,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   606
     * or null if no such entry exists in this keystore.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   607
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   608
    public String engineGetCertificateAlias(Certificate cert) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   609
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   610
        Certificate certElem;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   611
25762
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
   612
        for (Enumeration<String> e = entries.keys(); e.hasMoreElements(); ) {
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
   613
            String alias = e.nextElement();
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   614
            Object entry = entries.get(alias);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   615
            if (entry instanceof TrustedCertEntry) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   616
                certElem = ((TrustedCertEntry)entry).cert;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   617
            } else {
27498
b565dded1ead 8046777: apple.security.KeychainStore has a problem searching for identities
vinnie
parents: 27291
diff changeset
   618
                KeyEntry ke = (KeyEntry)entry;
b565dded1ead 8046777: apple.security.KeychainStore has a problem searching for identities
vinnie
parents: 27291
diff changeset
   619
                if (ke.chain == null || ke.chain.length == 0) {
b565dded1ead 8046777: apple.security.KeychainStore has a problem searching for identities
vinnie
parents: 27291
diff changeset
   620
                    continue;
b565dded1ead 8046777: apple.security.KeychainStore has a problem searching for identities
vinnie
parents: 27291
diff changeset
   621
                }
b565dded1ead 8046777: apple.security.KeychainStore has a problem searching for identities
vinnie
parents: 27291
diff changeset
   622
                certElem = ke.chain[0];
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   623
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   624
            if (certElem.equals(cert)) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   625
                return alias;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   626
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   627
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   628
        return null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   629
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   630
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   631
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   632
        * Stores this keystore to the given output stream, and protects its
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   633
     * integrity with the given password.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   634
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   635
     * @param stream Ignored. the output stream to which this keystore is written.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   636
     * @param password the password to generate the keystore integrity check
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   637
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   638
     * @exception IOException if there was an I/O problem with data
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   639
     * @exception NoSuchAlgorithmException if the appropriate data integrity
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   640
     * algorithm could not be found
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   641
     * @exception CertificateException if any of the certificates included in
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   642
     * the keystore data could not be stored
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   643
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   644
    public void engineStore(OutputStream stream, char[] password)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   645
        throws IOException, NoSuchAlgorithmException, CertificateException
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   646
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   647
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   648
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   649
        // Delete items that do have a keychain item ref.
25762
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
   650
        for (Enumeration<String> e = deletedEntries.keys(); e.hasMoreElements(); ) {
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
   651
            String alias = e.nextElement();
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   652
            Object entry = deletedEntries.get(alias);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   653
            if (entry instanceof TrustedCertEntry) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   654
                if (((TrustedCertEntry)entry).certRef != 0) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   655
                    _removeItemFromKeychain(((TrustedCertEntry)entry).certRef);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   656
                    _releaseKeychainItemRef(((TrustedCertEntry)entry).certRef);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   657
                }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   658
            } else {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   659
                Certificate certElem;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   660
                KeyEntry keyEntry = (KeyEntry)entry;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   661
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   662
                if (keyEntry.chain != null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   663
                    for (int i = 0; i < keyEntry.chain.length; i++) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   664
                        if (keyEntry.chainRefs[i] != 0) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   665
                            _removeItemFromKeychain(keyEntry.chainRefs[i]);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   666
                            _releaseKeychainItemRef(keyEntry.chainRefs[i]);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   667
                        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   668
                    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   669
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   670
                    if (keyEntry.keyRef != 0) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   671
                        _removeItemFromKeychain(keyEntry.keyRef);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   672
                        _releaseKeychainItemRef(keyEntry.keyRef);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   673
                    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   674
                }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   675
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   676
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   677
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   678
        // Add all of the certs or keys in the added entries.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   679
        // No need to check for 0 refs, as they are in the added list.
25762
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
   680
        for (Enumeration<String> e = addedEntries.keys(); e.hasMoreElements(); ) {
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
   681
            String alias = e.nextElement();
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   682
            Object entry = addedEntries.get(alias);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   683
            if (entry instanceof TrustedCertEntry) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   684
                TrustedCertEntry tce = (TrustedCertEntry)entry;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   685
                Certificate certElem;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   686
                certElem = tce.cert;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   687
                tce.certRef = addCertificateToKeychain(alias, certElem);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   688
            } else {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   689
                KeyEntry keyEntry = (KeyEntry)entry;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   690
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   691
                if (keyEntry.chain != null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   692
                    for (int i = 0; i < keyEntry.chain.length; i++) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   693
                        keyEntry.chainRefs[i] = addCertificateToKeychain(alias, keyEntry.chain[i]);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   694
                    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   695
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   696
                    keyEntry.keyRef = _addItemToKeychain(alias, false, keyEntry.protectedPrivKey, keyEntry.password);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   697
                }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   698
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   699
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   700
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   701
        // Clear the added and deletedEntries hashtables here, now that we're done with the updates.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   702
        // For the deleted entries, we freed up the native references above.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   703
        deletedEntries.clear();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   704
        addedEntries.clear();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   705
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   706
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   707
    private long addCertificateToKeychain(String alias, Certificate cert) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   708
        byte[] certblob = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   709
        long returnValue = 0;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   710
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   711
        try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   712
            certblob = cert.getEncoded();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   713
            returnValue = _addItemToKeychain(alias, true, certblob, null);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   714
        } catch (Exception e) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   715
            e.printStackTrace();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   716
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   717
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   718
        return returnValue;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   719
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   720
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   721
    private native long _addItemToKeychain(String alias, boolean isCertificate, byte[] datablob, char[] password);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   722
    private native int _removeItemFromKeychain(long certRef);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   723
    private native void _releaseKeychainItemRef(long keychainItemRef);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   724
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   725
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   726
      * Loads the keystore from the Keychain.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   727
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   728
     * @param stream Ignored - here for API compatibility.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   729
     * @param password Ignored - if user needs to unlock keychain Security
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   730
     * framework will post any dialogs.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   731
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   732
     * @exception IOException if there is an I/O or format problem with the
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   733
     * keystore data
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   734
     * @exception NoSuchAlgorithmException if the algorithm used to check
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   735
     * the integrity of the keystore cannot be found
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   736
     * @exception CertificateException if any of the certificates in the
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   737
     * keystore could not be loaded
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   738
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   739
    public void engineLoad(InputStream stream, char[] password)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   740
        throws IOException, NoSuchAlgorithmException, CertificateException
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   741
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   742
        permissionCheck();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   743
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   744
        // Release any stray keychain references before clearing out the entries.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   745
        synchronized(entries) {
25762
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
   746
            for (Enumeration<String> e = entries.keys(); e.hasMoreElements(); ) {
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
   747
                String alias = e.nextElement();
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   748
                Object entry = entries.get(alias);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   749
                if (entry instanceof TrustedCertEntry) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   750
                    if (((TrustedCertEntry)entry).certRef != 0) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   751
                        _releaseKeychainItemRef(((TrustedCertEntry)entry).certRef);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   752
                    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   753
                } else {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   754
                    KeyEntry keyEntry = (KeyEntry)entry;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   755
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   756
                    if (keyEntry.chain != null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   757
                        for (int i = 0; i < keyEntry.chain.length; i++) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   758
                            if (keyEntry.chainRefs[i] != 0) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   759
                                _releaseKeychainItemRef(keyEntry.chainRefs[i]);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   760
                            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   761
                        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   762
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   763
                        if (keyEntry.keyRef != 0) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   764
                            _releaseKeychainItemRef(keyEntry.keyRef);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   765
                        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   766
                    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   767
                }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   768
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   769
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   770
            entries.clear();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   771
            _scanKeychain();
53684
3f054fd85646 8218553: Enhance keystore load debug output
coffeys
parents: 47216
diff changeset
   772
            if (debug != null) {
3f054fd85646 8218553: Enhance keystore load debug output
coffeys
parents: 47216
diff changeset
   773
                debug.println("KeychainStore load entry count: " +
3f054fd85646 8218553: Enhance keystore load debug output
coffeys
parents: 47216
diff changeset
   774
                        entries.size());
3f054fd85646 8218553: Enhance keystore load debug output
coffeys
parents: 47216
diff changeset
   775
            }
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   776
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   777
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   778
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   779
    private native void _scanKeychain();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   780
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   781
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   782
     * Callback method from _scanKeychain.  If a trusted certificate is found, this method will be called.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   783
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   784
    private void createTrustedCertEntry(String alias, long keychainItemRef, long creationDate, byte[] derStream) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   785
        TrustedCertEntry tce = new TrustedCertEntry();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   786
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   787
        try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   788
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   789
            InputStream input = new ByteArrayInputStream(derStream);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   790
            X509Certificate cert = (X509Certificate) cf.generateCertificate(input);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   791
            input.close();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   792
            tce.cert = cert;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   793
            tce.certRef = keychainItemRef;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   794
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   795
            // Make a creation date.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   796
            if (creationDate != 0)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   797
                tce.date = new Date(creationDate);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   798
            else
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   799
                tce.date = new Date();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   800
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   801
            int uniqueVal = 1;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   802
            String originalAlias = alias;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   803
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   804
            while (entries.containsKey(alias.toLowerCase())) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   805
                alias = originalAlias + " " + uniqueVal;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   806
                uniqueVal++;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   807
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   808
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   809
            entries.put(alias.toLowerCase(), tce);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   810
        } catch (Exception e) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   811
            // The certificate will be skipped.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   812
            System.err.println("KeychainStore Ignored Exception: " + e);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   813
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   814
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   815
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   816
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   817
     * Callback method from _scanKeychain.  If an identity is found, this method will be called to create Java certificate
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   818
     * and private key objects from the keychain data.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   819
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   820
    private void createKeyEntry(String alias, long creationDate, long secKeyRef, long[] secCertificateRefs, byte[][] rawCertData)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   821
        throws IOException, NoSuchAlgorithmException, UnrecoverableKeyException {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   822
        KeyEntry ke = new KeyEntry();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   823
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   824
        // First, store off the private key information.  This is the easy part.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   825
        ke.protectedPrivKey = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   826
        ke.keyRef = secKeyRef;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   827
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   828
        // Make a creation date.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   829
        if (creationDate != 0)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   830
            ke.date = new Date(creationDate);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   831
        else
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   832
            ke.date = new Date();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   833
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   834
        // Next, create X.509 Certificate objects from the raw data.  This is complicated
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   835
        // because a certificate's public key may be too long for Java's default encryption strength.
25762
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
   836
        List<CertKeychainItemPair> createdCerts = new ArrayList<>();
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   837
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   838
        try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   839
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   840
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   841
            for (int i = 0; i < rawCertData.length; i++) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   842
                try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   843
                    InputStream input = new ByteArrayInputStream(rawCertData[i]);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   844
                    X509Certificate cert = (X509Certificate) cf.generateCertificate(input);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   845
                    input.close();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   846
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   847
                    // We successfully created the certificate, so track it and its corresponding SecCertificateRef.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   848
                    createdCerts.add(new CertKeychainItemPair(secCertificateRefs[i], cert));
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   849
                } catch (CertificateException e) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   850
                    // The certificate will be skipped.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   851
                    System.err.println("KeychainStore Ignored Exception: " + e);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   852
                }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   853
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   854
        } catch (CertificateException e) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   855
            e.printStackTrace();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   856
        } catch (IOException ioe) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   857
            ioe.printStackTrace();  // How would this happen?
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   858
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   859
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   860
        // We have our certificates in the List, so now extract them into an array of
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   861
        // Certificates and SecCertificateRefs.
25762
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
   862
        CertKeychainItemPair[] objArray = createdCerts.toArray(new CertKeychainItemPair[0]);
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   863
        Certificate[] certArray = new Certificate[objArray.length];
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   864
        long[] certRefArray = new long[objArray.length];
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   865
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   866
        for (int i = 0; i < objArray.length; i++) {
25762
c4a3548120c6 8044862: Fix raw and unchecked lint warnings in macosx specific code
henryjen
parents: 22584
diff changeset
   867
            CertKeychainItemPair addedItem = objArray[i];
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   868
            certArray[i] = addedItem.mCert;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   869
            certRefArray[i] = addedItem.mCertificateRef;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   870
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   871
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   872
        ke.chain = certArray;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   873
        ke.chainRefs = certRefArray;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   874
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   875
        // If we don't have already have an item with this item's alias
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   876
        // create a new one for it.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   877
        int uniqueVal = 1;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   878
        String originalAlias = alias;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   879
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   880
        while (entries.containsKey(alias.toLowerCase())) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   881
            alias = originalAlias + " " + uniqueVal;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   882
            uniqueVal++;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   883
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   884
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   885
        entries.put(alias.toLowerCase(), ke);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   886
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   887
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   888
    private class CertKeychainItemPair {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   889
        long mCertificateRef;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   890
        Certificate mCert;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   891
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   892
        CertKeychainItemPair(long inCertRef, Certificate cert) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   893
            mCertificateRef = inCertRef;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   894
            mCert = cert;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   895
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   896
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   897
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   898
    /*
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   899
     * Validate Certificate Chain
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   900
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   901
    private boolean validateChain(Certificate[] certChain)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   902
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   903
        for (int i = 0; i < certChain.length-1; i++) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   904
            X500Principal issuerDN =
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   905
            ((X509Certificate)certChain[i]).getIssuerX500Principal();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   906
            X500Principal subjectDN =
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   907
                ((X509Certificate)certChain[i+1]).getSubjectX500Principal();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   908
            if (!(issuerDN.equals(subjectDN)))
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   909
                return false;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   910
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   911
        return true;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   912
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   913
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   914
    private byte[] fetchPrivateKeyFromBag(byte[] privateKeyInfo) throws IOException, NoSuchAlgorithmException, CertificateException
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   915
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   916
        byte[] returnValue = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   917
        DerValue val = new DerValue(new ByteArrayInputStream(privateKeyInfo));
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   918
        DerInputStream s = val.toDerInputStream();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   919
        int version = s.getInteger();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   920
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   921
        if (version != 3) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   922
            throw new IOException("PKCS12 keystore not in version 3 format");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   923
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   924
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   925
        /*
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   926
            * Read the authSafe.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   927
         */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   928
        byte[] authSafeData;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   929
        ContentInfo authSafe = new ContentInfo(s);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   930
        ObjectIdentifier contentType = authSafe.getContentType();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   931
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   932
        if (contentType.equals(ContentInfo.DATA_OID)) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   933
            authSafeData = authSafe.getData();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   934
        } else /* signed data */ {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   935
            throw new IOException("public key protected PKCS12 not supported");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   936
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   937
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   938
        DerInputStream as = new DerInputStream(authSafeData);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   939
        DerValue[] safeContentsArray = as.getSequence(2);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   940
        int count = safeContentsArray.length;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   941
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   942
        /*
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   943
         * Spin over the ContentInfos.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   944
         */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   945
        for (int i = 0; i < count; i++) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   946
            byte[] safeContentsData;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   947
            ContentInfo safeContents;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   948
            DerInputStream sci;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   949
            byte[] eAlgId = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   950
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   951
            sci = new DerInputStream(safeContentsArray[i].toByteArray());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   952
            safeContents = new ContentInfo(sci);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   953
            contentType = safeContents.getContentType();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   954
            safeContentsData = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   955
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   956
            if (contentType.equals(ContentInfo.DATA_OID)) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   957
                safeContentsData = safeContents.getData();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   958
            } else if (contentType.equals(ContentInfo.ENCRYPTED_DATA_OID)) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   959
                // The password was used to export the private key from the keychain.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   960
                // The Keychain won't export the key with encrypted data, so we don't need
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   961
                // to worry about it.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   962
                continue;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   963
            } else {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   964
                throw new IOException("public key protected PKCS12" +
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   965
                                      " not supported");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   966
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   967
            DerInputStream sc = new DerInputStream(safeContentsData);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   968
            returnValue = extractKeyData(sc);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   969
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   970
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   971
        return returnValue;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   972
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   973
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   974
    private byte[] extractKeyData(DerInputStream stream)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   975
        throws IOException, NoSuchAlgorithmException, CertificateException
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   976
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   977
        byte[] returnValue = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   978
        DerValue[] safeBags = stream.getSequence(2);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   979
        int count = safeBags.length;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   980
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   981
        /*
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   982
         * Spin over the SafeBags.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   983
         */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   984
        for (int i = 0; i < count; i++) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   985
            ObjectIdentifier bagId;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   986
            DerInputStream sbi;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   987
            DerValue bagValue;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   988
            Object bagItem = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   989
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   990
            sbi = safeBags[i].toDerInputStream();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   991
            bagId = sbi.getOID();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   992
            bagValue = sbi.getDerValue();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   993
            if (!bagValue.isContextSpecific((byte)0)) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   994
                throw new IOException("unsupported PKCS12 bag value type "
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   995
                                      + bagValue.tag);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   996
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   997
            bagValue = bagValue.data.getDerValue();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   998
            if (bagId.equals(PKCS8ShroudedKeyBag_OID)) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   999
                // got what we were looking for.  Return it.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1000
                returnValue = bagValue.toByteArray();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1001
            } else {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1002
                // log error message for "unsupported PKCS12 bag type"
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1003
                System.out.println("Unsupported bag type '" + bagId + "'");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1004
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1005
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1006
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1007
        return returnValue;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1008
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1009
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1010
    /*
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1011
        * Generate PBE Algorithm Parameters
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1012
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1013
    private AlgorithmParameters getAlgorithmParameters(String algorithm)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1014
        throws IOException
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1015
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1016
        AlgorithmParameters algParams = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1017
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1018
        // create PBE parameters from salt and iteration count
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1019
        PBEParameterSpec paramSpec =
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1020
            new PBEParameterSpec(getSalt(), iterationCount);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1021
        try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1022
            algParams = AlgorithmParameters.getInstance(algorithm);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1023
            algParams.init(paramSpec);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1024
        } catch (Exception e) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1025
            IOException ioe =
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1026
            new IOException("getAlgorithmParameters failed: " +
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1027
                            e.getMessage());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1028
            ioe.initCause(e);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1029
            throw ioe;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1030
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1031
        return algParams;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1032
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1033
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1034
    // the source of randomness
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1035
    private SecureRandom random;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1036
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1037
    /*
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1038
     * Generate random salt
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1039
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1040
    private byte[] getSalt()
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1041
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1042
        // Generate a random salt.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1043
        byte[] salt = new byte[SALT_LEN];
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1044
        if (random == null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1045
            random = new SecureRandom();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1046
        }
55063
51c699875f7c 8042904: apple.security.KeychainStore.getSalt() calling generateSeed()
coffeys
parents: 53684
diff changeset
  1047
        random.nextBytes(salt);
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1048
        return salt;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1049
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1050
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1051
    /*
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1052
     * parse Algorithm Parameters
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1053
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1054
    private AlgorithmParameters parseAlgParameters(DerInputStream in)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1055
        throws IOException
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1056
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1057
        AlgorithmParameters algParams = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1058
        try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1059
            DerValue params;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1060
            if (in.available() == 0) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1061
                params = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1062
            } else {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1063
                params = in.getDerValue();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1064
                if (params.tag == DerValue.tag_Null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1065
                    params = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1066
                }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1067
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1068
            if (params != null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1069
                algParams = AlgorithmParameters.getInstance("PBE");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1070
                algParams.init(params.toByteArray());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1071
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1072
        } catch (Exception e) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1073
            IOException ioe =
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1074
            new IOException("parseAlgParameters failed: " +
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1075
                            e.getMessage());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1076
            ioe.initCause(e);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1077
            throw ioe;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1078
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1079
        return algParams;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1080
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1081
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1082
    /*
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1083
     * Generate PBE key
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1084
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1085
    private SecretKey getPBEKey(char[] password) throws IOException
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1086
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1087
        SecretKey skey = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1088
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1089
        try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1090
            PBEKeySpec keySpec = new PBEKeySpec(password);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1091
            SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1092
            skey = skFac.generateSecret(keySpec);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1093
        } catch (Exception e) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1094
            IOException ioe = new IOException("getSecretKey failed: " +
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1095
                                              e.getMessage());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1096
            ioe.initCause(e);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1097
            throw ioe;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1098
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1099
        return skey;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1100
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1101
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1102
    /*
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1103
     * Encrypt private key using Password-based encryption (PBE)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1104
     * as defined in PKCS#5.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1105
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1106
     * NOTE: Currently pbeWithSHAAnd3-KeyTripleDES-CBC algorithmID is
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1107
     *       used to derive the key and IV.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1108
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1109
     * @return encrypted private key encoded as EncryptedPrivateKeyInfo
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1110
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1111
    private byte[] encryptPrivateKey(byte[] data, char[] password)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1112
        throws IOException, NoSuchAlgorithmException, UnrecoverableKeyException
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1113
    {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1114
        byte[] key = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1115
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1116
        try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1117
            // create AlgorithmParameters
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1118
            AlgorithmParameters algParams =
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1119
            getAlgorithmParameters("PBEWithSHA1AndDESede");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1120
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1121
            // Use JCE
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1122
            SecretKey skey = getPBEKey(password);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1123
            Cipher cipher = Cipher.getInstance("PBEWithSHA1AndDESede");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1124
            cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1125
            byte[] encryptedKey = cipher.doFinal(data);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1126
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1127
            // wrap encrypted private key in EncryptedPrivateKeyInfo
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1128
            // as defined in PKCS#8
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1129
            AlgorithmId algid =
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1130
                new AlgorithmId(pbeWithSHAAnd3KeyTripleDESCBC_OID, algParams);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1131
            EncryptedPrivateKeyInfo encrInfo =
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1132
                new EncryptedPrivateKeyInfo(algid, encryptedKey);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1133
            key = encrInfo.getEncoded();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1134
        } catch (Exception e) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1135
            UnrecoverableKeyException uke =
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1136
            new UnrecoverableKeyException("Encrypt Private Key failed: "
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1137
                                          + e.getMessage());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1138
            uke.initCause(e);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1139
            throw uke;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1140
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1141
22584
eed64ee05369 8032733: Fix cast lint warnings in client libraries
darcy
parents: 14342
diff changeset
  1142
        return key;
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1143
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1144
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1145
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1146
}
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
  1147