1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.jce.provider;
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;
9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.Key;
106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.KeyStore;
114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.KeyStore.LoadStoreParameter;
124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.KeyStore.ProtectionParameter;
13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.KeyStoreException;
14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.KeyStoreSpi;
15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.NoSuchAlgorithmException;
16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.Principal;
17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.PrivateKey;
18c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport java.security.Provider;
19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.PublicKey;
20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.SecureRandom;
21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.UnrecoverableKeyException;
22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.cert.Certificate;
23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.cert.CertificateEncodingException;
246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.cert.CertificateException;
25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.cert.CertificateFactory;
26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.cert.X509Certificate;
27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Date;
28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Enumeration;
29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Hashtable;
30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Vector;
31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport javax.crypto.Cipher;
33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport javax.crypto.Mac;
34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport javax.crypto.SecretKey;
35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport javax.crypto.SecretKeyFactory;
36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport javax.crypto.spec.PBEKeySpec;
37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport javax.crypto.spec.PBEParameterSpec;
38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Encodable;
40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1EncodableVector;
414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Encoding;
42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1InputStream;
434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1ObjectIdentifier;
44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1OctetString;
454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Primitive;
46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1Sequence;
47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1Set;
4870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstromimport org.bouncycastle.asn1.BEROctetString;
49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.BEROutputStream;
50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DERBMPString;
51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DERNull;
52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DEROctetString;
536e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.asn1.DEROutputStream;
54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DERSequence;
55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DERSet;
56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.AuthenticatedSafe;
57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.CertBag;
58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.ContentInfo;
59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.EncryptedData;
60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.MacData;
61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.PKCS12PBEParams;
62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.Pfx;
64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.SafeBag;
65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.util.ASN1Dump;
66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.x509.AlgorithmIdentifier;
67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.x509.DigestInfo;
6970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstromimport org.bouncycastle.asn1.x509.Extension;
70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
74b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.jce.interfaces.BCKeyStore;
75b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
76c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.util.Arrays;
77c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.util.Strings;
78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.util.encoders.Hex;
79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class JDKPKCS12KeyStore
81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    extends KeyStoreSpi
82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    implements PKCSObjectIdentifiers, X509ObjectIdentifiers, BCKeyStore
83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
84c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static final int                SALT_SIZE = 20;
85c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static final int                MIN_ITERATIONS = 1024;
86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
87c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static final Provider           bcProvider = new BouncyCastleProvider();
88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
89c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private IgnoresCaseHashtable            keys = new IgnoresCaseHashtable();
90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private Hashtable                       localIds = new Hashtable();
91c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private IgnoresCaseHashtable            certs = new IgnoresCaseHashtable();
92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private Hashtable                       chainCerts = new Hashtable();
93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private Hashtable                       keyCerts = new Hashtable();
94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // generic object types
97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    static final int NULL           = 0;
99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    static final int CERTIFICATE    = 1;
100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    static final int KEY            = 2;
101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    static final int SECRET         = 3;
102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    static final int SEALED         = 4;
103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // key types
106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    static final int    KEY_PRIVATE = 0;
108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    static final int    KEY_PUBLIC  = 1;
109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    static final int    KEY_SECRET  = 2;
110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected SecureRandom      random = new SecureRandom();
112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
113c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // use of final causes problems with JDK 1.2 compiler
114c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private CertificateFactory  certFact;
1154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private ASN1ObjectIdentifier keyAlgorithm;
1164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private ASN1ObjectIdentifier certAlgorithm;
117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private class CertId
119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  id;
121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        CertId(
123b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            PublicKey  key)
124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
125b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            this.id = createSubjectKeyId(key).getKeyIdentifier();
126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        CertId(
129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            byte[]  id)
130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            this.id = id;
132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        public int hashCode()
135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
136c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return Arrays.hashCode(id);
137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        public boolean equals(
140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            Object  o)
141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
142c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (o == this)
143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
144c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                return true;
145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
147c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (!(o instanceof CertId))
148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                return false;
150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
152c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            CertId  cId = (CertId)o;
153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
154c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return Arrays.areEqual(id, cId.id);
155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public JDKPKCS12KeyStore(
159c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        Provider provider,
1604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1ObjectIdentifier keyAlgorithm,
1614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1ObjectIdentifier certAlgorithm)
162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
163c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        this.keyAlgorithm = keyAlgorithm;
164c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        this.certAlgorithm = certAlgorithm;
165c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (provider != null)
169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certFact = CertificateFactory.getInstance("X.509", provider);
171b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
172b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
173b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
174b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certFact = CertificateFactory.getInstance("X.509");
175b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
176b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
177b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (Exception e)
178b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
179b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IllegalArgumentException("can't create cert factory - " + e.toString());
180b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
181b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
182b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
183b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private SubjectKeyIdentifier createSubjectKeyId(
184b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        PublicKey   pubKey)
185b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
186b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
187b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
188b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
1894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                (ASN1Sequence) ASN1Primitive.fromByteArray(pubKey.getEncoded()));
190b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
191b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return new SubjectKeyIdentifier(info);
192b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
193b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (Exception e)
194b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
195b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new RuntimeException("error creating key");
196b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
197b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
198b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
199b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void setRandom(
200b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        SecureRandom    rand)
201b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
202b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.random = rand;
203b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
204b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
205b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public Enumeration engineAliases()
206b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
207b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Hashtable  tab = new Hashtable();
208b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
209b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Enumeration e = certs.keys();
210b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (e.hasMoreElements())
211b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
212b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            tab.put(e.nextElement(), "cert");
213b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
214b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
215b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        e = keys.keys();
216b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (e.hasMoreElements())
217b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
218b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            String  a = (String)e.nextElement();
219b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (tab.get(a) == null)
220b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
221b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                tab.put(a, "key");
222b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
223b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
224b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
225b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return tab.keys();
226b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
227b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
228b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public boolean engineContainsAlias(
229b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String  alias)
230b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
231b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return (certs.get(alias) != null || keys.get(alias) != null);
232b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
233b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
234b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
235c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * this is not quite complete - we should follow up on the chain, a bit
236b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * tricky if a certificate appears in more than one chain...
237b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
238b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void engineDeleteEntry(
239b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String  alias)
240b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws KeyStoreException
241b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
242b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Key k = (Key)keys.remove(alias);
243b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
244b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Certificate c = (Certificate)certs.remove(alias);
245b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
246b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (c != null)
247b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
248b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            chainCerts.remove(new CertId(c.getPublicKey()));
249b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
250b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
251b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (k != null)
252b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
253b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            String  id = (String)localIds.remove(alias);
254b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (id != null)
255b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
256b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                c = (Certificate)keyCerts.remove(id);
257b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
258b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (c != null)
259b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
260b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                chainCerts.remove(new CertId(c.getPublicKey()));
261b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
262b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
263b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
264b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
265b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
266b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * simply return the cert for the private key
267b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
268b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public Certificate engineGetCertificate(
269b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String alias)
270b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
271b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (alias == null)
272b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
273b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IllegalArgumentException("null alias passed to getCertificate.");
274b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
275b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
276b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Certificate c = (Certificate)certs.get(alias);
277b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
278b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
279b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // look up the key table - and try the local key id
280b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
281b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (c == null)
282b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
283b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            String  id = (String)localIds.get(alias);
284b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (id != null)
285b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
286b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                c = (Certificate)keyCerts.get(id);
287b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
288b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
289b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
290b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                c = (Certificate)keyCerts.get(alias);
291b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
292b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
293b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
294b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return c;
295b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
296b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
297b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public String engineGetCertificateAlias(
298b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Certificate cert)
299b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
300b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Enumeration c = certs.elements();
301b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Enumeration k = certs.keys();
302b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
303b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (c.hasMoreElements())
304b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
305b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            Certificate tc = (Certificate)c.nextElement();
306b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            String      ta = (String)k.nextElement();
307b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
308b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (tc.equals(cert))
309b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
310b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                return ta;
311b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
312b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
313b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
314b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = keyCerts.elements();
315b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        k = keyCerts.keys();
316b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
317b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (c.hasMoreElements())
318b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
319b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            Certificate tc = (Certificate)c.nextElement();
320b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            String      ta = (String)k.nextElement();
321b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
322b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (tc.equals(cert))
323b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
324b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                return ta;
325b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
326b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
327b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
328b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return null;
329b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
330b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
331b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public Certificate[] engineGetCertificateChain(
332b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String alias)
333b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
334b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (alias == null)
335b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
336b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IllegalArgumentException("null alias passed to getCertificateChain.");
337b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
338b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
339b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (!engineIsKeyEntry(alias))
340b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
341b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return null;
342b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
343b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
344b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Certificate c = engineGetCertificate(alias);
345b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
346b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (c != null)
347b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
348b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            Vector  cs = new Vector();
349b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
350b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            while (c != null)
351b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
352b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                X509Certificate     x509c = (X509Certificate)c;
353b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                Certificate         nextC = null;
354b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
35570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                byte[]  bytes = x509c.getExtensionValue(Extension.authorityKeyIdentifier.getId());
356b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (bytes != null)
357b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
358b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    try
359b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
360b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        ASN1InputStream         aIn = new ASN1InputStream(bytes);
361b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
362b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        byte[] authBytes = ((ASN1OctetString)aIn.readObject()).getOctets();
363b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        aIn = new ASN1InputStream(authBytes);
364b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
36570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                        AuthorityKeyIdentifier id = AuthorityKeyIdentifier.getInstance(aIn.readObject());
366b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        if (id.getKeyIdentifier() != null)
367b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
368b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            nextC = (Certificate)chainCerts.get(new CertId(id.getKeyIdentifier()));
369b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
370b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
371b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
372b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    catch (IOException e)
373b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
374b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        throw new RuntimeException(e.toString());
375b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
376b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
377b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
378b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (nextC == null)
379b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
380b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
381b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    // no authority key id, try the Issuer DN
382b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
383b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    Principal  i = x509c.getIssuerDN();
384b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    Principal  s = x509c.getSubjectDN();
385b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
386b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    if (!i.equals(s))
387b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
388b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        Enumeration e = chainCerts.keys();
389b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
390b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        while (e.hasMoreElements())
391b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
392b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            X509Certificate crt = (X509Certificate)chainCerts.get(e.nextElement());
393b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            Principal  sub = crt.getSubjectDN();
394b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            if (sub.equals(i))
395b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
396b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                try
397b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
398b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    x509c.verify(crt.getPublicKey());
399b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    nextC = crt;
400b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    break;
401b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
402b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                catch (Exception ex)
403b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
404b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    // continue
405b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
406b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
407b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
408b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
409b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
410b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
411b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                cs.addElement(c);
412b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (nextC != c)     // self signed - end of the chain
413b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
414b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    c = nextC;
415b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
416b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                else
417b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
418b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    c = null;
419b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
420b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
421b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
422b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            Certificate[]   certChain = new Certificate[cs.size()];
423b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
424b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            for (int i = 0; i != certChain.length; i++)
425b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
426b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certChain[i] = (Certificate)cs.elementAt(i);
427b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
428b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
429b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return certChain;
430b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
431b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
432b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return null;
433b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
434b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
435b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public Date engineGetCreationDate(String alias)
436b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
43770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        if (alias == null)
43870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        {
4398e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            throw new NullPointerException("alias == null");
4408e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
44170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        if (keys.get(alias) == null && certs.get(alias) == null)
44270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        {
4438e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            return null;
4448e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
445b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return new Date();
446b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
447b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
448b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public Key engineGetKey(
449b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String alias,
450b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        char[] password)
451b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws NoSuchAlgorithmException, UnrecoverableKeyException
452b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
453b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (alias == null)
454b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
455b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IllegalArgumentException("null alias passed to getKey.");
456b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
457b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
458b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return (Key)keys.get(alias);
459b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
460b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
461b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public boolean engineIsCertificateEntry(
462b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String alias)
463b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
464b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return (certs.get(alias) != null && keys.get(alias) == null);
465b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
466b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
467b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public boolean engineIsKeyEntry(
468b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String alias)
469b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
470b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return (keys.get(alias) != null);
471b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
472b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
473b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void engineSetCertificateEntry(
474b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String      alias,
475b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Certificate cert)
476b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws KeyStoreException
477b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
478c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (keys.get(alias) != null)
479b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
480c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            throw new KeyStoreException("There is a key entry with the name " + alias + ".");
481b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
482b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
483b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        certs.put(alias, cert);
484b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        chainCerts.put(new CertId(cert.getPublicKey()), cert);
485b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
486b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
487b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void engineSetKeyEntry(
488b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String alias,
489b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[] key,
490b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Certificate[] chain)
491b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws KeyStoreException
492b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
493b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throw new RuntimeException("operation not supported");
494b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
495b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
496b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void engineSetKeyEntry(
497b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String          alias,
498b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Key             key,
499b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        char[]          password,
500b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Certificate[]   chain)
501b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws KeyStoreException
502b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
50370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        if (!(key instanceof PrivateKey))
50470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        {
5058e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            throw new KeyStoreException("PKCS12 does not support non-PrivateKeys");
5068e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
50770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom
508b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if ((key instanceof PrivateKey) && (chain == null))
509b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
510b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new KeyStoreException("no certificate chain for private key");
511b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
512b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
513c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (keys.get(alias) != null)
514b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
515c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            engineDeleteEntry(alias);
516b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
517b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
518b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        keys.put(alias, key);
51970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        if (chain != null)
520b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
52170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom            certs.put(alias, chain[0]);
52270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom
52370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom            for (int i = 0; i != chain.length; i++)
52470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom            {
52570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                chainCerts.put(new CertId(chain[i].getPublicKey()), chain[i]);
52670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom            }
5278e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
528b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
529b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
530b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public int engineSize()
531b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
532b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Hashtable  tab = new Hashtable();
533b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
534b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Enumeration e = certs.keys();
535b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (e.hasMoreElements())
536b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
537b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            tab.put(e.nextElement(), "cert");
538b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
539b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
540b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        e = keys.keys();
541b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (e.hasMoreElements())
542b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
543b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            String  a = (String)e.nextElement();
544b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (tab.get(a) == null)
545b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
546b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                tab.put(a, "key");
547b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
548b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
549b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
550b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return tab.size();
551b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
552b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
553b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected PrivateKey unwrapKey(
554b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        AlgorithmIdentifier   algId,
555b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]                data,
556b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        char[]                password,
557b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        boolean               wrongPKCS12Zero)
558b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
559b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
5604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        String              algorithm = algId.getAlgorithm().getId();
5614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        PKCS12PBEParams     pbeParams = PKCS12PBEParams.getInstance(algId.getParameters());
562b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
563b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        PBEKeySpec          pbeSpec = new PBEKeySpec(password);
564c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        PrivateKey          out;
565b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
566b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
567b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
568b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            SecretKeyFactory    keyFact = SecretKeyFactory.getInstance(
569c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                                algorithm, bcProvider);
570b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            PBEParameterSpec    defParams = new PBEParameterSpec(
571b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                                pbeParams.getIV(),
572b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                                pbeParams.getIterations().intValue());
573b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
574b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            SecretKey           k = keyFact.generateSecret(pbeSpec);
575b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
5764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ((BCPBEKey)k).setTryWrongPKCS12Zero(wrongPKCS12Zero);
577b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
578c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            Cipher cipher = Cipher.getInstance(algorithm, bcProvider);
579b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
580b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            cipher.init(Cipher.UNWRAP_MODE, k, defParams);
581b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
582b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            // we pass "" as the key algorithm type as it is unknown at this point
583b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            out = (PrivateKey)cipher.unwrap(data, "", Cipher.PRIVATE_KEY);
584b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
585b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (Exception e)
586b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
587b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IOException("exception unwrapping private key - " + e.toString());
588b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
589b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
590b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return out;
591b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
592b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
593b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected byte[] wrapKey(
594b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String                  algorithm,
595b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Key                     key,
596b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        PKCS12PBEParams         pbeParams,
597b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        char[]                  password)
598b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
599b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
600b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        PBEKeySpec          pbeSpec = new PBEKeySpec(password);
601b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]              out;
602b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
603b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
604b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
605b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            SecretKeyFactory    keyFact = SecretKeyFactory.getInstance(
606c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                                algorithm, bcProvider);
607b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            PBEParameterSpec    defParams = new PBEParameterSpec(
608b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                                pbeParams.getIV(),
609b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                                pbeParams.getIterations().intValue());
610b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
611c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            Cipher cipher = Cipher.getInstance(algorithm, bcProvider);
612b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
613b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            cipher.init(Cipher.WRAP_MODE, keyFact.generateSecret(pbeSpec), defParams);
614b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
615b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            out = cipher.wrap(key);
616b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
617b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (Exception e)
618b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
619b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IOException("exception encrypting data - " + e.toString());
620b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
621b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
622b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return out;
623b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
624b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
625c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    protected byte[] cryptData(
626c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        boolean               forEncryption,
627b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        AlgorithmIdentifier   algId,
628b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        char[]                password,
629c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        boolean               wrongPKCS12Zero,
630c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        byte[]                data)
631b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
632b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
6334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        String          algorithm = algId.getAlgorithm().getId();
6344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters());
635c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        PBEKeySpec      pbeSpec = new PBEKeySpec(password);
636b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
637b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
638b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
639c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm, bcProvider);
640c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            PBEParameterSpec defParams = new PBEParameterSpec(
641c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                pbeParams.getIV(),
642c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                pbeParams.getIterations().intValue());
6434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            BCPBEKey key = (BCPBEKey) keyFact.generateSecret(pbeSpec);
644c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
645c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            key.setTryWrongPKCS12Zero(wrongPKCS12Zero);
646c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
647c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            Cipher cipher = Cipher.getInstance(algorithm, bcProvider);
648c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
649c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            cipher.init(mode, key, defParams);
650c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return cipher.doFinal(data);
651b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
652b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (Exception e)
653b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
654b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IOException("exception decrypting data - " + e.toString());
655b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
656b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
657b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
658b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void engineLoad(
659b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        InputStream stream,
660b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        char[]      password)
661b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
662b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
663b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (stream == null)     // just initialising
664b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
665b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return;
666b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
667b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
668b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (password == null)
669b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
670b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new NullPointerException("No password supplied for PKCS#12 KeyStore.");
671b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
672b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
673b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        BufferedInputStream             bufIn = new BufferedInputStream(stream);
674b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
675b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bufIn.mark(10);
676b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
677b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int head = bufIn.read();
678b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
679b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (head != 0x30)
680b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
681b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IOException("stream does not represent a PKCS12 key store");
682b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
683b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
684b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bufIn.reset();
685b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
686b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        ASN1InputStream bIn = new ASN1InputStream(bufIn);
687b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        ASN1Sequence    obj = (ASN1Sequence)bIn.readObject();
6884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        Pfx             bag = Pfx.getInstance(obj);
689b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        ContentInfo     info = bag.getAuthSafe();
690b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Vector          chain = new Vector();
691b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        boolean         unmarkedKey = false;
692b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        boolean         wrongPKCS12Zero = false;
693b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
694b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (bag.getMacData() != null)           // check the mac code
695b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
696b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            MacData                     mData = bag.getMacData();
697b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            DigestInfo                  dInfo = mData.getMac();
698b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            AlgorithmIdentifier         algId = dInfo.getAlgorithmId();
699b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            byte[]                      salt = mData.getSalt();
700b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            int                         itCount = mData.getIterationCount().intValue();
701b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
702b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            byte[]  data = ((ASN1OctetString)info.getContent()).getOctets();
703b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
704b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            try
705b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
706c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                byte[] res = calculatePbeMac(algId.getObjectId(), salt, itCount, password, false, data);
707c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                byte[] dig = dInfo.getDigest();
708b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
709c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                if (!Arrays.constantTimeAreEqual(res, dig))
710b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
711c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    if (password.length > 0)
712b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
713c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        throw new IOException("PKCS12 key store mac invalid - wrong password or corrupted file.");
714b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
715c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
716c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    // Try with incorrect zero length password
717c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    res = calculatePbeMac(algId.getObjectId(), salt, itCount, password, true, data);
718c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
719c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    if (!Arrays.constantTimeAreEqual(res, dig))
720b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
721c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        throw new IOException("PKCS12 key store mac invalid - wrong password or corrupted file.");
722b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
723c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
724b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    wrongPKCS12Zero = true;
725b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
726b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
727b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (IOException e)
728b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
729b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw e;
730b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
731b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (Exception e)
732b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
733b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new IOException("error constructing MAC: " + e.toString());
734b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
735b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
736b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
737c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        keys = new IgnoresCaseHashtable();
738b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        localIds = new Hashtable();
739b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
740b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (info.getContentType().equals(data))
741b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
742b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            bIn = new ASN1InputStream(((ASN1OctetString)info.getContent()).getOctets());
743b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
7444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            AuthenticatedSafe   authSafe = AuthenticatedSafe.getInstance(bIn.readObject());
745b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            ContentInfo[]       c = authSafe.getContentInfo();
746b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
747b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            for (int i = 0; i != c.length; i++)
748b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
749b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (c[i].getContentType().equals(data))
750b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
751b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    ASN1InputStream dIn = new ASN1InputStream(((ASN1OctetString)c[i].getContent()).getOctets());
752b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    ASN1Sequence    seq = (ASN1Sequence)dIn.readObject();
753b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
754b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    for (int j = 0; j != seq.size(); j++)
755b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
7564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        SafeBag b = SafeBag.getInstance(seq.getObjectAt(j));
757b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        if (b.getBagId().equals(pkcs8ShroudedKeyBag))
758b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
7594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                            org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo eIn = org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo.getInstance(b.getBagValue());
760b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            PrivateKey              privKey = unwrapKey(eIn.getEncryptionAlgorithm(), eIn.getEncryptedData(), password, wrongPKCS12Zero);
761b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
762b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            //
763b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            // set the attributes on the key
764b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            //
765b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            PKCS12BagAttributeCarrier   bagAttr = (PKCS12BagAttributeCarrier)privKey;
766b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            String                                   alias = null;
767b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            ASN1OctetString                   localId = null;
768b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
769b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            if (b.getBagAttributes() != null)
770b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
771b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                Enumeration e = b.getBagAttributes().getObjects();
772b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                while (e.hasMoreElements())
773b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
774b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    ASN1Sequence  sq = (ASN1Sequence)e.nextElement();
7754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    ASN1ObjectIdentifier     aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0);
776b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    ASN1Set                 attrSet = (ASN1Set)sq.getObjectAt(1);
7774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    ASN1Primitive               attr = null;
778b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
779b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    if (attrSet.size() > 0)
780b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    {
7814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        attr = (ASN1Primitive)attrSet.getObjectAt(0);
782c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
7834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        ASN1Encodable existing = bagAttr.getBagAttribute(aOid);
784c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        if (existing != null)
785c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        {
786c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                            // OK, but the value has to be the same
7874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                            if (!existing.toASN1Primitive().equals(attr))
788c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                            {
789c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                                throw new IOException(
790c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                                    "attempt to add existing attribute with different value");
791c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                            }
792c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        }
793c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        else
794c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        {
795c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                            bagAttr.setBagAttribute(aOid, attr);
796c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        }
797b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    }
798b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
799b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    if (aOid.equals(pkcs_9_at_friendlyName))
800b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    {
801b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                        alias = ((DERBMPString)attr).getString();
802b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                        keys.put(alias, privKey);
803b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    }
804b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    else if (aOid.equals(pkcs_9_at_localKeyId))
805b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    {
806b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                        localId = (ASN1OctetString)attr;
807b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    }
808b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
809b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
810b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
811b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            if (localId != null)
812b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
813b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                String name = new String(Hex.encode(localId.getOctets()));
814b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
815b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                if (alias == null)
816b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
817b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    keys.put(name, privKey);
818b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
819b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                else
820b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
821b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    localIds.put(alias, name);
822b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
823b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                             }
824b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                             else
825b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                             {
826b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                 unmarkedKey = true;
827b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                 keys.put("unmarked", privKey);
828b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                             }
829b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
830b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        else if (b.getBagId().equals(certBag))
831b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
832b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            chain.addElement(b);
833b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
834b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        else
835b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
836b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            System.out.println("extra in data " + b.getBagId());
837b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            System.out.println(ASN1Dump.dumpAsString(b));
838b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
839b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
840b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
841b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                else if (c[i].getContentType().equals(encryptedData))
842b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
8434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    EncryptedData d = EncryptedData.getInstance(c[i].getContent());
844c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    byte[] octets = cryptData(false, d.getEncryptionAlgorithm(),
845c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        password, wrongPKCS12Zero, d.getContent().getOctets());
8464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    ASN1Sequence seq = (ASN1Sequence) ASN1Primitive.fromByteArray(octets);
847b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
848b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    for (int j = 0; j != seq.size(); j++)
849b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
8504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        SafeBag b = SafeBag.getInstance(seq.getObjectAt(j));
851b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
852b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        if (b.getBagId().equals(certBag))
853b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
854b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            chain.addElement(b);
855b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
856b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        else if (b.getBagId().equals(pkcs8ShroudedKeyBag))
857b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
8584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                            org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo eIn = org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo.getInstance(b.getBagValue());
859b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            PrivateKey              privKey = unwrapKey(eIn.getEncryptionAlgorithm(), eIn.getEncryptedData(), password, wrongPKCS12Zero);
860b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
861b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            //
862b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            // set the attributes on the key
863b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            //
864b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            PKCS12BagAttributeCarrier   bagAttr = (PKCS12BagAttributeCarrier)privKey;
865b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            String                      alias = null;
866b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            ASN1OctetString              localId = null;
867b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
868b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            Enumeration e = b.getBagAttributes().getObjects();
869b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            while (e.hasMoreElements())
870b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
871b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                ASN1Sequence  sq = (ASN1Sequence)e.nextElement();
8724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                ASN1ObjectIdentifier     aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0);
873b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                ASN1Set                 attrSet= (ASN1Set)sq.getObjectAt(1);
8744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                ASN1Primitive               attr = null;
875b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
876b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                if (attrSet.size() > 0)
877b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
8784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    attr = (ASN1Primitive)attrSet.getObjectAt(0);
879b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
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                                }
895b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
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
907b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            String name = new String(Hex.encode(localId.getOctets()));
908b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
909b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            if (alias == null)
910b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
911b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                keys.put(name, privKey);
912b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
913b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            else
914b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
915b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                localIds.put(alias, name);
916b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
917b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
918b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        else if (b.getBagId().equals(keyBag))
919b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
9204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                            org.bouncycastle.asn1.pkcs.PrivateKeyInfo kInfo = new org.bouncycastle.asn1.pkcs.PrivateKeyInfo((ASN1Sequence)b.getBagValue());
9214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                            PrivateKey     privKey = BouncyCastleProvider.getPrivateKey(kInfo);
922b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
923b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            //
924b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            // set the attributes on the key
925b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            //
926b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            PKCS12BagAttributeCarrier   bagAttr = (PKCS12BagAttributeCarrier)privKey;
927b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            String                      alias = null;
928b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            ASN1OctetString             localId = null;
929b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
930b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            Enumeration e = b.getBagAttributes().getObjects();
931b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            while (e.hasMoreElements())
932b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
933b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                ASN1Sequence  sq = (ASN1Sequence)e.nextElement();
9344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                ASN1ObjectIdentifier     aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0);
935b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                ASN1Set                 attrSet = (ASN1Set)sq.getObjectAt(1);
9364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                ASN1Primitive   attr = null;
937b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
938b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                if (attrSet.size() > 0)
939b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
9404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    attr = (ASN1Primitive)attrSet.getObjectAt(0);
941b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
9424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    ASN1Encodable existing = bagAttr.getBagAttribute(aOid);
943c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    if (existing != null)
944c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    {
945c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        // OK, but the value has to be the same
9464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        if (!existing.toASN1Primitive().equals(attr))
947c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        {
948c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                            throw new IOException(
949c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                                "attempt to add existing attribute with different value");
950c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        }
951c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    }
952c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    else
953c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    {
954c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        bagAttr.setBagAttribute(aOid, attr);
955c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    }
956b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
957b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
958b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                if (aOid.equals(pkcs_9_at_friendlyName))
959b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
960b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    alias = ((DERBMPString)attr).getString();
961b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    keys.put(alias, privKey);
962b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
963b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                else if (aOid.equals(pkcs_9_at_localKeyId))
964b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                {
965b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    localId = (ASN1OctetString)attr;
966b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                }
967b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
968b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
969b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            String name = new String(Hex.encode(localId.getOctets()));
970b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
971b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            if (alias == null)
972b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
973b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                keys.put(name, privKey);
974b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
975b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            else
976b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            {
977b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                localIds.put(alias, name);
978b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            }
979b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
980b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        else
981b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        {
982b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            System.out.println("extra in encryptedData " + b.getBagId());
983b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                            System.out.println(ASN1Dump.dumpAsString(b));
984b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        }
985b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
986b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
987b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                else
988b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
989b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    System.out.println("extra " + c[i].getContentType().getId());
990b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    System.out.println("extra " + ASN1Dump.dumpAsString(c[i].getContent()));
991b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
992b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
993b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
994b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
995c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        certs = new IgnoresCaseHashtable();
996b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        chainCerts = new Hashtable();
997b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        keyCerts = new Hashtable();
998b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
999b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        for (int i = 0; i != chain.size(); i++)
1000b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1001b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            SafeBag     b = (SafeBag)chain.elementAt(i);
10024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            CertBag     cb = CertBag.getInstance(b.getBagValue());
1003c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1004c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (!cb.getCertId().equals(x509Certificate))
1005c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
1006c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                throw new RuntimeException("Unsupported certificate type: " + cb.getCertId());
1007c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
1008c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1009c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            Certificate cert;
1010b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1011b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            try
1012b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1013b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                ByteArrayInputStream  cIn = new ByteArrayInputStream(
1014b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                ((ASN1OctetString)cb.getCertValue()).getOctets());
1015b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                cert = certFact.generateCertificate(cIn);
1016b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1017b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (Exception e)
1018b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1019b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new RuntimeException(e.toString());
1020b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1021b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1022b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            //
1023b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            // set the attributes
1024b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            //
1025c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            ASN1OctetString localId = null;
1026c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            String          alias = null;
1027b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1028b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (b.getBagAttributes() != null)
1029b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1030b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                Enumeration e = b.getBagAttributes().getObjects();
1031b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                while (e.hasMoreElements())
1032b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1033b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    ASN1Sequence  sq = (ASN1Sequence)e.nextElement();
10344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    ASN1ObjectIdentifier     oid = (ASN1ObjectIdentifier)sq.getObjectAt(0);
10354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    ASN1Primitive               attr = (ASN1Primitive)((ASN1Set)sq.getObjectAt(1)).getObjectAt(0);
1036c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    PKCS12BagAttributeCarrier   bagAttr = null;
1037b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1038b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    if (cert instanceof PKCS12BagAttributeCarrier)
1039b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
1040c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        bagAttr = (PKCS12BagAttributeCarrier)cert;
1041c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
10424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        ASN1Encodable existing = bagAttr.getBagAttribute(oid);
1043c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        if (existing != null)
1044c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        {
1045c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                            // OK, but the value has to be the same
10464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                            if (!existing.toASN1Primitive().equals(attr))
1047c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                            {
1048c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                throw new IOException(
1049c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                    "attempt to add existing attribute with different value");
1050c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                            }
1051c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        }
1052c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        else
1053c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        {
1054c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                            bagAttr.setBagAttribute(oid, attr);
1055c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        }
1056b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1057b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1058b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    if (oid.equals(pkcs_9_at_friendlyName))
1059b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
1060b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        alias = ((DERBMPString)attr).getString();
1061b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1062b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    else if (oid.equals(pkcs_9_at_localKeyId))
1063b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
1064b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        localId = (ASN1OctetString)attr;
1065b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1066b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1067b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1068b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1069b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            chainCerts.put(new CertId(cert.getPublicKey()), cert);
1070b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1071b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (unmarkedKey)
1072b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1073b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (keyCerts.isEmpty())
1074b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1075b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    String    name = new String(Hex.encode(createSubjectKeyId(cert.getPublicKey()).getKeyIdentifier()));
1076b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1077b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    keyCerts.put(name, cert);
1078b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    keys.put(name, keys.remove("unmarked"));
1079b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1080b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1081b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
1082b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1083b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1084b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                // the local key id needs to override the friendly name
1085b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1086b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (localId != null)
1087b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1088b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    String name = new String(Hex.encode(localId.getOctets()));
1089b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1090b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    keyCerts.put(name, cert);
1091b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1092b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (alias != null)
1093b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1094b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    certs.put(alias, cert);
1095b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1096b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1097b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1098b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
1099b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
11006e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    public void engineStore(LoadStoreParameter param) throws IOException,
11016e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            NoSuchAlgorithmException, CertificateException
11026e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
11036e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (param == null)
11046e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
11056e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            throw new IllegalArgumentException("'param' arg cannot be null");
11066e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
11076e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
11086e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (!(param instanceof JDKPKCS12StoreParameter))
11096e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
11106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            throw new IllegalArgumentException(
11116e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                "No support for 'param' of type " + param.getClass().getName());
11126e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
11136e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
11146e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        JDKPKCS12StoreParameter bcParam = (JDKPKCS12StoreParameter)param;
11156e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
11166e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        char[] password;
11176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        ProtectionParameter protParam = param.getProtectionParameter();
11186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (protParam == null)
11196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
11206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            password = null;
11216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
11226e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else if (protParam instanceof KeyStore.PasswordProtection)
11236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
11246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            password = ((KeyStore.PasswordProtection)protParam).getPassword();
11256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
11266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else
11276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
11286e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            throw new IllegalArgumentException(
11296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                "No support for protection parameter of type " + protParam.getClass().getName());
11306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
11316e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
11326e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        doStore(bcParam.getOutputStream(), password, bcParam.isUseDEREncoding());
11336e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
11346e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void engineStore(OutputStream stream, char[] password)
1136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
1137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
11386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        doStore(stream, password, false);
11396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
11406e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
11416e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    private void doStore(OutputStream stream, char[] password, boolean useDEREncoding)
11426e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        throws IOException
11436e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
1144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (password == null)
1145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new NullPointerException("No password supplied for PKCS#12 KeyStore.");
1147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // handle the key
1151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        ASN1EncodableVector  keyS = new ASN1EncodableVector();
1153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Enumeration ks = keys.keys();
1156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (ks.hasMoreElements())
1158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            byte[]                  kSalt = new byte[SALT_SIZE];
1160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            random.nextBytes(kSalt);
1162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            String                  name = (String)ks.nextElement();
1164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            PrivateKey              privKey = (PrivateKey)keys.get(name);
1165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            PKCS12PBEParams         kParams = new PKCS12PBEParams(kSalt, MIN_ITERATIONS);
1166c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            byte[]                  kBytes = wrapKey(keyAlgorithm.getId(), privKey, kParams, password);
11674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            AlgorithmIdentifier     kAlgId = new AlgorithmIdentifier(keyAlgorithm, kParams.toASN1Primitive());
1168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo kInfo = new org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo(kAlgId, kBytes);
1169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            boolean                 attrSet = false;
1170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            ASN1EncodableVector     kName = new ASN1EncodableVector();
1171b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1172b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (privKey instanceof PKCS12BagAttributeCarrier)
1173b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1174b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                PKCS12BagAttributeCarrier   bagAttrs = (PKCS12BagAttributeCarrier)privKey;
1175b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1176b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                // make sure we are using the local alias on store
1177b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1178b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                DERBMPString    nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName);
1179b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (nm == null || !nm.getString().equals(name))
1180b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1181b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(name));
1182b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1183b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1184b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1185b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                // make sure we have a local key-id
1186b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1187b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (bagAttrs.getBagAttribute(pkcs_9_at_localKeyId) == null)
1188b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1189b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    Certificate             ct = engineGetCertificate(name);
1190b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1191b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    bagAttrs.setBagAttribute(pkcs_9_at_localKeyId, createSubjectKeyId(ct.getPublicKey()));
1192b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1193b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1194b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                Enumeration e = bagAttrs.getBagAttributeKeys();
1195b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1196b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                while (e.hasMoreElements())
1197b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
11984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
1199b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    ASN1EncodableVector  kSeq = new ASN1EncodableVector();
1200b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1201b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    kSeq.add(oid);
1202b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    kSeq.add(new DERSet(bagAttrs.getBagAttribute(oid)));
1203b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1204b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    attrSet = true;
1205b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1206b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    kName.add(new DERSequence(kSeq));
1207b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1208b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1209b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1210b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (!attrSet)
1211b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1212b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1213b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                // set a default friendly name (from the key id) and local id
1214b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
1215b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                ASN1EncodableVector     kSeq = new ASN1EncodableVector();
1216b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                Certificate             ct = engineGetCertificate(name);
1217b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1218b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                kSeq.add(pkcs_9_at_localKeyId);
1219b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                kSeq.add(new DERSet(createSubjectKeyId(ct.getPublicKey())));
1220b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1221b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                kName.add(new DERSequence(kSeq));
1222b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1223b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                kSeq = new ASN1EncodableVector();
1224b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1225b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                kSeq.add(pkcs_9_at_friendlyName);
1226b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                kSeq.add(new DERSet(new DERBMPString(name)));
1227b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1228b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                kName.add(new DERSequence(kSeq));
1229b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1230b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
12314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            SafeBag                 kBag = new SafeBag(pkcs8ShroudedKeyBag, kInfo.toASN1Primitive(), new DERSet(kName));
1232b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            keyS.add(kBag);
1233b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1234b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
12354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]                    keySEncoded = new DERSequence(keyS).getEncoded(ASN1Encoding.DER);
123670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        BEROctetString keyString = new BEROctetString(keySEncoded);
1237b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1238b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1239c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        // certificate processing
1240b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1241b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]                  cSalt = new byte[SALT_SIZE];
1242b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1243b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        random.nextBytes(cSalt);
1244b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1245b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        ASN1EncodableVector  certSeq = new ASN1EncodableVector();
1246b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        PKCS12PBEParams         cParams = new PKCS12PBEParams(cSalt, MIN_ITERATIONS);
12474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        AlgorithmIdentifier     cAlgId = new AlgorithmIdentifier(certAlgorithm, cParams.toASN1Primitive());
1248b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Hashtable               doneCerts = new Hashtable();
1249b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1250b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Enumeration cs = keys.keys();
1251b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (cs.hasMoreElements())
1252b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1253b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            try
1254b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1255b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                String              name = (String)cs.nextElement();
1256b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                Certificate         cert = engineGetCertificate(name);
1257b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                boolean             cAttrSet = false;
1258b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                CertBag             cBag = new CertBag(
1259c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        x509Certificate,
1260b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                        new DEROctetString(cert.getEncoded()));
1261b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                ASN1EncodableVector fName = new ASN1EncodableVector();
1262b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1263b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (cert instanceof PKCS12BagAttributeCarrier)
1264b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1265b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    PKCS12BagAttributeCarrier   bagAttrs = (PKCS12BagAttributeCarrier)cert;
1266b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
1267b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    // make sure we are using the local alias on store
1268b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
1269b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    DERBMPString    nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName);
1270b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    if (nm == null || !nm.getString().equals(name))
1271b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
1272b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(name));
1273b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1274b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1275b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
1276b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    // make sure we have a local key-id
1277b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
1278b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    if (bagAttrs.getBagAttribute(pkcs_9_at_localKeyId) == null)
1279b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
1280b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        bagAttrs.setBagAttribute(pkcs_9_at_localKeyId, createSubjectKeyId(cert.getPublicKey()));
1281b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1282b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1283b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    Enumeration e = bagAttrs.getBagAttributeKeys();
1284b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1285b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    while (e.hasMoreElements())
1286b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
12874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
1288b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        ASN1EncodableVector fSeq = new ASN1EncodableVector();
1289b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1290b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fSeq.add(oid);
1291b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid)));
1292b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fName.add(new DERSequence(fSeq));
1293b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1294b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        cAttrSet = true;
1295b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1296b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1297b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1298b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (!cAttrSet)
1299b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1300b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    ASN1EncodableVector  fSeq = new ASN1EncodableVector();
1301b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1302b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fSeq.add(pkcs_9_at_localKeyId);
1303b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fSeq.add(new DERSet(createSubjectKeyId(cert.getPublicKey())));
1304b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fName.add(new DERSequence(fSeq));
1305b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1306b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fSeq = new ASN1EncodableVector();
1307b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1308b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fSeq.add(pkcs_9_at_friendlyName);
1309b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fSeq.add(new DERSet(new DERBMPString(name)));
1310b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1311b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fName.add(new DERSequence(fSeq));
1312b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1313b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
13144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                SafeBag sBag = new SafeBag(certBag, cBag.toASN1Primitive(), new DERSet(fName));
1315b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1316b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certSeq.add(sBag);
1317b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1318b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                doneCerts.put(cert, cert);
1319b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1320b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (CertificateEncodingException e)
1321b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1322b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new IOException("Error encoding certificate: " + e.toString());
1323b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1324b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1325b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1326b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        cs = certs.keys();
1327b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (cs.hasMoreElements())
1328b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1329b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            try
1330b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1331b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                String              certId = (String)cs.nextElement();
1332b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                Certificate         cert = (Certificate)certs.get(certId);
1333b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                boolean             cAttrSet = false;
1334b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1335b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (keys.get(certId) != null)
1336b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1337b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    continue;
1338b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1339b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1340b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                CertBag             cBag = new CertBag(
1341c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        x509Certificate,
1342b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                        new DEROctetString(cert.getEncoded()));
1343b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                ASN1EncodableVector fName = new ASN1EncodableVector();
1344b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1345b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (cert instanceof PKCS12BagAttributeCarrier)
1346b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1347b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    PKCS12BagAttributeCarrier   bagAttrs = (PKCS12BagAttributeCarrier)cert;
1348b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
1349b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    // make sure we are using the local alias on store
1350b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    //
1351b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    DERBMPString    nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName);
1352b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    if (nm == null || !nm.getString().equals(certId))
1353b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
1354b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(certId));
1355b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1356b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1357b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    Enumeration e = bagAttrs.getBagAttributeKeys();
1358b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1359b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    while (e.hasMoreElements())
1360b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
13614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
1362c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1363c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        // a certificate not immediately linked to a key doesn't require
1364c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        // a localKeyID and will confuse some PKCS12 implementations.
1365c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        //
1366c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        // If we find one, we'll prune it out.
1367c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        if (oid.equals(PKCSObjectIdentifiers.pkcs_9_at_localKeyId))
1368c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        {
1369c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                            continue;
1370c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        }
1371c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1372b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        ASN1EncodableVector fSeq = new ASN1EncodableVector();
1373b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1374b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fSeq.add(oid);
1375b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid)));
1376b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fName.add(new DERSequence(fSeq));
1377b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1378b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        cAttrSet = true;
1379b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1380b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1381b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1382b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (!cAttrSet)
1383b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1384b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    ASN1EncodableVector  fSeq = new ASN1EncodableVector();
1385b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1386b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fSeq.add(pkcs_9_at_friendlyName);
1387b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fSeq.add(new DERSet(new DERBMPString(certId)));
1388b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1389b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    fName.add(new DERSequence(fSeq));
1390b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1391b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
13924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                SafeBag sBag = new SafeBag(certBag, cBag.toASN1Primitive(), new DERSet(fName));
1393b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1394b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certSeq.add(sBag);
1395b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1396b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                doneCerts.put(cert, cert);
1397b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1398b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (CertificateEncodingException e)
1399b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1400b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new IOException("Error encoding certificate: " + e.toString());
1401b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1402b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1403b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1404b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        cs = chainCerts.keys();
1405b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (cs.hasMoreElements())
1406b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1407b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            try
1408b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1409b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                CertId              certId = (CertId)cs.nextElement();
1410b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                Certificate         cert = (Certificate)chainCerts.get(certId);
1411b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1412b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (doneCerts.get(cert) != null)
1413b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1414b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    continue;
1415b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1416b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1417b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                CertBag             cBag = new CertBag(
1418c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        x509Certificate,
1419b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                        new DEROctetString(cert.getEncoded()));
1420b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                ASN1EncodableVector fName = new ASN1EncodableVector();
1421b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1422b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (cert instanceof PKCS12BagAttributeCarrier)
1423b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1424b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    PKCS12BagAttributeCarrier   bagAttrs = (PKCS12BagAttributeCarrier)cert;
1425b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    Enumeration e = bagAttrs.getBagAttributeKeys();
1426b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1427b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    while (e.hasMoreElements())
1428b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
14294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
1430c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1431c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        // a certificate not immediately linked to a key doesn't require
1432c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        // a localKeyID and will confuse some PKCS12 implementations.
1433c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        //
1434c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        // If we find one, we'll prune it out.
1435c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        if (oid.equals(PKCSObjectIdentifiers.pkcs_9_at_localKeyId))
1436c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        {
1437c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                            continue;
1438c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        }
1439c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1440b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        ASN1EncodableVector fSeq = new ASN1EncodableVector();
1441b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1442b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fSeq.add(oid);
1443b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid)));
1444b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        fName.add(new DERSequence(fSeq));
1445b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
1446b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1447b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
14484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                SafeBag sBag = new SafeBag(certBag, cBag.toASN1Primitive(), new DERSet(fName));
1449b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1450b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certSeq.add(sBag);
1451b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1452b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (CertificateEncodingException e)
1453b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
1454b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new IOException("Error encoding certificate: " + e.toString());
1455b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
1456b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1457b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
14584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]          certSeqEncoded = new DERSequence(certSeq).getEncoded(ASN1Encoding.DER);
1459c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        byte[]          certBytes = cryptData(true, cAlgId, password, false, certSeqEncoded);
146070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        EncryptedData   cInfo = new EncryptedData(data, cAlgId, new BEROctetString(certBytes));
1461b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1462c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        ContentInfo[] info = new ContentInfo[]
1463c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
1464c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            new ContentInfo(data, keyString),
14654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            new ContentInfo(encryptedData, cInfo.toASN1Primitive())
1466c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        };
1467b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1468c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        AuthenticatedSafe   auth = new AuthenticatedSafe(info);
1469b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1470c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
14716e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        DEROutputStream asn1Out;
14726e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (useDEREncoding)
14736e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
14746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            asn1Out = new DEROutputStream(bOut);
14756e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
14766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else
14776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
14786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            asn1Out = new BEROutputStream(bOut);
14796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
1480b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
14816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        asn1Out.writeObject(auth);
1482b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1483b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]              pkg = bOut.toByteArray();
1484b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
148570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        ContentInfo         mainInfo = new ContentInfo(data, new BEROctetString(pkg));
1486b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1487b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1488b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // create the mac
1489b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1490b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]                      mSalt = new byte[20];
1491b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int                         itCount = MIN_ITERATIONS;
1492b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1493b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        random.nextBytes(mSalt);
1494b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1495b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  data = ((ASN1OctetString)mainInfo.getContent()).getOctets();
1496b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1497c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        MacData                 mData;
1498b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1499b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
1500b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1501c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            byte[] res = calculatePbeMac(id_SHA1, mSalt, itCount, password, false, data);
1502b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1503c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            AlgorithmIdentifier     algId = new AlgorithmIdentifier(id_SHA1, DERNull.INSTANCE);
1504b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            DigestInfo              dInfo = new DigestInfo(algId, res);
1505b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1506b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            mData = new MacData(dInfo, mSalt, itCount);
1507b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1508b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (Exception e)
1509b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1510b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IOException("error constructing MAC: " + e.toString());
1511b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1512b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1513b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1514b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // output the Pfx
1515b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
1516b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Pfx                 pfx = new Pfx(mainInfo, mData);
1517b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
15186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (useDEREncoding)
15196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
15206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            asn1Out = new DEROutputStream(stream);
15216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
15226e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else
15236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
15246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            asn1Out = new BEROutputStream(stream);
15256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
1526b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
15276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        asn1Out.writeObject(pfx);
1528b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
1529b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1530c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static byte[] calculatePbeMac(
15314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1ObjectIdentifier oid,
1532c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        byte[]              salt,
1533c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        int                 itCount,
1534c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        char[]              password,
1535c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        boolean             wrongPkcs12Zero,
1536c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        byte[]              data)
1537c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        throws Exception
1538c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
1539c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        SecretKeyFactory    keyFact = SecretKeyFactory.getInstance(oid.getId(), bcProvider);
1540c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        PBEParameterSpec    defParams = new PBEParameterSpec(salt, itCount);
1541c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        PBEKeySpec          pbeSpec = new PBEKeySpec(password);
15424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        BCPBEKey key = (BCPBEKey) keyFact.generateSecret(pbeSpec);
1543c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        key.setTryWrongPKCS12Zero(wrongPkcs12Zero);
1544c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1545c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        Mac mac = Mac.getInstance(oid.getId(), bcProvider);
1546c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        mac.init(key, defParams);
1547c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        mac.update(data);
1548c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return mac.doFinal();
1549c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
1550c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1551b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public static class BCPKCS12KeyStore
1552b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        extends JDKPKCS12KeyStore
1553b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
1554b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        public BCPKCS12KeyStore()
1555b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
15564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            super(bcProvider, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC);
1557b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1558b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
1559b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1560c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // BEGIN android-removed
1561c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // public static class BCPKCS12KeyStore3DES
1562c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //     extends JDKPKCS12KeyStore
1563c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // {
1564c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //     public BCPKCS12KeyStore3DES()
1565c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //     {
1566c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //         super(bcProvider, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC);
1567c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //     }
1568c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // }
15697a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    //
15707a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    // public static class DefPKCS12KeyStore
15717a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    //     extends JDKPKCS12KeyStore
15727a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    // {
15737a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    //     public DefPKCS12KeyStore()
15747a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    //     {
15754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    //         super(null, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC);
15767a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    //     }
15777a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    // }
15787a6b43b187fb942402daa61e0b92496746f5bc1cBrian Carlstrom    //
1579c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // public static class DefPKCS12KeyStore3DES
1580c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //     extends JDKPKCS12KeyStore
1581c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // {
1582c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //     public DefPKCS12KeyStore3DES()
1583c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //     {
1584c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //         super(null, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC);
1585c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    //     }
1586c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // }
1587c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // END android-removed
1588c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1589c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static class IgnoresCaseHashtable
1590c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
1591c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        private Hashtable orig = new Hashtable();
1592c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        private Hashtable keys = new Hashtable();
1593c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1594c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        public void put(String key, Object value)
1595c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
15968e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            String lower = (key == null) ? null : Strings.toLowerCase(key);
1597c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            String k = (String)keys.get(lower);
1598c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (k != null)
1599c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
1600c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                orig.remove(k);
1601c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
1602c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1603c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            keys.put(lower, key);
1604c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            orig.put(key, value);
1605c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
1606c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1607c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        public Enumeration keys()
1608c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
1609c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return orig.keys();
1610c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
1611c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1612c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        public Object remove(String alias)
1613c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
16148e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            String k = (String)keys.remove(alias == null ? null : Strings.toLowerCase(alias));
1615c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (k == null)
1616c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
1617c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                return null;
1618c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
1619c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1620c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return orig.remove(k);
1621c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
1622c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1623c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        public Object get(String alias)
1624c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
16258e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            String k = (String)keys.get(alias == null ? null : Strings.toLowerCase(alias));
1626c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (k == null)
1627c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
1628c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                return null;
1629c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
1630c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1631c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return orig.get(k);
1632c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
1633c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1634c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        public Enumeration elements()
1635c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
1636c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return orig.elements();
1637b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1638b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
1639b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
1640