1a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrompackage org.bouncycastle.jcajce.provider.keystore.pkcs12;
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.BufferedInputStream;
4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.ByteArrayInputStream;
5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.ByteArrayOutputStream;
6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.IOException;
7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.InputStream;
8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.OutputStream;
95db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport java.security.InvalidAlgorithmParameterException;
105db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport java.security.InvalidKeyException;
11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.Key;
126e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.KeyStore;
134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.KeyStore.LoadStoreParameter;
144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.KeyStore.ProtectionParameter;
15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.KeyStoreException;
16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.KeyStoreSpi;
17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.NoSuchAlgorithmException;
18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.Principal;
19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.PrivateKey;
20c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport java.security.Provider;
21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.PublicKey;
22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.SecureRandom;
23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.UnrecoverableKeyException;
24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.cert.Certificate;
25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.cert.CertificateEncodingException;
266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.cert.CertificateException;
27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.cert.CertificateFactory;
28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.cert.X509Certificate;
295db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport java.security.spec.InvalidKeySpecException;
305db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport java.util.Collections;
31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Date;
32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Enumeration;
335db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport java.util.HashMap;
34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Hashtable;
355db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport java.util.Map;
36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Vector;
37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport javax.crypto.Cipher;
39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport javax.crypto.Mac;
405db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport javax.crypto.NoSuchPaddingException;
41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport javax.crypto.SecretKey;
42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport javax.crypto.SecretKeyFactory;
43a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstromimport javax.crypto.spec.IvParameterSpec;
44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport javax.crypto.spec.PBEKeySpec;
45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport javax.crypto.spec.PBEParameterSpec;
46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Encodable;
48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1EncodableVector;
494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Encoding;
50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1InputStream;
514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1ObjectIdentifier;
52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1OctetString;
534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Primitive;
54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1Sequence;
55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1Set;
56e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstromimport org.bouncycastle.asn1.BEROctetString;
57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.BEROutputStream;
58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DERBMPString;
59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DERNull;
60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DEROctetString;
616e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.asn1.DEROutputStream;
62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DERSequence;
63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DERSet;
645db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root// BEGIN android-removed
655db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
665db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root// import org.bouncycastle.asn1.cryptopro.GOST28147Parameters;
675db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root// END android-removed
685db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
695db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.AuthenticatedSafe;
71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.CertBag;
72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.ContentInfo;
73b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.EncryptedData;
74b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.MacData;
75a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstromimport org.bouncycastle.asn1.pkcs.PBES2Parameters;
76a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstromimport org.bouncycastle.asn1.pkcs.PBKDF2Params;
77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.PKCS12PBEParams;
78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.Pfx;
80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.SafeBag;
81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.util.ASN1Dump;
82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.x509.AlgorithmIdentifier;
83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.x509.DigestInfo;
85e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstromimport org.bouncycastle.asn1.x509.Extension;
86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
89a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstromimport org.bouncycastle.jcajce.provider.config.PKCS12StoreParameter;
904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
915db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root// BEGIN android-removed
925db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root// import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
935db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root// END android-removed
945db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport org.bouncycastle.jcajce.spec.PBKDF2KeySpec;
95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.jce.interfaces.BCKeyStore;
96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
97a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstromimport org.bouncycastle.jce.provider.BouncyCastleProvider;
98a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstromimport org.bouncycastle.jce.provider.JDKPKCS12StoreParameter;
99c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.util.Arrays;
1005db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport org.bouncycastle.util.Integers;
101c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.util.Strings;
102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.util.encoders.Hex;
103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
104a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrompublic class PKCS12KeyStoreSpi
105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    extends KeyStoreSpi
106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    implements PKCSObjectIdentifiers, X509ObjectIdentifiers, BCKeyStore
107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
108a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private static final int SALT_SIZE = 20;
109a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private static final int MIN_ITERATIONS = 1024;
110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
111a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private static final Provider bcProvider = new BouncyCastleProvider();
1125db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    private static final DefaultSecretKeyProvider keySizeProvider = new DefaultSecretKeyProvider();
113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
114a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private IgnoresCaseHashtable keys = new IgnoresCaseHashtable();
115a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private Hashtable localIds = new Hashtable();
116a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private IgnoresCaseHashtable certs = new IgnoresCaseHashtable();
117a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private Hashtable chainCerts = new Hashtable();
118a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private Hashtable keyCerts = new Hashtable();
119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // generic object types
122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
123a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    static final int NULL = 0;
124a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    static final int CERTIFICATE = 1;
125a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    static final int KEY = 2;
126a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    static final int SECRET = 3;
127a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    static final int SEALED = 4;
128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // key types
131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
132a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    static final int KEY_PRIVATE = 0;
133a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    static final int KEY_PUBLIC = 1;
134a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    static final int KEY_SECRET = 2;
135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
136a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    protected SecureRandom random = new SecureRandom();
137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
138c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // use of final causes problems with JDK 1.2 compiler
139a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private CertificateFactory certFact;
1404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private ASN1ObjectIdentifier keyAlgorithm;
1414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private ASN1ObjectIdentifier certAlgorithm;
142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private class CertId
144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
145a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        byte[] id;
146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        CertId(
148a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            PublicKey key)
149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            this.id = createSubjectKeyId(key).getKeyIdentifier();
151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        CertId(
154a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            byte[] id)
155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            this.id = id;
157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        public int hashCode()
160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
161c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return Arrays.hashCode(id);
162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        public boolean equals(
165a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            Object o)
166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
167c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (o == this)
168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
169c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                return true;
170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
171b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
172c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (!(o instanceof CertId))
173b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
174b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                return false;
175b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
176b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
177a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            CertId cId = (CertId)o;
178b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
179c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return Arrays.areEqual(id, cId.id);
180b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
181b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
182b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
183a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    public PKCS12KeyStoreSpi(
184c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        Provider provider,
1854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1ObjectIdentifier keyAlgorithm,
1864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1ObjectIdentifier certAlgorithm)
187b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
188c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        this.keyAlgorithm = keyAlgorithm;
189c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        this.certAlgorithm = certAlgorithm;
190c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
191b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
192b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
193b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (provider != null)
194b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
195b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certFact = CertificateFactory.getInstance("X.509", provider);
196b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
197b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
198b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
199b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certFact = CertificateFactory.getInstance("X.509");
200b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
201b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
202b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (Exception e)
203b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
204b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IllegalArgumentException("can't create cert factory - " + e.toString());
205b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
206b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
207b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
208b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private SubjectKeyIdentifier createSubjectKeyId(
209a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        PublicKey pubKey)
210b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
211b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
212b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
213b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
214a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                (ASN1Sequence)ASN1Primitive.fromByteArray(pubKey.getEncoded()));
215b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
216b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return new SubjectKeyIdentifier(info);
217b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
218b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (Exception e)
219b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
220b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new RuntimeException("error creating key");
221b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
222b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
223b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
224b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void setRandom(
225a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        SecureRandom rand)
226b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
227b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.random = rand;
228b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
229b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
230a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    public Enumeration engineAliases()
231b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
232a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        Hashtable tab = new Hashtable();
233b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
234b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Enumeration e = certs.keys();
235b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (e.hasMoreElements())
236b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
237b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            tab.put(e.nextElement(), "cert");
238b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
239b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
240b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        e = keys.keys();
241b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (e.hasMoreElements())
242b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
243a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            String a = (String)e.nextElement();
244b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (tab.get(a) == null)
245b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
246b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                tab.put(a, "key");
247b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
248b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
249b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
250b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return tab.keys();
251b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
252b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
253b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public boolean engineContainsAlias(
254a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        String alias)
255b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
256b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return (certs.get(alias) != null || keys.get(alias) != null);
257b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
258b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
259b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
260c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * this is not quite complete - we should follow up on the chain, a bit
261b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * tricky if a certificate appears in more than one chain...
262b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
263b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void engineDeleteEntry(
264a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        String alias)
265b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws KeyStoreException
266b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
267b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Key k = (Key)keys.remove(alias);
268b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
269b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Certificate c = (Certificate)certs.remove(alias);
270b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
271b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (c != null)
272b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
273b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            chainCerts.remove(new CertId(c.getPublicKey()));
274b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
275b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
276b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (k != null)
277b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
278a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            String id = (String)localIds.remove(alias);
279b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (id != null)
280b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
281b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                c = (Certificate)keyCerts.remove(id);
282b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
283b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (c != null)
284b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
285b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                chainCerts.remove(new CertId(c.getPublicKey()));
286b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
287b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
288b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
289b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
290b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
291b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * simply return the cert for the private key
292b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
293b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public Certificate engineGetCertificate(
294a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        String alias)
295b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
296b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (alias == null)
297b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
298b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IllegalArgumentException("null alias passed to getCertificate.");
299b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
300a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
301b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Certificate c = (Certificate)certs.get(alias);
302b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
303b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
304b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // look up the key table - and try the local key id
305b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
306b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (c == null)
307b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
308a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            String id = (String)localIds.get(alias);
309b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (id != null)
310b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
311b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                c = (Certificate)keyCerts.get(id);
312b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
313b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
314b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
315b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                c = (Certificate)keyCerts.get(alias);
316b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
317b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
318b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
319b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return c;
320b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
321b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
322b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public String engineGetCertificateAlias(
323a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        Certificate cert)
324b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
325b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Enumeration c = certs.elements();
326b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Enumeration k = certs.keys();
327b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
328b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (c.hasMoreElements())
329b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
330b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            Certificate tc = (Certificate)c.nextElement();
331a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            String ta = (String)k.nextElement();
332b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
333b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (tc.equals(cert))
334b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
335b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                return ta;
336b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
337b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
338b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
339b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = keyCerts.elements();
340b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        k = keyCerts.keys();
341b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
342b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (c.hasMoreElements())
343b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
344b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            Certificate tc = (Certificate)c.nextElement();
345a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            String ta = (String)k.nextElement();
346b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
347b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (tc.equals(cert))
348b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
349b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                return ta;
350b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
351b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
352a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
353b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return null;
354b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
355a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
356b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public Certificate[] engineGetCertificateChain(
357a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        String alias)
358b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
359b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (alias == null)
360b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
361b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IllegalArgumentException("null alias passed to getCertificateChain.");
362b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
363a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
364b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (!engineIsKeyEntry(alias))
365b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
366b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return null;
367b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
368a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
369b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Certificate c = engineGetCertificate(alias);
370b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
371b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (c != null)
372b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
373a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            Vector cs = new Vector();
374b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
375b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            while (c != null)
376b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
377a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                X509Certificate x509c = (X509Certificate)c;
378a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                Certificate nextC = null;
379b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
380a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                byte[] bytes = x509c.getExtensionValue(Extension.authorityKeyIdentifier.getId());
381b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (bytes != null)
382b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
383b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    try
384b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
385a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                        ASN1InputStream aIn = new ASN1InputStream(bytes);
386b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
387b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        byte[] authBytes = ((ASN1OctetString)aIn.readObject()).getOctets();
388b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        aIn = new ASN1InputStream(authBytes);
389b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
390e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                        AuthorityKeyIdentifier id = AuthorityKeyIdentifier.getInstance(aIn.readObject());
391b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        if (id.getKeyIdentifier() != null)
392b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
393b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            nextC = (Certificate)chainCerts.get(new CertId(id.getKeyIdentifier()));
394b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
395a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
396b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
397b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    catch (IOException e)
398b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
399b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        throw new RuntimeException(e.toString());
400b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
401b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
402b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
403b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (nextC == null)
404b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
405b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
406b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    // no authority key id, try the Issuer DN
407b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
408a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    Principal i = x509c.getIssuerDN();
409a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    Principal s = x509c.getSubjectDN();
410b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
411b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    if (!i.equals(s))
412b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
413b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        Enumeration e = chainCerts.keys();
414b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
415b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        while (e.hasMoreElements())
416b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
417b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            X509Certificate crt = (X509Certificate)chainCerts.get(e.nextElement());
418a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            Principal sub = crt.getSubjectDN();
419b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            if (sub.equals(i))
420b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
421b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                try
422b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
423b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    x509c.verify(crt.getPublicKey());
424b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    nextC = crt;
425b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    break;
426b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
427b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                catch (Exception ex)
428b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
429b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    // continue
430b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
431b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
432b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
433b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
434b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
435b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
436b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                cs.addElement(c);
437b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (nextC != c)     // self signed - end of the chain
438b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
439b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    c = nextC;
440b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
441b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                else
442b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
443b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    c = null;
444b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
445b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
446b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
447a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            Certificate[] certChain = new Certificate[cs.size()];
448b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
449b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            for (int i = 0; i != certChain.length; i++)
450b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
451b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certChain[i] = (Certificate)cs.elementAt(i);
452b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
453b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
454b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return certChain;
455b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
456b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
457b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return null;
458b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
459a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
460a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    public Date engineGetCreationDate(String alias)
461b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
462e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        if (alias == null)
463e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
4648e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            throw new NullPointerException("alias == null");
4658e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
466e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        if (keys.get(alias) == null && certs.get(alias) == null)
467e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
4688e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            return null;
4698e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
470b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return new Date();
471b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
472b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
473b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public Key engineGetKey(
474b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String alias,
475a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        char[] password)
476b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws NoSuchAlgorithmException, UnrecoverableKeyException
477b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
478b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (alias == null)
479b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
480b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IllegalArgumentException("null alias passed to getKey.");
481b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
482a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
483b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return (Key)keys.get(alias);
484b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
485b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
486b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public boolean engineIsCertificateEntry(
487a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        String alias)
488b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
489b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return (certs.get(alias) != null && keys.get(alias) == null);
490b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
491b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
492b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public boolean engineIsKeyEntry(
493a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        String alias)
494b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
495b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return (keys.get(alias) != null);
496b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
497b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
498b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void engineSetCertificateEntry(
499a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        String alias,
500a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        Certificate cert)
501b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws KeyStoreException
502b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
503c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (keys.get(alias) != null)
504b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
505c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            throw new KeyStoreException("There is a key entry with the name " + alias + ".");
506b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
507b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
508b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        certs.put(alias, cert);
509b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        chainCerts.put(new CertId(cert.getPublicKey()), cert);
510b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
511b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
512b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void engineSetKeyEntry(
513b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String alias,
514b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[] key,
515a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        Certificate[] chain)
516b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws KeyStoreException
517b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
518b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throw new RuntimeException("operation not supported");
519b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
520b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
521b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void engineSetKeyEntry(
522a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        String alias,
523a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        Key key,
524a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        char[] password,
525a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        Certificate[] chain)
526b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws KeyStoreException
527b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
528e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        if (!(key instanceof PrivateKey))
529e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
5308e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            throw new KeyStoreException("PKCS12 does not support non-PrivateKeys");
5318e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
532e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
533b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if ((key instanceof PrivateKey) && (chain == null))
534b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
535b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new KeyStoreException("no certificate chain for private key");
536b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
537b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
538c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (keys.get(alias) != null)
539b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
540c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            engineDeleteEntry(alias);
541b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
542b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
543b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        keys.put(alias, key);
544e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        if (chain != null)
545b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
546e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            certs.put(alias, chain[0]);
547e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
548e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            for (int i = 0; i != chain.length; i++)
549e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            {
550e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                chainCerts.put(new CertId(chain[i].getPublicKey()), chain[i]);
551e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            }
5528e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
553b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
554b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
555a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    public int engineSize()
556b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
557a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        Hashtable tab = new Hashtable();
558b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
559b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Enumeration e = certs.keys();
560b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (e.hasMoreElements())
561b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
562b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            tab.put(e.nextElement(), "cert");
563b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
564b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
565b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        e = keys.keys();
566b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (e.hasMoreElements())
567b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
568a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            String a = (String)e.nextElement();
569b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (tab.get(a) == null)
570b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
571b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                tab.put(a, "key");
572b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
573b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
574b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
575b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return tab.size();
576b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
577b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
578b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected PrivateKey unwrapKey(
579a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        AlgorithmIdentifier algId,
580a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        byte[] data,
581a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        char[] password,
582a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        boolean wrongPKCS12Zero)
583b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
584b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
585a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        ASN1ObjectIdentifier algorithm = algId.getAlgorithm();
586b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
587b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
588a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            if (algorithm.on(PKCSObjectIdentifiers.pkcs_12PbeIds))
589a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            {
590a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters());
591b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
592a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                PBEKeySpec pbeSpec = new PBEKeySpec(password);
593a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                PrivateKey out;
594b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
595a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                SecretKeyFactory keyFact = SecretKeyFactory.getInstance(
596a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    algorithm.getId(), bcProvider);
597a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                PBEParameterSpec defParams = new PBEParameterSpec(
598a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    pbeParams.getIV(),
599a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    pbeParams.getIterations().intValue());
600a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
601a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                SecretKey k = keyFact.generateSecret(pbeSpec);
602a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
603a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                ((BCPBEKey)k).setTryWrongPKCS12Zero(wrongPKCS12Zero);
604a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
605a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                Cipher cipher = Cipher.getInstance(algorithm.getId(), bcProvider);
606b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
607a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                cipher.init(Cipher.UNWRAP_MODE, k, defParams);
608a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
609a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                // we pass "" as the key algorithm type as it is unknown at this point
610a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                return (PrivateKey)cipher.unwrap(data, "", Cipher.PRIVATE_KEY);
611a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            }
612a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            else if (algorithm.equals(PKCSObjectIdentifiers.id_PBES2))
613a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            {
614b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
6155db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                Cipher cipher = createCipher(Cipher.UNWRAP_MODE, password, algId);
616a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
617a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                // we pass "" as the key algorithm type as it is unknown at this point
618a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                return (PrivateKey)cipher.unwrap(data, "", Cipher.PRIVATE_KEY);
619a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            }
620b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
621b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (Exception e)
622b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
623b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IOException("exception unwrapping private key - " + e.toString());
624b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
625b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
626a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        throw new IOException("exception unwrapping private key - cannot recognise: " + algorithm);
627b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
628b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
629b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected byte[] wrapKey(
630a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        String algorithm,
631a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        Key key,
632a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        PKCS12PBEParams pbeParams,
633a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        char[] password)
634b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
635b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
636a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        PBEKeySpec pbeSpec = new PBEKeySpec(password);
637a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        byte[] out;
638b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
639b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
640b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
641a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            SecretKeyFactory keyFact = SecretKeyFactory.getInstance(
642a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                algorithm, bcProvider);
643a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            PBEParameterSpec defParams = new PBEParameterSpec(
644a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                pbeParams.getIV(),
645a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                pbeParams.getIterations().intValue());
646b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
647c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            Cipher cipher = Cipher.getInstance(algorithm, bcProvider);
648b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
649b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            cipher.init(Cipher.WRAP_MODE, keyFact.generateSecret(pbeSpec), defParams);
650b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
651b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            out = cipher.wrap(key);
652b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
653b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (Exception e)
654b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
655b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IOException("exception encrypting data - " + e.toString());
656b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
657b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
658b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return out;
659b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
660b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
661c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    protected byte[] cryptData(
662a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        boolean forEncryption,
663a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        AlgorithmIdentifier algId,
664a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        char[] password,
665a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        boolean wrongPKCS12Zero,
666a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        byte[] data)
667b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
668b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
6695db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        ASN1ObjectIdentifier algorithm = algId.getAlgorithm();
670b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
6715db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        if (algorithm.on(PKCSObjectIdentifiers.pkcs_12PbeIds))
672b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
6735db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters());
6745db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            PBEKeySpec pbeSpec = new PBEKeySpec(password);
675c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
6765db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            try
6775db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            {
6785db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm.getId(), bcProvider);
6795db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                PBEParameterSpec defParams = new PBEParameterSpec(
6805db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                    pbeParams.getIV(),
6815db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                    pbeParams.getIterations().intValue());
6825db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                BCPBEKey key = (BCPBEKey)keyFact.generateSecret(pbeSpec);
683c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
6845db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                key.setTryWrongPKCS12Zero(wrongPKCS12Zero);
6855db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
6865db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                Cipher cipher = Cipher.getInstance(algorithm.getId(), bcProvider);
6875db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
6885db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                cipher.init(mode, key, defParams);
6895db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                return cipher.doFinal(data);
6905db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            }
6915db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            catch (Exception e)
6925db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            {
6935db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                throw new IOException("exception decrypting data - " + e.toString());
6945db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            }
695b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
6965db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        else  if (algorithm.equals(PKCSObjectIdentifiers.id_PBES2))
697b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
6985db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            try
6995db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            {
7005db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                Cipher cipher = createCipher(Cipher.DECRYPT_MODE, password, algId);
7015db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
7025db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                return cipher.doFinal(data);
7035db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            }
7045db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            catch (Exception e)
7055db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            {
7065db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                throw new IOException("exception decrypting data - " + e.toString());
7075db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            }
7085db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        }
7095db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        else
7105db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        {
7115db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            throw new IOException("unknown PBE algorithm: " + algorithm);
712b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
713b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
714b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
7155db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    private Cipher createCipher(int mode, char[] password, AlgorithmIdentifier algId)
7165db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException
7175db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    {
7185db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        PBES2Parameters alg = PBES2Parameters.getInstance(algId.getParameters());
7195db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        PBKDF2Params func = PBKDF2Params.getInstance(alg.getKeyDerivationFunc().getParameters());
7205db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        AlgorithmIdentifier encScheme = AlgorithmIdentifier.getInstance(alg.getEncryptionScheme());
7215db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
7225db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        SecretKeyFactory keyFact = SecretKeyFactory.getInstance(alg.getKeyDerivationFunc().getAlgorithm().getId(), bcProvider);
7235db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        SecretKey key;
7245db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
7255db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        if (func.isDefaultPrf())
7265db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        {
7275db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            key = keyFact.generateSecret(new PBEKeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme)));
7285db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        }
7295db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        else
7305db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        {
7315db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            key = keyFact.generateSecret(new PBKDF2KeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme), func.getPrf()));
7325db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        }
7335db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
7345db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        Cipher cipher = Cipher.getInstance(alg.getEncryptionScheme().getAlgorithm().getId());
7355db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
7365db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        AlgorithmIdentifier encryptionAlg = AlgorithmIdentifier.getInstance(alg.getEncryptionScheme());
7375db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
7385db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        ASN1Encodable encParams = alg.getEncryptionScheme().getParameters();
7395db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        if (encParams instanceof ASN1OctetString)
7405db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        {
7415db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            cipher.init(mode, key, new IvParameterSpec(ASN1OctetString.getInstance(encParams).getOctets()));
7425db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        }
7435db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        // BEGIN android-removed
7445db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        // else
7455db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        // {
7465db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //     // TODO: at the moment it's just GOST, but...
7475db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //     GOST28147Parameters gParams = GOST28147Parameters.getInstance(encParams);
7485db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //
7495db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //     cipher.init(mode, key, new GOST28147ParameterSpec(gParams.getEncryptionParamSet(), gParams.getIV()));
7505db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        // }
7515db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        // END android-removed
7525db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        return cipher;
7535db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    }
7545db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
755b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void engineLoad(
756b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        InputStream stream,
757a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        char[] password)
758b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
759b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
760b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (stream == null)     // just initialising
761b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
762b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return;
763b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
764b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
765b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (password == null)
766b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
767b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new NullPointerException("No password supplied for PKCS#12 KeyStore.");
768b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
769b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
770a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        BufferedInputStream bufIn = new BufferedInputStream(stream);
771b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
772b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bufIn.mark(10);
773b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
774b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int head = bufIn.read();
775b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
776b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (head != 0x30)
777b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
778b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IOException("stream does not represent a PKCS12 key store");
779b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
780b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
781b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bufIn.reset();
782b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
783b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        ASN1InputStream bIn = new ASN1InputStream(bufIn);
784a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        ASN1Sequence obj = (ASN1Sequence)bIn.readObject();
785a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        Pfx bag = Pfx.getInstance(obj);
786a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        ContentInfo info = bag.getAuthSafe();
787a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        Vector chain = new Vector();
788a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        boolean unmarkedKey = false;
789a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        boolean wrongPKCS12Zero = false;
790b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
791b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (bag.getMacData() != null)           // check the mac code
792b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
793a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            MacData mData = bag.getMacData();
794a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            DigestInfo dInfo = mData.getMac();
795a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            AlgorithmIdentifier algId = dInfo.getAlgorithmId();
796a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            byte[] salt = mData.getSalt();
797a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            int itCount = mData.getIterationCount().intValue();
798b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
799a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            byte[] data = ((ASN1OctetString)info.getContent()).getOctets();
800b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
801b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            try
802b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
803a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                byte[] res = calculatePbeMac(algId.getAlgorithm(), salt, itCount, password, false, data);
804c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                byte[] dig = dInfo.getDigest();
805b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
806c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                if (!Arrays.constantTimeAreEqual(res, dig))
807b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
808c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    if (password.length > 0)
809b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
810c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        throw new IOException("PKCS12 key store mac invalid - wrong password or corrupted file.");
811b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
812c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
813c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    // Try with incorrect zero length password
814a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    res = calculatePbeMac(algId.getAlgorithm(), salt, itCount, password, true, data);
815c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
816c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    if (!Arrays.constantTimeAreEqual(res, dig))
817b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
818c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        throw new IOException("PKCS12 key store mac invalid - wrong password or corrupted file.");
819b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
820c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
821b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    wrongPKCS12Zero = true;
822b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
823b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
824b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (IOException e)
825b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
826b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw e;
827b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
828b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (Exception e)
829b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
830b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new IOException("error constructing MAC: " + e.toString());
831b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
832b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
833b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
834c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        keys = new IgnoresCaseHashtable();
835b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        localIds = new Hashtable();
836b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
837b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (info.getContentType().equals(data))
838b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
839b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            bIn = new ASN1InputStream(((ASN1OctetString)info.getContent()).getOctets());
840b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
841a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            AuthenticatedSafe authSafe = AuthenticatedSafe.getInstance(bIn.readObject());
842a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            ContentInfo[] c = authSafe.getContentInfo();
843b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
844b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            for (int i = 0; i != c.length; i++)
845b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
846b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (c[i].getContentType().equals(data))
847b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
848b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    ASN1InputStream dIn = new ASN1InputStream(((ASN1OctetString)c[i].getContent()).getOctets());
849a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    ASN1Sequence seq = (ASN1Sequence)dIn.readObject();
850b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
851b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    for (int j = 0; j != seq.size(); j++)
852b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
8534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        SafeBag b = SafeBag.getInstance(seq.getObjectAt(j));
854b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        if (b.getBagId().equals(pkcs8ShroudedKeyBag))
855b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
8564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                            org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo eIn = org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo.getInstance(b.getBagValue());
857a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            PrivateKey privKey = unwrapKey(eIn.getEncryptionAlgorithm(), eIn.getEncryptedData(), password, wrongPKCS12Zero);
858b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
859b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            //
860b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            // set the attributes on the key
861b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            //
862a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey;
863a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            String alias = null;
864a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            ASN1OctetString localId = null;
865b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
866b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            if (b.getBagAttributes() != null)
867b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
868b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                Enumeration e = b.getBagAttributes().getObjects();
869b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                while (e.hasMoreElements())
870b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
871a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                                    ASN1Sequence sq = (ASN1Sequence)e.nextElement();
872a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                                    ASN1ObjectIdentifier aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0);
873a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                                    ASN1Set attrSet = (ASN1Set)sq.getObjectAt(1);
874a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                                    ASN1Primitive attr = null;
875a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
876b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    if (attrSet.size() > 0)
877b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    {
8784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        attr = (ASN1Primitive)attrSet.getObjectAt(0);
879c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
8804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        ASN1Encodable existing = bagAttr.getBagAttribute(aOid);
881c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        if (existing != null)
882c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        {
883c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                            // OK, but the value has to be the same
8844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                            if (!existing.toASN1Primitive().equals(attr))
885c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                            {
886c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                                throw new IOException(
887c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                                    "attempt to add existing attribute with different value");
888c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                            }
889c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        }
890c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        else
891c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        {
892c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                            bagAttr.setBagAttribute(aOid, attr);
893c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        }
894b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    }
895a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
896b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    if (aOid.equals(pkcs_9_at_friendlyName))
897b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    {
898b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                        alias = ((DERBMPString)attr).getString();
899b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                        keys.put(alias, privKey);
900b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    }
901b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    else if (aOid.equals(pkcs_9_at_localKeyId))
902b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    {
903b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                        localId = (ASN1OctetString)attr;
904b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    }
905b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
906b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
907a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
908b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            if (localId != null)
909b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
910b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                String name = new String(Hex.encode(localId.getOctets()));
911a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
912b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                if (alias == null)
913b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
914b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    keys.put(name, privKey);
915b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
916b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                else
917b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
918b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    localIds.put(alias, name);
919b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
920a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            }
921a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            else
922a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            {
923a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                                unmarkedKey = true;
924a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                                keys.put("unmarked", privKey);
925a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            }
926b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
927b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        else if (b.getBagId().equals(certBag))
928b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
929b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            chain.addElement(b);
930b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
931b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        else
932b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
933b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            System.out.println("extra in data " + b.getBagId());
934b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            System.out.println(ASN1Dump.dumpAsString(b));
935b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
936b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
937b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
938b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                else if (c[i].getContentType().equals(encryptedData))
939b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
9404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    EncryptedData d = EncryptedData.getInstance(c[i].getContent());
941c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    byte[] octets = cryptData(false, d.getEncryptionAlgorithm(),
942c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        password, wrongPKCS12Zero, d.getContent().getOctets());
943a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    ASN1Sequence seq = (ASN1Sequence)ASN1Primitive.fromByteArray(octets);
944b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
945b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    for (int j = 0; j != seq.size(); j++)
946b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
9474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        SafeBag b = SafeBag.getInstance(seq.getObjectAt(j));
948a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
949b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        if (b.getBagId().equals(certBag))
950b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
951b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            chain.addElement(b);
952b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
953b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        else if (b.getBagId().equals(pkcs8ShroudedKeyBag))
954b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
9554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                            org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo eIn = org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo.getInstance(b.getBagValue());
956a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            PrivateKey privKey = unwrapKey(eIn.getEncryptionAlgorithm(), eIn.getEncryptedData(), password, wrongPKCS12Zero);
957b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
958b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            //
959b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            // set the attributes on the key
960b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            //
961a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey;
962a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            String alias = null;
963a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            ASN1OctetString localId = null;
964b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
965b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            Enumeration e = b.getBagAttributes().getObjects();
966b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            while (e.hasMoreElements())
967b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
968a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                                ASN1Sequence sq = (ASN1Sequence)e.nextElement();
969a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                                ASN1ObjectIdentifier aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0);
970a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                                ASN1Set attrSet = (ASN1Set)sq.getObjectAt(1);
971a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                                ASN1Primitive attr = null;
972b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
973b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                if (attrSet.size() > 0)
974b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
9754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    attr = (ASN1Primitive)attrSet.getObjectAt(0);
976b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
9774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    ASN1Encodable existing = bagAttr.getBagAttribute(aOid);
978c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    if (existing != null)
979c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    {
980c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        // OK, but the value has to be the same
9814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        if (!existing.toASN1Primitive().equals(attr))
982c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        {
983c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                            throw new IOException(
984c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                                "attempt to add existing attribute with different value");
985c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        }
986c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    }
987c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    else
988c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    {
989c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        bagAttr.setBagAttribute(aOid, attr);
990c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    }
991b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
992b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
993b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                if (aOid.equals(pkcs_9_at_friendlyName))
994b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
995b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    alias = ((DERBMPString)attr).getString();
996b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    keys.put(alias, privKey);
997b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
998b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                else if (aOid.equals(pkcs_9_at_localKeyId))
999b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
1000b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    localId = (ASN1OctetString)attr;
1001b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
1002b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
1003b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1004b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            String name = new String(Hex.encode(localId.getOctets()));
1005b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1006b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            if (alias == null)
1007b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
1008b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                keys.put(name, privKey);
1009b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
1010b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            else
1011b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
1012b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                localIds.put(alias, name);
1013b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
1014b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
1015b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        else if (b.getBagId().equals(keyBag))
1016b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
1017a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            org.bouncycastle.asn1.pkcs.PrivateKeyInfo kInfo = org.bouncycastle.asn1.pkcs.PrivateKeyInfo.getInstance(b.getBagValue());
1018a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            PrivateKey privKey = BouncyCastleProvider.getPrivateKey(kInfo);
1019b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1020b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            //
1021b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            // set the attributes on the key
1022b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            //
1023a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey;
1024a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            String alias = null;
1025a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            ASN1OctetString localId = null;
1026b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1027b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            Enumeration e = b.getBagAttributes().getObjects();
1028b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            while (e.hasMoreElements())
1029b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
1030a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                                ASN1Sequence sq = (ASN1Sequence)e.nextElement();
1031a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                                ASN1ObjectIdentifier aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0);
1032a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                                ASN1Set attrSet = (ASN1Set)sq.getObjectAt(1);
1033a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                                ASN1Primitive attr = null;
1034b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1035b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                if (attrSet.size() > 0)
1036b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
10374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    attr = (ASN1Primitive)attrSet.getObjectAt(0);
1038b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
10394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    ASN1Encodable existing = bagAttr.getBagAttribute(aOid);
1040c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    if (existing != null)
1041c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    {
1042c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        // OK, but the value has to be the same
10434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        if (!existing.toASN1Primitive().equals(attr))
1044c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        {
1045c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                            throw new IOException(
1046c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                                "attempt to add existing attribute with different value");
1047c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        }
1048c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    }
1049c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    else
1050c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    {
1051c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        bagAttr.setBagAttribute(aOid, attr);
1052c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    }
1053b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
1054b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1055b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                if (aOid.equals(pkcs_9_at_friendlyName))
1056b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
1057b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    alias = ((DERBMPString)attr).getString();
1058b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    keys.put(alias, privKey);
1059b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
1060b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                else if (aOid.equals(pkcs_9_at_localKeyId))
1061b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
1062b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    localId = (ASN1OctetString)attr;
1063b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
1064b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
1065b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1066b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            String name = new String(Hex.encode(localId.getOctets()));
1067b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1068b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            if (alias == null)
1069b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
1070b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                keys.put(name, privKey);
1071b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
1072b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            else
1073b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
1074b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                localIds.put(alias, name);
1075b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
1076b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
1077b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        else
1078b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
1079b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            System.out.println("extra in encryptedData " + b.getBagId());
1080b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            System.out.println(ASN1Dump.dumpAsString(b));
1081b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
1082b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1083b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1084b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                else
1085b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1086b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    System.out.println("extra " + c[i].getContentType().getId());
1087b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    System.out.println("extra " + ASN1Dump.dumpAsString(c[i].getContent()));
1088b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1089b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1090b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1091b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1092c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        certs = new IgnoresCaseHashtable();
1093b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        chainCerts = new Hashtable();
1094b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        keyCerts = new Hashtable();
1095b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1096b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        for (int i = 0; i != chain.size(); i++)
1097b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1098a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            SafeBag b = (SafeBag)chain.elementAt(i);
1099a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            CertBag cb = CertBag.getInstance(b.getBagValue());
1100c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1101c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (!cb.getCertId().equals(x509Certificate))
1102c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
1103c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                throw new RuntimeException("Unsupported certificate type: " + cb.getCertId());
1104c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
1105c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1106c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            Certificate cert;
1107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            try
1109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1110a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                ByteArrayInputStream cIn = new ByteArrayInputStream(
1111a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    ((ASN1OctetString)cb.getCertValue()).getOctets());
1112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                cert = certFact.generateCertificate(cIn);
1113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (Exception e)
1115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new RuntimeException(e.toString());
1117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            //
1120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            // set the attributes
1121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            //
1122c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            ASN1OctetString localId = null;
1123a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            String alias = null;
1124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1125b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (b.getBagAttributes() != null)
1126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                Enumeration e = b.getBagAttributes().getObjects();
1128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                while (e.hasMoreElements())
1129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1130a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    ASN1Sequence sq = (ASN1Sequence)e.nextElement();
1131a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)sq.getObjectAt(0);
1132a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    ASN1Primitive attr = (ASN1Primitive)((ASN1Set)sq.getObjectAt(1)).getObjectAt(0);
1133a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    PKCS12BagAttributeCarrier bagAttr = null;
1134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    if (cert instanceof PKCS12BagAttributeCarrier)
1136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
1137c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        bagAttr = (PKCS12BagAttributeCarrier)cert;
1138c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
11394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        ASN1Encodable existing = bagAttr.getBagAttribute(oid);
1140c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        if (existing != null)
1141c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        {
1142c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                            // OK, but the value has to be the same
11434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                            if (!existing.toASN1Primitive().equals(attr))
1144c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                            {
1145c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                throw new IOException(
1146c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    "attempt to add existing attribute with different value");
1147c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                            }
1148c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        }
1149c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        else
1150c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        {
1151c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                            bagAttr.setBagAttribute(oid, attr);
1152c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        }
1153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    if (oid.equals(pkcs_9_at_friendlyName))
1156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
1157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        alias = ((DERBMPString)attr).getString();
1158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    else if (oid.equals(pkcs_9_at_localKeyId))
1160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
1161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        localId = (ASN1OctetString)attr;
1162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            chainCerts.put(new CertId(cert.getPublicKey()), cert);
1167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (unmarkedKey)
1169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (keyCerts.isEmpty())
1171b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1172a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    String name = new String(Hex.encode(createSubjectKeyId(cert.getPublicKey()).getKeyIdentifier()));
1173a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
1174b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    keyCerts.put(name, cert);
1175b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    keys.put(name, keys.remove("unmarked"));
1176b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1177b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1178b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
1179b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1180b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1181b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                // the local key id needs to override the friendly name
1182b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1183b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (localId != null)
1184b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1185b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    String name = new String(Hex.encode(localId.getOctets()));
1186b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1187b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    keyCerts.put(name, cert);
1188b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1189b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (alias != null)
1190b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1191b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    certs.put(alias, cert);
1192b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1193b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1194b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1195b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
1196b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1197a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    public void engineStore(LoadStoreParameter param)
1198a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        throws IOException,
1199a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        NoSuchAlgorithmException, CertificateException
12006e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
12016e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (param == null)
12026e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
12036e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            throw new IllegalArgumentException("'param' arg cannot be null");
12046e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
12056e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1206a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        if (!(param instanceof PKCS12StoreParameter || param instanceof JDKPKCS12StoreParameter))
12076e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
12086e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            throw new IllegalArgumentException(
12096e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                "No support for 'param' of type " + param.getClass().getName());
12106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
12116e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1212a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        PKCS12StoreParameter bcParam;
1213a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
1214a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        if (param instanceof PKCS12StoreParameter)
1215a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        {
1216a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            bcParam = (PKCS12StoreParameter)param;
1217a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        }
1218a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        else
1219a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        {
1220a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            bcParam = new PKCS12StoreParameter(((JDKPKCS12StoreParameter)param).getOutputStream(),
1221a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                param.getProtectionParameter(), ((JDKPKCS12StoreParameter)param).isUseDEREncoding());
1222a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        }
12236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
12246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        char[] password;
12256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        ProtectionParameter protParam = param.getProtectionParameter();
12266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (protParam == null)
12276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
12286e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            password = null;
12296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
12306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else if (protParam instanceof KeyStore.PasswordProtection)
12316e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
12326e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            password = ((KeyStore.PasswordProtection)protParam).getPassword();
12336e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
12346e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else
12356e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
12366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            throw new IllegalArgumentException(
12376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                "No support for protection parameter of type " + protParam.getClass().getName());
12386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
12396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1240a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        doStore(bcParam.getOutputStream(), password, bcParam.isForDEREncoding());
12416e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
12426e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1243a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    public void engineStore(OutputStream stream, char[] password)
1244b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
1245b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
12466e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        doStore(stream, password, false);
12476e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
12486e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1249a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private void doStore(OutputStream stream, char[] password, boolean useDEREncoding)
12506e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        throws IOException
12516e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
1252b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (password == null)
1253b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1254b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new NullPointerException("No password supplied for PKCS#12 KeyStore.");
1255b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1256b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1257b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1258b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // handle the key
1259b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1260a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        ASN1EncodableVector keyS = new ASN1EncodableVector();
1261b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1262b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1263b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Enumeration ks = keys.keys();
1264b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1265b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (ks.hasMoreElements())
1266b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1267a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            byte[] kSalt = new byte[SALT_SIZE];
1268b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1269b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            random.nextBytes(kSalt);
1270b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1271a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            String name = (String)ks.nextElement();
1272a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            PrivateKey privKey = (PrivateKey)keys.get(name);
1273a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            PKCS12PBEParams kParams = new PKCS12PBEParams(kSalt, MIN_ITERATIONS);
1274a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            byte[] kBytes = wrapKey(keyAlgorithm.getId(), privKey, kParams, password);
1275a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            AlgorithmIdentifier kAlgId = new AlgorithmIdentifier(keyAlgorithm, kParams.toASN1Primitive());
1276b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo kInfo = new org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo(kAlgId, kBytes);
1277a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            boolean attrSet = false;
1278a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            ASN1EncodableVector kName = new ASN1EncodableVector();
1279b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1280b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (privKey instanceof PKCS12BagAttributeCarrier)
1281b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1282a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)privKey;
1283b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1284b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                // make sure we are using the local alias on store
1285b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1286a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                DERBMPString nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName);
1287b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (nm == null || !nm.getString().equals(name))
1288b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1289b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(name));
1290b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1291b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1292b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1293b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                // make sure we have a local key-id
1294b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1295b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (bagAttrs.getBagAttribute(pkcs_9_at_localKeyId) == null)
1296b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1297a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    Certificate ct = engineGetCertificate(name);
1298b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1299b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    bagAttrs.setBagAttribute(pkcs_9_at_localKeyId, createSubjectKeyId(ct.getPublicKey()));
1300b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1301b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1302b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                Enumeration e = bagAttrs.getBagAttributeKeys();
1303b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1304b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                while (e.hasMoreElements())
1305b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
13064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
1307a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    ASN1EncodableVector kSeq = new ASN1EncodableVector();
1308b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1309b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    kSeq.add(oid);
1310b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    kSeq.add(new DERSet(bagAttrs.getBagAttribute(oid)));
1311b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1312b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    attrSet = true;
1313b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1314b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    kName.add(new DERSequence(kSeq));
1315b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1316b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1317b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1318b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (!attrSet)
1319b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1320b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1321b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                // set a default friendly name (from the key id) and local id
1322b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1323a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                ASN1EncodableVector kSeq = new ASN1EncodableVector();
1324a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                Certificate ct = engineGetCertificate(name);
1325b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1326b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                kSeq.add(pkcs_9_at_localKeyId);
1327b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                kSeq.add(new DERSet(createSubjectKeyId(ct.getPublicKey())));
1328b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1329b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                kName.add(new DERSequence(kSeq));
1330b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1331b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                kSeq = new ASN1EncodableVector();
1332b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1333b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                kSeq.add(pkcs_9_at_friendlyName);
1334b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                kSeq.add(new DERSet(new DERBMPString(name)));
1335b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1336b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                kName.add(new DERSequence(kSeq));
1337b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1338b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1339a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            SafeBag kBag = new SafeBag(pkcs8ShroudedKeyBag, kInfo.toASN1Primitive(), new DERSet(kName));
1340b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            keyS.add(kBag);
1341b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1342b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1343a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        byte[] keySEncoded = new DERSequence(keyS).getEncoded(ASN1Encoding.DER);
1344e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        BEROctetString keyString = new BEROctetString(keySEncoded);
1345b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1346b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1347c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        // certificate processing
1348b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1349a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        byte[] cSalt = new byte[SALT_SIZE];
1350b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1351b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        random.nextBytes(cSalt);
1352b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1353a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        ASN1EncodableVector certSeq = new ASN1EncodableVector();
1354a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        PKCS12PBEParams cParams = new PKCS12PBEParams(cSalt, MIN_ITERATIONS);
1355a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        AlgorithmIdentifier cAlgId = new AlgorithmIdentifier(certAlgorithm, cParams.toASN1Primitive());
1356a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        Hashtable doneCerts = new Hashtable();
1357b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1358b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Enumeration cs = keys.keys();
1359b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (cs.hasMoreElements())
1360b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1361b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            try
1362b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1363a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                String name = (String)cs.nextElement();
1364a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                Certificate cert = engineGetCertificate(name);
1365a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                boolean cAttrSet = false;
1366a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                CertBag cBag = new CertBag(
1367a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    x509Certificate,
1368a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    new DEROctetString(cert.getEncoded()));
1369b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                ASN1EncodableVector fName = new ASN1EncodableVector();
1370b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1371b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (cert instanceof PKCS12BagAttributeCarrier)
1372b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1373a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)cert;
1374b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
1375b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    // make sure we are using the local alias on store
1376b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
1377a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    DERBMPString nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName);
1378b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    if (nm == null || !nm.getString().equals(name))
1379b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
1380b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(name));
1381b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1382b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1383b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
1384b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    // make sure we have a local key-id
1385b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
1386b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    if (bagAttrs.getBagAttribute(pkcs_9_at_localKeyId) == null)
1387b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
1388b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        bagAttrs.setBagAttribute(pkcs_9_at_localKeyId, createSubjectKeyId(cert.getPublicKey()));
1389b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1390b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1391b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    Enumeration e = bagAttrs.getBagAttributeKeys();
1392b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1393b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    while (e.hasMoreElements())
1394b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
13954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
1396b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        ASN1EncodableVector fSeq = new ASN1EncodableVector();
1397b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1398b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fSeq.add(oid);
1399b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid)));
1400b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fName.add(new DERSequence(fSeq));
1401b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1402b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        cAttrSet = true;
1403b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1404b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1405b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1406b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (!cAttrSet)
1407b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1408a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    ASN1EncodableVector fSeq = new ASN1EncodableVector();
1409b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1410b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fSeq.add(pkcs_9_at_localKeyId);
1411b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fSeq.add(new DERSet(createSubjectKeyId(cert.getPublicKey())));
1412b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fName.add(new DERSequence(fSeq));
1413b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1414b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fSeq = new ASN1EncodableVector();
1415b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1416b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fSeq.add(pkcs_9_at_friendlyName);
1417b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fSeq.add(new DERSet(new DERBMPString(name)));
1418b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1419b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fName.add(new DERSequence(fSeq));
1420b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1421b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
14224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                SafeBag sBag = new SafeBag(certBag, cBag.toASN1Primitive(), new DERSet(fName));
1423b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1424b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certSeq.add(sBag);
1425b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1426b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                doneCerts.put(cert, cert);
1427b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1428b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (CertificateEncodingException e)
1429b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1430b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new IOException("Error encoding certificate: " + e.toString());
1431b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1432b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1433b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1434b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        cs = certs.keys();
1435b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (cs.hasMoreElements())
1436b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1437b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            try
1438b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1439a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                String certId = (String)cs.nextElement();
1440a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                Certificate cert = (Certificate)certs.get(certId);
1441a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                boolean cAttrSet = false;
1442b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1443b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (keys.get(certId) != null)
1444b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1445b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    continue;
1446b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1447b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1448a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                CertBag cBag = new CertBag(
1449a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    x509Certificate,
1450a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    new DEROctetString(cert.getEncoded()));
1451b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                ASN1EncodableVector fName = new ASN1EncodableVector();
1452b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1453b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (cert instanceof PKCS12BagAttributeCarrier)
1454b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1455a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)cert;
1456b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
1457b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    // make sure we are using the local alias on store
1458b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
1459a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    DERBMPString nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName);
1460b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    if (nm == null || !nm.getString().equals(certId))
1461b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
1462b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(certId));
1463b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1464b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1465b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    Enumeration e = bagAttrs.getBagAttributeKeys();
1466b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1467b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    while (e.hasMoreElements())
1468b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
14694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
1470c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1471c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        // a certificate not immediately linked to a key doesn't require
1472c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        // a localKeyID and will confuse some PKCS12 implementations.
1473c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        //
1474c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        // If we find one, we'll prune it out.
1475c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        if (oid.equals(PKCSObjectIdentifiers.pkcs_9_at_localKeyId))
1476c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        {
1477c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                            continue;
1478c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        }
1479c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1480b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        ASN1EncodableVector fSeq = new ASN1EncodableVector();
1481b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1482b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fSeq.add(oid);
1483b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid)));
1484b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fName.add(new DERSequence(fSeq));
1485b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1486b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        cAttrSet = true;
1487b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1488b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1489b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1490b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (!cAttrSet)
1491b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1492a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    ASN1EncodableVector fSeq = new ASN1EncodableVector();
1493b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1494b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fSeq.add(pkcs_9_at_friendlyName);
1495b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fSeq.add(new DERSet(new DERBMPString(certId)));
1496b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1497b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fName.add(new DERSequence(fSeq));
1498b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1499b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
15004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                SafeBag sBag = new SafeBag(certBag, cBag.toASN1Primitive(), new DERSet(fName));
1501b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1502b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certSeq.add(sBag);
1503b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1504b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                doneCerts.put(cert, cert);
1505b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1506b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (CertificateEncodingException e)
1507b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1508b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new IOException("Error encoding certificate: " + e.toString());
1509b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1510b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1511b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1512b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        cs = chainCerts.keys();
1513b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (cs.hasMoreElements())
1514b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1515b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            try
1516b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1517a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                CertId certId = (CertId)cs.nextElement();
1518a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                Certificate cert = (Certificate)chainCerts.get(certId);
1519b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1520b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (doneCerts.get(cert) != null)
1521b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1522b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    continue;
1523b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1524b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1525a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                CertBag cBag = new CertBag(
1526a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    x509Certificate,
1527a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    new DEROctetString(cert.getEncoded()));
1528b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                ASN1EncodableVector fName = new ASN1EncodableVector();
1529b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1530b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (cert instanceof PKCS12BagAttributeCarrier)
1531b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1532a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)cert;
1533b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    Enumeration e = bagAttrs.getBagAttributeKeys();
1534b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1535b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    while (e.hasMoreElements())
1536b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
15374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
1538c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1539c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        // a certificate not immediately linked to a key doesn't require
1540c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        // a localKeyID and will confuse some PKCS12 implementations.
1541c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        //
1542c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        // If we find one, we'll prune it out.
1543c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        if (oid.equals(PKCSObjectIdentifiers.pkcs_9_at_localKeyId))
1544c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        {
1545c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                            continue;
1546c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        }
1547c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1548b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        ASN1EncodableVector fSeq = new ASN1EncodableVector();
1549b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1550b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fSeq.add(oid);
1551b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid)));
1552b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fName.add(new DERSequence(fSeq));
1553b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1554b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1555b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
15564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                SafeBag sBag = new SafeBag(certBag, cBag.toASN1Primitive(), new DERSet(fName));
1557b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1558b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certSeq.add(sBag);
1559b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1560b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (CertificateEncodingException e)
1561b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1562b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new IOException("Error encoding certificate: " + e.toString());
1563b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1564b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1565b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1566a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        byte[] certSeqEncoded = new DERSequence(certSeq).getEncoded(ASN1Encoding.DER);
1567a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        byte[] certBytes = cryptData(true, cAlgId, password, false, certSeqEncoded);
1568a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        EncryptedData cInfo = new EncryptedData(data, cAlgId, new BEROctetString(certBytes));
1569b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1570c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        ContentInfo[] info = new ContentInfo[]
1571a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            {
1572a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                new ContentInfo(data, keyString),
1573a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                new ContentInfo(encryptedData, cInfo.toASN1Primitive())
1574a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            };
1575b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1576a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        AuthenticatedSafe auth = new AuthenticatedSafe(info);
1577b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1578a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
15796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        DEROutputStream asn1Out;
15806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (useDEREncoding)
15816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
15826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            asn1Out = new DEROutputStream(bOut);
15836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
15846e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else
15856e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
15866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            asn1Out = new BEROutputStream(bOut);
15876e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
1588b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
15896e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        asn1Out.writeObject(auth);
1590b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1591a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        byte[] pkg = bOut.toByteArray();
1592b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1593a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        ContentInfo mainInfo = new ContentInfo(data, new BEROctetString(pkg));
1594b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1595b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1596b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // create the mac
1597b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1598a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        byte[] mSalt = new byte[20];
1599a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        int itCount = MIN_ITERATIONS;
1600b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1601b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        random.nextBytes(mSalt);
1602b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1603a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        byte[] data = ((ASN1OctetString)mainInfo.getContent()).getOctets();
1604a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
1605a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        MacData mData;
1606b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1607b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
1608b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1609c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            byte[] res = calculatePbeMac(id_SHA1, mSalt, itCount, password, false, data);
1610b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1611a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            AlgorithmIdentifier algId = new AlgorithmIdentifier(id_SHA1, DERNull.INSTANCE);
1612a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            DigestInfo dInfo = new DigestInfo(algId, res);
1613b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1614b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            mData = new MacData(dInfo, mSalt, itCount);
1615b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1616b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (Exception e)
1617b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1618b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IOException("error constructing MAC: " + e.toString());
1619b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1620a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
1621b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1622b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // output the Pfx
1623b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1624a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        Pfx pfx = new Pfx(mainInfo, mData);
1625b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
16266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (useDEREncoding)
16276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
16286e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            asn1Out = new DEROutputStream(stream);
16296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
16306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else
16316e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
16326e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            asn1Out = new BEROutputStream(stream);
16336e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
1634b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
16356e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        asn1Out.writeObject(pfx);
1636b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
1637b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1638c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static byte[] calculatePbeMac(
16394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1ObjectIdentifier oid,
1640a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        byte[] salt,
1641a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        int itCount,
1642a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        char[] password,
1643a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        boolean wrongPkcs12Zero,
1644a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        byte[] data)
1645c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        throws Exception
1646c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
1647a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        SecretKeyFactory keyFact = SecretKeyFactory.getInstance(oid.getId(), bcProvider);
1648a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        PBEParameterSpec defParams = new PBEParameterSpec(salt, itCount);
1649a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        PBEKeySpec pbeSpec = new PBEKeySpec(password);
1650a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        BCPBEKey key = (BCPBEKey)keyFact.generateSecret(pbeSpec);
1651c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        key.setTryWrongPKCS12Zero(wrongPkcs12Zero);
1652c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1653c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        Mac mac = Mac.getInstance(oid.getId(), bcProvider);
1654c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        mac.init(key, defParams);
1655c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        mac.update(data);
1656c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return mac.doFinal();
1657c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
1658a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
1659b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public static class BCPKCS12KeyStore
1660a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        extends PKCS12KeyStoreSpi
1661b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
1662b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        public BCPKCS12KeyStore()
1663b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
16644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            super(bcProvider, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC);
1665b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1666b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
1667b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1668c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // BEGIN android-removed
1669c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // public static class BCPKCS12KeyStore3DES
1670a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    //     extends PKCS12KeyStoreSpi
1671c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // {
1672c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //     public BCPKCS12KeyStore3DES()
1673c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //     {
1674c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //         super(bcProvider, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC);
1675c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //     }
1676c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // }
16777a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    //
16787a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    // public static class DefPKCS12KeyStore
1679a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    //     extends PKCS12KeyStoreSpi
16807a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    // {
16817a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    //     public DefPKCS12KeyStore()
16827a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    //     {
16834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    //         super(null, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC);
16847a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    //     }
16857a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    // }
16867a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    //
1687c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // public static class DefPKCS12KeyStore3DES
1688a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    //     extends PKCS12KeyStoreSpi
1689c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // {
1690c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //     public DefPKCS12KeyStore3DES()
1691c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //     {
1692c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //         super(null, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC);
1693c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //     }
1694c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // }
1695c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // END android-removed
1696c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1697c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static class IgnoresCaseHashtable
1698c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
1699c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        private Hashtable orig = new Hashtable();
1700c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        private Hashtable keys = new Hashtable();
1701c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1702c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        public void put(String key, Object value)
1703c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
17048e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            String lower = (key == null) ? null : Strings.toLowerCase(key);
1705c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            String k = (String)keys.get(lower);
1706c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (k != null)
1707c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
1708c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                orig.remove(k);
1709c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
1710c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1711c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            keys.put(lower, key);
1712c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            orig.put(key, value);
1713c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
1714c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1715c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        public Enumeration keys()
1716c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
1717c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return orig.keys();
1718c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
1719c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1720c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        public Object remove(String alias)
1721c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
17228e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            String k = (String)keys.remove(alias == null ? null : Strings.toLowerCase(alias));
1723c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (k == null)
1724c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
1725c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                return null;
1726c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
1727c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1728c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return orig.remove(k);
1729c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
1730c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1731c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        public Object get(String alias)
1732c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
17338e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            String k = (String)keys.get(alias == null ? null : Strings.toLowerCase(alias));
1734c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (k == null)
1735c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
1736c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                return null;
1737c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
1738a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
1739c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return orig.get(k);
1740c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
1741c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1742c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        public Enumeration elements()
1743c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
1744c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return orig.elements();
1745b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1746b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
17475db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
17485db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    private static class DefaultSecretKeyProvider
17495db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    {
17505db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        private final Map KEY_SIZES;
17515db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
17525db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        DefaultSecretKeyProvider()
17535db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        {
17545db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            Map keySizes = new HashMap();
17555db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
17565db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            keySizes.put(new ASN1ObjectIdentifier("1.2.840.113533.7.66.10"), Integers.valueOf(128));
17575db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
17585db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), Integers.valueOf(192));
17595db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
17605db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            keySizes.put(NISTObjectIdentifiers.id_aes128_CBC, Integers.valueOf(128));
17615db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            keySizes.put(NISTObjectIdentifiers.id_aes192_CBC, Integers.valueOf(192));
17625db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            keySizes.put(NISTObjectIdentifiers.id_aes256_CBC, Integers.valueOf(256));
17635db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
17645db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            keySizes.put(NTTObjectIdentifiers.id_camellia128_cbc, Integers.valueOf(128));
17655db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            keySizes.put(NTTObjectIdentifiers.id_camellia192_cbc, Integers.valueOf(192));
17665db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            keySizes.put(NTTObjectIdentifiers.id_camellia256_cbc, Integers.valueOf(256));
17675db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
17685db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            // BEGIN android-removed
17695db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            // keySizes.put(CryptoProObjectIdentifiers.gostR28147_gcfb, Integers.valueOf(256));
17705db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            // END android-removed
17715db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
17725db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            KEY_SIZES = Collections.unmodifiableMap(keySizes);
17735db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        }
17745db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
17755db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        public int getKeySize(AlgorithmIdentifier algorithmIdentifier)
17765db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        {
17775db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            // TODO: not all ciphers/oid relationships are this simple.
17785db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            Integer keySize = (Integer)KEY_SIZES.get(algorithmIdentifier.getAlgorithm());
17795db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
17805db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            if (keySize != null)
17815db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            {
17825db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                return keySize.intValue();
17835db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            }
17845db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
17855db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            return -1;
17865db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        }
17875db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    }
1788b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
1789