1package org.bouncycastle.cms;
2
3import java.util.ArrayList;
4import java.util.HashMap;
5import java.util.HashSet;
6import java.util.Iterator;
7import java.util.List;
8import java.util.Map;
9import java.util.Set;
10
11import org.bouncycastle.asn1.ASN1Encodable;
12import org.bouncycastle.asn1.ASN1ObjectIdentifier;
13import org.bouncycastle.asn1.DERTaggedObject;
14import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
15// BEGIN android-removed
16// import org.bouncycastle.asn1.cms.OtherRevocationInfoFormat;
17// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
18// END android-removed
19import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
20import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
21import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
22import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
23import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
24import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
25import org.bouncycastle.cert.X509AttributeCertificateHolder;
26import org.bouncycastle.cert.X509CRLHolder;
27import org.bouncycastle.cert.X509CertificateHolder;
28import org.bouncycastle.util.Arrays;
29import org.bouncycastle.util.Store;
30
31public class CMSSignedGenerator
32{
33    /**
34     * Default type for the signed data.
35     */
36    public static final String  DATA = CMSObjectIdentifiers.data.getId();
37
38    public static final String  DIGEST_SHA1 = OIWObjectIdentifiers.idSHA1.getId();
39    public static final String  DIGEST_SHA224 = NISTObjectIdentifiers.id_sha224.getId();
40    public static final String  DIGEST_SHA256 = NISTObjectIdentifiers.id_sha256.getId();
41    public static final String  DIGEST_SHA384 = NISTObjectIdentifiers.id_sha384.getId();
42    public static final String  DIGEST_SHA512 = NISTObjectIdentifiers.id_sha512.getId();
43    public static final String  DIGEST_MD5 = PKCSObjectIdentifiers.md5.getId();
44    // BEGIN android-removed
45    // public static final String  DIGEST_GOST3411 = CryptoProObjectIdentifiers.gostR3411.getId();
46    // public static final String  DIGEST_RIPEMD128 = TeleTrusTObjectIdentifiers.ripemd128.getId();
47    // public static final String  DIGEST_RIPEMD160 = TeleTrusTObjectIdentifiers.ripemd160.getId();
48    // public static final String  DIGEST_RIPEMD256 = TeleTrusTObjectIdentifiers.ripemd256.getId();
49    // END android-removed
50
51    public static final String  ENCRYPTION_RSA = PKCSObjectIdentifiers.rsaEncryption.getId();
52    public static final String  ENCRYPTION_DSA = X9ObjectIdentifiers.id_dsa_with_sha1.getId();
53    public static final String  ENCRYPTION_ECDSA = X9ObjectIdentifiers.ecdsa_with_SHA1.getId();
54    public static final String  ENCRYPTION_RSA_PSS = PKCSObjectIdentifiers.id_RSASSA_PSS.getId();
55    // BEGIN android-removed
56    // public static final String  ENCRYPTION_GOST3410 = CryptoProObjectIdentifiers.gostR3410_94.getId();
57    // public static final String  ENCRYPTION_ECGOST3410 = CryptoProObjectIdentifiers.gostR3410_2001.getId();
58    // END android-removed
59
60    private static final String  ENCRYPTION_ECDSA_WITH_SHA1 = X9ObjectIdentifiers.ecdsa_with_SHA1.getId();
61    private static final String  ENCRYPTION_ECDSA_WITH_SHA224 = X9ObjectIdentifiers.ecdsa_with_SHA224.getId();
62    private static final String  ENCRYPTION_ECDSA_WITH_SHA256 = X9ObjectIdentifiers.ecdsa_with_SHA256.getId();
63    private static final String  ENCRYPTION_ECDSA_WITH_SHA384 = X9ObjectIdentifiers.ecdsa_with_SHA384.getId();
64    private static final String  ENCRYPTION_ECDSA_WITH_SHA512 = X9ObjectIdentifiers.ecdsa_with_SHA512.getId();
65
66    private static final Set NO_PARAMS = new HashSet();
67    private static final Map EC_ALGORITHMS = new HashMap();
68
69    static
70    {
71        NO_PARAMS.add(ENCRYPTION_DSA);
72        NO_PARAMS.add(ENCRYPTION_ECDSA);
73        NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA1);
74        NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA224);
75        NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA256);
76        NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA384);
77        NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA512);
78
79        EC_ALGORITHMS.put(DIGEST_SHA1, ENCRYPTION_ECDSA_WITH_SHA1);
80        EC_ALGORITHMS.put(DIGEST_SHA224, ENCRYPTION_ECDSA_WITH_SHA224);
81        EC_ALGORITHMS.put(DIGEST_SHA256, ENCRYPTION_ECDSA_WITH_SHA256);
82        EC_ALGORITHMS.put(DIGEST_SHA384, ENCRYPTION_ECDSA_WITH_SHA384);
83        EC_ALGORITHMS.put(DIGEST_SHA512, ENCRYPTION_ECDSA_WITH_SHA512);
84    }
85
86    protected List certs = new ArrayList();
87    protected List crls = new ArrayList();
88    protected List _signers = new ArrayList();
89    protected List signerGens = new ArrayList();
90    protected Map digests = new HashMap();
91
92    /**
93     * base constructor
94     */
95    protected CMSSignedGenerator()
96    {
97    }
98
99    protected Map getBaseParameters(ASN1ObjectIdentifier contentType, AlgorithmIdentifier digAlgId, byte[] hash)
100    {
101        Map param = new HashMap();
102        param.put(CMSAttributeTableGenerator.CONTENT_TYPE, contentType);
103        param.put(CMSAttributeTableGenerator.DIGEST_ALGORITHM_IDENTIFIER, digAlgId);
104        param.put(CMSAttributeTableGenerator.DIGEST, Arrays.clone(hash));
105        return param;
106    }
107
108    /**
109     * Add a certificate to the certificate set to be included with the generated SignedData message.
110     *
111     * @param certificate the certificate to be included.
112     * @throws CMSException if the certificate cannot be encoded for adding.
113     */
114    public void addCertificate(
115        X509CertificateHolder certificate)
116        throws CMSException
117    {
118        certs.add(certificate.toASN1Structure());
119    }
120
121    /**
122     * Add the certificates in certStore to the certificate set to be included with the generated SignedData message.
123     *
124     * @param certStore the store containing the certificates to be included.
125     * @throws CMSException if the certificates cannot be encoded for adding.
126     */
127    public void addCertificates(
128        Store certStore)
129        throws CMSException
130    {
131        certs.addAll(CMSUtils.getCertificatesFromStore(certStore));
132    }
133
134    /**
135     * Add a CRL to the CRL set to be included with the generated SignedData message.
136     *
137     * @param crl the CRL to be included.
138     */
139    public void addCRL(X509CRLHolder crl)
140    {
141        crls.add(crl.toASN1Structure());
142    }
143
144    /**
145     * Add the CRLs in crlStore to the CRL set to be included with the generated SignedData message.
146     *
147     * @param crlStore the store containing the CRLs to be included.
148     * @throws CMSException if the CRLs cannot be encoded for adding.
149     */
150    public void addCRLs(
151        Store crlStore)
152        throws CMSException
153    {
154        crls.addAll(CMSUtils.getCRLsFromStore(crlStore));
155    }
156
157    /**
158     * Add the attribute certificates in attrStore to the certificate set to be included with the generated SignedData message.
159     *
160     * @param attrCert the store containing the certificates to be included.
161     * @throws CMSException if the attribute certificate cannot be encoded for adding.
162     */
163    public void addAttributeCertificate(
164        X509AttributeCertificateHolder attrCert)
165        throws CMSException
166    {
167        certs.add(new DERTaggedObject(false, 2, attrCert.toASN1Structure()));
168    }
169
170    /**
171     * Add the attribute certificates in attrStore to the certificate set to be included with the generated SignedData message.
172     *
173     * @param attrStore the store containing the certificates to be included.
174     * @throws CMSException if the attribute certificate cannot be encoded for adding.
175     */
176    public void addAttributeCertificates(
177        Store attrStore)
178        throws CMSException
179    {
180        certs.addAll(CMSUtils.getAttributeCertificatesFromStore(attrStore));
181    }
182
183    // BEGIN android-removed
184    // /**
185    //  * Add a single instance of otherRevocationData to the CRL set to be included with the generated SignedData message.
186    //  *
187    //  * @param otherRevocationInfoFormat the OID specifying the format of the otherRevocationInfo data.
188    //  * @param otherRevocationInfo the otherRevocationInfo ASN.1 structure.
189    //  */
190    // public void addOtherRevocationInfo(
191    //     ASN1ObjectIdentifier   otherRevocationInfoFormat,
192    //     ASN1Encodable          otherRevocationInfo)
193    // {
194    //     crls.add(new DERTaggedObject(false, 1, new OtherRevocationInfoFormat(otherRevocationInfoFormat, otherRevocationInfo)));
195    // }
196    //
197    // /**
198    //  * Add a Store of otherRevocationData to the CRL set to be included with the generated SignedData message.
199    //  *
200    //  * @param otherRevocationInfoFormat the OID specifying the format of the otherRevocationInfo data.
201    //  * @param otherRevocationInfos a Store of otherRevocationInfo data to add.
202    //  */
203    // public void addOtherRevocationInfo(
204    //     ASN1ObjectIdentifier   otherRevocationInfoFormat,
205    //     Store                  otherRevocationInfos)
206    // {
207    //     crls.addAll(CMSUtils.getOthersFromStore(otherRevocationInfoFormat, otherRevocationInfos));
208    // }
209    // END android-removed
210
211    /**
212     * Add a store of pre-calculated signers to the generator.
213     *
214     * @param signerStore store of signers
215     */
216    public void addSigners(
217        SignerInformationStore    signerStore)
218    {
219        Iterator    it = signerStore.getSigners().iterator();
220
221        while (it.hasNext())
222        {
223            _signers.add(it.next());
224        }
225    }
226
227    /**
228     * Add a generator for a particular signer to this CMS SignedData generator.
229     *
230     * @param infoGen the generator representing the particular signer.
231     */
232    public void addSignerInfoGenerator(SignerInfoGenerator infoGen)
233    {
234         signerGens.add(infoGen);
235    }
236
237    /**
238     * Return a map of oids and byte arrays representing the digests calculated on the content during
239     * the last generate.
240     *
241     * @return a map of oids (as String objects) and byte[] representing digests.
242     */
243    public Map getGeneratedDigests()
244    {
245        return new HashMap(digests);
246    }
247}
248