1e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrompackage org.bouncycastle.cms;
2e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
3e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.io.IOException;
4e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.io.OutputStream;
5e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.security.NoSuchAlgorithmException;
6e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.security.NoSuchProviderException;
7e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.security.Provider;
8e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.security.PublicKey;
9e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.security.cert.CertificateExpiredException;
10e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.security.cert.CertificateNotYetValidException;
11e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.security.cert.X509Certificate;
12e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.util.ArrayList;
13e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.util.Enumeration;
14e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.util.Iterator;
15e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.util.List;
16e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
17e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1Encodable;
18e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1EncodableVector;
19e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1Encoding;
20e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1ObjectIdentifier;
21e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1OctetString;
22e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1Primitive;
23e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1Set;
2470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstromimport org.bouncycastle.asn1.DERNull;
25e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.DERSet;
26e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.Attribute;
27e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.AttributeTable;
28e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.CMSAttributes;
29e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
30e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.SignerIdentifier;
31e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.SignerInfo;
32e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.Time;
33e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.x509.AlgorithmIdentifier;
34e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.x509.DigestInfo;
35e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.cert.X509CertificateHolder;
36e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.cms.jcajce.JcaSignerInfoVerifierBuilder;
37e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
38e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.operator.ContentVerifier;
39e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.operator.DigestCalculator;
40e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.operator.OperatorCreationException;
41e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.operator.RawContentVerifier;
42e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
43e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.util.Arrays;
4470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstromimport org.bouncycastle.util.io.TeeOutputStream;
45e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
46e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom/**
47e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * an expanded SignerInfo block from a CMS Signed message
48e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */
49e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrompublic class SignerInformation
50e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom{
51e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private SignerId                sid;
52e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private SignerInfo              info;
53e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private AlgorithmIdentifier     digestAlgorithm;
54e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private AlgorithmIdentifier     encryptionAlgorithm;
55e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private final ASN1Set           signedAttributeSet;
56e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private final ASN1Set           unsignedAttributeSet;
57e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private CMSProcessable          content;
58e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private byte[]                  signature;
59e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private ASN1ObjectIdentifier    contentType;
60e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private byte[]                  resultDigest;
61e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
62e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    // Derived
63e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private AttributeTable          signedAttributeValues;
64e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private AttributeTable          unsignedAttributeValues;
65e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private boolean                 isCounterSignature;
66e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
67e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    SignerInformation(
68e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        SignerInfo          info,
69e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1ObjectIdentifier contentType,
70e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        CMSProcessable      content,
71e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        byte[]              resultDigest)
72e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
73e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this.info = info;
74e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this.contentType = contentType;
75e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this.isCounterSignature = contentType == null;
76e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
77e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        SignerIdentifier   s = info.getSID();
78e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
79e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (s.isTagged())
80e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
81e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            ASN1OctetString octs = ASN1OctetString.getInstance(s.getId());
82e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
83e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            sid = new SignerId(octs.getOctets());
84e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
85e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        else
86e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
87e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            IssuerAndSerialNumber   iAnds = IssuerAndSerialNumber.getInstance(s.getId());
88e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
89e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            sid = new SignerId(iAnds.getName(), iAnds.getSerialNumber().getValue());
90e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
91e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
92e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this.digestAlgorithm = info.getDigestAlgorithm();
93e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this.signedAttributeSet = info.getAuthenticatedAttributes();
94e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this.unsignedAttributeSet = info.getUnauthenticatedAttributes();
95e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this.encryptionAlgorithm = info.getDigestEncryptionAlgorithm();
96e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this.signature = info.getEncryptedDigest().getOctets();
97e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
98e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this.content = content;
99e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this.resultDigest = resultDigest;
100e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
101e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
102e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public boolean isCounterSignature()
103e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
104e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return isCounterSignature;
105e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
106e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
107e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public ASN1ObjectIdentifier getContentType()
108e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
109e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return this.contentType;
110e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
111e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
112e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private byte[] encodeObj(
113e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1Encodable    obj)
114e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        throws IOException
115e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
116e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (obj != null)
117e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
118e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            return obj.toASN1Primitive().getEncoded();
119e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
120e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
121e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return null;
122e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
123e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
124e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public SignerId getSID()
125e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
126e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return sid;
127e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
128e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
129e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
130e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * return the version number for this objects underlying SignerInfo structure.
131e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
132e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public int getVersion()
133e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
134e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return info.getVersion().getValue().intValue();
135e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
136e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
137e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public AlgorithmIdentifier getDigestAlgorithmID()
138e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
139e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return digestAlgorithm;
140e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
141e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
142e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
143e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * return the object identifier for the signature.
144e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
145e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public String getDigestAlgOID()
146e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
14770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        return digestAlgorithm.getAlgorithm().getId();
148e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
149e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
150e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
151e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * return the signature parameters, or null if there aren't any.
152e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
153e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public byte[] getDigestAlgParams()
154e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
155e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        try
156e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
157e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            return encodeObj(digestAlgorithm.getParameters());
158e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
159e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        catch (Exception e)
160e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
161e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            throw new RuntimeException("exception getting digest parameters " + e);
162e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
163e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
164e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
165e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
166e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * return the content digest that was calculated during verification.
167e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
168e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public byte[] getContentDigest()
169e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
170e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (resultDigest == null)
171e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
172e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            throw new IllegalStateException("method can only be called after verify.");
173e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
174e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
175e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return (byte[])resultDigest.clone();
176e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
177e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
178e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
179e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * return the object identifier for the signature.
180e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
181e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public String getEncryptionAlgOID()
182e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
18370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        return encryptionAlgorithm.getAlgorithm().getId();
184e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
185e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
186e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
187e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * return the signature/encryption algorithm parameters, or null if
188e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * there aren't any.
189e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
190e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public byte[] getEncryptionAlgParams()
191e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
192e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        try
193e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
194e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            return encodeObj(encryptionAlgorithm.getParameters());
195e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
196e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        catch (Exception e)
197e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
198e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            throw new RuntimeException("exception getting encryption parameters " + e);
199e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
200e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
201e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
202e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
203e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * return a table of the signed attributes - indexed by
204e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * the OID of the attribute.
205e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
206e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public AttributeTable getSignedAttributes()
207e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
208e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (signedAttributeSet != null && signedAttributeValues == null)
209e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
210e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            signedAttributeValues = new AttributeTable(signedAttributeSet);
211e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
212e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
213e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return signedAttributeValues;
214e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
215e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
216e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
217e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * return a table of the unsigned attributes indexed by
218e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * the OID of the attribute.
219e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
220e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public AttributeTable getUnsignedAttributes()
221e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
222e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (unsignedAttributeSet != null && unsignedAttributeValues == null)
223e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
224e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            unsignedAttributeValues = new AttributeTable(unsignedAttributeSet);
225e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
226e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
227e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return unsignedAttributeValues;
228e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
229e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
230e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
231e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * return the encoded signature
232e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
233e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public byte[] getSignature()
234e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
235e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return (byte[])signature.clone();
236e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
237e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
238e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
239e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * Return a SignerInformationStore containing the counter signatures attached to this
240e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * signer. If no counter signatures are present an empty store is returned.
241e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
242e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public SignerInformationStore getCounterSignatures()
243e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
244e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        // TODO There are several checks implied by the RFC3852 comments that are missing
245e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
246e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        /*
247e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        The countersignature attribute MUST be an unsigned attribute; it MUST
248e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        NOT be a signed attribute, an authenticated attribute, an
249e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        unauthenticated attribute, or an unprotected attribute.
250e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        */
251e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        AttributeTable unsignedAttributeTable = getUnsignedAttributes();
252e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (unsignedAttributeTable == null)
253e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
254e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            return new SignerInformationStore(new ArrayList(0));
255e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
256e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
257e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        List counterSignatures = new ArrayList();
258e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
259e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        /*
260e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        The UnsignedAttributes syntax is defined as a SET OF Attributes.  The
261e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        UnsignedAttributes in a signerInfo may include multiple instances of
262e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        the countersignature attribute.
263e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        */
264e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1EncodableVector allCSAttrs = unsignedAttributeTable.getAll(CMSAttributes.counterSignature);
265e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
266e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        for (int i = 0; i < allCSAttrs.size(); ++i)
267e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
268e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            Attribute counterSignatureAttribute = (Attribute)allCSAttrs.get(i);
269e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
270e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            /*
271e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            A countersignature attribute can have multiple attribute values.  The
272e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            syntax is defined as a SET OF AttributeValue, and there MUST be one
273e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            or more instances of AttributeValue present.
274e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            */
275e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            ASN1Set values = counterSignatureAttribute.getAttrValues();
276e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            if (values.size() < 1)
277e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
278e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                // TODO Throw an appropriate exception?
279e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
280e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
281e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            for (Enumeration en = values.getObjects(); en.hasMoreElements();)
282e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
283e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                /*
284e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                Countersignature values have the same meaning as SignerInfo values
285e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                for ordinary signatures, except that:
286e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
287e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                   1. The signedAttributes field MUST NOT contain a content-type
288e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                      attribute; there is no content type for countersignatures.
289e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
290e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                   2. The signedAttributes field MUST contain a message-digest
291e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                      attribute if it contains any other attributes.
292e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
293e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                   3. The input to the message-digesting process is the contents
294e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                      octets of the DER encoding of the signatureValue field of the
295e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                      SignerInfo value with which the attribute is associated.
296e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                */
297e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                SignerInfo si = SignerInfo.getInstance(en.nextElement());
298e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
299e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                counterSignatures.add(new SignerInformation(si, null, new CMSProcessableByteArray(getSignature()), null));
300e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
301e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
302e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
303e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return new SignerInformationStore(counterSignatures);
304e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
305e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
306e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
307e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * return the DER encoding of the signed attributes.
308e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @throws IOException if an encoding error occurs.
309e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
310e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public byte[] getEncodedSignedAttributes()
311e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        throws IOException
312e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
313e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (signedAttributeSet != null)
314e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
315e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            return signedAttributeSet.getEncoded();
316e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
317e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
318e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return null;
319e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
320e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
321e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
322e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @deprecated
323e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
324e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private boolean doVerify(
325e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        PublicKey       key,
326e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        Provider        sigProvider)
327e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        throws CMSException, NoSuchAlgorithmException
328e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
329e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        try
330e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
331e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            SignerInformationVerifier verifier;
332e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
333e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            if (sigProvider != null)
334e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
335e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                if (!sigProvider.getName().equalsIgnoreCase("BC"))
336e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
337e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    verifier = new JcaSignerInfoVerifierBuilder(new JcaDigestCalculatorProviderBuilder().build()).setProvider(sigProvider).build(key);
338e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
339e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                else
340e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
341e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    verifier = new JcaSimpleSignerInfoVerifierBuilder().setProvider(sigProvider).build(key);
342e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
343e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
344e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            else
345e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
346e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                verifier = new JcaSimpleSignerInfoVerifierBuilder().build(key);
347e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
348e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
349e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            return doVerify(verifier);
350e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
351e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        catch (OperatorCreationException e)
352e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
353e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            throw new CMSException("unable to create verifier: " + e.getMessage(), e);
354e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
355e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
356e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
357e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private boolean doVerify(
358e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        SignerInformationVerifier verifier)
359e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        throws CMSException
360e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
361e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        String          encName = CMSSignedHelper.INSTANCE.getEncryptionAlgName(this.getEncryptionAlgOID());
36270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        ContentVerifier contentVerifier;
363e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
364e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        try
365e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
36670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom            contentVerifier = verifier.getContentVerifier(encryptionAlgorithm, info.getDigestAlgorithm());
36770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        }
36870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        catch (OperatorCreationException e)
36970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        {
37070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom            throw new CMSException("can't create content verifier: " + e.getMessage(), e);
37170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        }
37270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom
37370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        try
37470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom        {
37570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom            OutputStream sigOut = contentVerifier.getOutputStream();
37670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom
377e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            if (resultDigest == null)
378e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
379e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                DigestCalculator calc = verifier.getDigestCalculator(this.getDigestAlgorithmID());
380e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                if (content != null)
381e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
382e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    OutputStream      digOut = calc.getOutputStream();
383e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
38470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    if (signedAttributeSet == null)
38570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    {
38670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                        if (contentVerifier instanceof RawContentVerifier)
38770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                        {
38870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                            content.write(digOut);
38970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                        }
39070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                        else
39170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                        {
39270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                            OutputStream cOut = new TeeOutputStream(digOut, sigOut);
39370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom
39470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                            content.write(cOut);
39570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom
39670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                            cOut.close();
39770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                        }
39870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    }
39970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    else
40070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    {
40170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                        content.write(digOut);
40270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                        sigOut.write(this.getEncodedSignedAttributes());
40370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    }
404e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
405e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    digOut.close();
406e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
40770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                else if (signedAttributeSet != null)
40870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                {
40970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    sigOut.write(this.getEncodedSignedAttributes());
41070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                }
41170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                else
412e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
413e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    // TODO Get rid of this exception and just treat content==null as empty not missing?
414e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    throw new CMSException("data not encapsulated in signature - use detached constructor.");
415e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
416e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
417e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                resultDigest = calc.getDigest();
418e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
41970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom            else
42070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom            {
42170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                if (signedAttributeSet == null)
42270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                {
42370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    if (content != null)
42470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    {
42570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                        content.write(sigOut);
42670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    }
42770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                }
42870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                else
42970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                {
43070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    sigOut.write(this.getEncodedSignedAttributes());
43170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                }
43270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom            }
43370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom
43470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom            sigOut.close();
435e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
436e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        catch (IOException e)
437e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
438e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            throw new CMSException("can't process mime object to create signature.", e);
439e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
440e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        catch (OperatorCreationException e)
441e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
442e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            throw new CMSException("can't create digest calculator: " + e.getMessage(), e);
443e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
444e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
445e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        // RFC 3852 11.1 Check the content-type attribute is correct
446e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
447e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            ASN1Primitive validContentType = getSingleValuedSignedAttribute(
448e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                CMSAttributes.contentType, "content-type");
449e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            if (validContentType == null)
450e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
451e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                if (!isCounterSignature && signedAttributeSet != null)
452e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
453e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    throw new CMSException("The content-type attribute type MUST be present whenever signed attributes are present in signed-data");
454e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
455e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
456e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            else
457e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
458e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                if (isCounterSignature)
459e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
460e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    throw new CMSException("[For counter signatures,] the signedAttributes field MUST NOT contain a content-type attribute");
461e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
462e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
46370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                if (!(validContentType instanceof ASN1ObjectIdentifier))
464e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
465e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    throw new CMSException("content-type attribute value not of ASN.1 type 'OBJECT IDENTIFIER'");
466e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
467e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
46870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                ASN1ObjectIdentifier signedContentType = (ASN1ObjectIdentifier)validContentType;
469e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
470e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                if (!signedContentType.equals(contentType))
471e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
472e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    throw new CMSException("content-type attribute value does not match eContentType");
473e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
474e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
475e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
476e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
477e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        // RFC 3852 11.2 Check the message-digest attribute is correct
478e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
479e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            ASN1Primitive validMessageDigest = getSingleValuedSignedAttribute(
480e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                CMSAttributes.messageDigest, "message-digest");
481e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            if (validMessageDigest == null)
482e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
483e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                if (signedAttributeSet != null)
484e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
485e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    throw new CMSException("the message-digest signed attribute type MUST be present when there are any signed attributes present");
486e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
487e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
488e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            else
489e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
490e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                if (!(validMessageDigest instanceof ASN1OctetString))
491e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
492e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    throw new CMSException("message-digest attribute value not of ASN.1 type 'OCTET STRING'");
493e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
494e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
495e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                ASN1OctetString signedMessageDigest = (ASN1OctetString)validMessageDigest;
496e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
497e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                if (!Arrays.constantTimeAreEqual(resultDigest, signedMessageDigest.getOctets()))
498e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
499e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    throw new CMSSignerDigestMismatchException("message-digest attribute value does not match calculated value");
500e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
501e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
502e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
503e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
504e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        // RFC 3852 11.4 Validate countersignature attribute(s)
505e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
506e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            AttributeTable signedAttrTable = this.getSignedAttributes();
507e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            if (signedAttrTable != null
508e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                && signedAttrTable.getAll(CMSAttributes.counterSignature).size() > 0)
509e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
510e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                throw new CMSException("A countersignature attribute MUST NOT be a signed attribute");
511e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
512e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
513e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            AttributeTable unsignedAttrTable = this.getUnsignedAttributes();
514e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            if (unsignedAttrTable != null)
515e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
516e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                ASN1EncodableVector csAttrs = unsignedAttrTable.getAll(CMSAttributes.counterSignature);
517e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                for (int i = 0; i < csAttrs.size(); ++i)
518e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
519e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    Attribute csAttr = (Attribute)csAttrs.get(i);
520e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    if (csAttr.getAttrValues().size() < 1)
521e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    {
522e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                        throw new CMSException("A countersignature attribute MUST contain at least one AttributeValue");
523e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    }
524e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
525e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    // Note: We don't recursively validate the countersignature value
526e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
527e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
528e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
529e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
530e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        try
531e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
53270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom            if (signedAttributeSet == null && resultDigest != null)
533e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
53470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                if (contentVerifier instanceof RawContentVerifier)
535e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
53670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    RawContentVerifier rawVerifier = (RawContentVerifier)contentVerifier;
537e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
53870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    if (encName.equals("RSA"))
53970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    {
54070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                        DigestInfo digInfo = new DigestInfo(new AlgorithmIdentifier(digestAlgorithm.getAlgorithm(), DERNull.INSTANCE), resultDigest);
541e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
54270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                        return rawVerifier.verify(digInfo.getEncoded(ASN1Encoding.DER), this.getSignature());
543e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    }
544e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
54570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom                    return rawVerifier.verify(resultDigest, this.getSignature());
546e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
547e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
548e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
549e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            return contentVerifier.verify(this.getSignature());
550e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
551e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        catch (IOException e)
552e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
553e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            throw new CMSException("can't process mime object to create signature.", e);
554e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
555e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
556e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
557e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
558e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * verify that the given public key successfully handles and confirms the
559e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * signature associated with this signer.
560e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @deprecated use verify(ContentVerifierProvider)
561e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
562e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public boolean verify(
563e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        PublicKey   key,
564e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        String      sigProvider)
565e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
566e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
567e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return verify(key, CMSUtils.getProvider(sigProvider));
568e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
569e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
570e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
571e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * verify that the given public key successfully handles and confirms the
572e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * signature associated with this signer
573e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @deprecated use verify(ContentVerifierProvider)
574e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
575e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public boolean verify(
576e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        PublicKey   key,
577e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        Provider    sigProvider)
578e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
579e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
580e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        // Optional, but still need to validate if present
581e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        getSigningTime();
582e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
583e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return doVerify(key, sigProvider);
584e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
585e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
586e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
587e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * verify that the given certificate successfully handles and confirms
588e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * the signature associated with this signer and, if a signingTime
589e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * attribute is available, that the certificate was valid at the time the
590e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * signature was generated.
591e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @deprecated use verify(ContentVerifierProvider)
592e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
593e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public boolean verify(
594e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        X509Certificate cert,
595e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        String          sigProvider)
596e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        throws NoSuchAlgorithmException, NoSuchProviderException,
597e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            CertificateExpiredException, CertificateNotYetValidException,
598e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            CMSException
599e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
600e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return verify(cert, CMSUtils.getProvider(sigProvider));
601e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
602e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
603e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
604e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * verify that the given certificate successfully handles and confirms
605e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * the signature associated with this signer and, if a signingTime
606e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * attribute is available, that the certificate was valid at the time the
607e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * signature was generated.
608e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @deprecated use verify(ContentVerifierProvider)
609e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
610e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public boolean verify(
611e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        X509Certificate cert,
612e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        Provider        sigProvider)
613e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        throws NoSuchAlgorithmException,
614e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            CertificateExpiredException, CertificateNotYetValidException,
615e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            CMSException
616e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
617e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        Time signingTime = getSigningTime();
618e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (signingTime != null)
619e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
620e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            cert.checkValidity(signingTime.getDate());
621e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
622e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
623e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return doVerify(cert.getPublicKey(), sigProvider);
624e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
625e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
626e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
627e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * Verify that the given verifier can successfully verify the signature on
628e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * this SignerInformation object.
629e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     *
630e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @param verifier a suitably configured SignerInformationVerifier.
631e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @return true if the signer information is verified, false otherwise.
632e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @throws org.bouncycastle.cms.CMSVerifierCertificateNotValidException if the provider has an associated certificate and the certificate is not valid at the time given as the SignerInfo's signing time.
633e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @throws org.bouncycastle.cms.CMSException if the verifier is unable to create a ContentVerifiers or DigestCalculators.
634e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
635e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public boolean verify(SignerInformationVerifier verifier)
636e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        throws CMSException
637e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
638e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        Time signingTime = getSigningTime();   // has to be validated if present.
639e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
640e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (verifier.hasAssociatedCertificate())
641e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
642e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            if (signingTime != null)
643e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
644e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                X509CertificateHolder dcv = verifier.getAssociatedCertificate();
645e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
646e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                if (!dcv.isValidOn(signingTime.getDate()))
647e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
648e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    throw new CMSVerifierCertificateNotValidException("verifier not valid at signingTime");
649e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
650e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
651e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
652e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
653e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return doVerify(verifier);
654e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
655e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
656e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
657e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * Return the base ASN.1 CMS structure that this object contains.
658e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     *
659e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @return an object containing a CMS SignerInfo structure.
660e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @deprecated use toASN1Structure()
661e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
662e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public SignerInfo toSignerInfo()
663e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
664e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return info;
665e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
666e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
667e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
668e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * Return the underlying ASN.1 object defining this SignerInformation object.
669e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     *
670e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @return a SignerInfo.
671e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
672e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public SignerInfo toASN1Structure()
673e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
674e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return info;
675e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
676e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
677e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private ASN1Primitive getSingleValuedSignedAttribute(
678e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1ObjectIdentifier attrOID, String printableName)
679e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        throws CMSException
680e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
681e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        AttributeTable unsignedAttrTable = this.getUnsignedAttributes();
682e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (unsignedAttrTable != null
683e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            && unsignedAttrTable.getAll(attrOID).size() > 0)
684e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
685e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            throw new CMSException("The " + printableName
686e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                + " attribute MUST NOT be an unsigned attribute");
687e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
688e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
689e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        AttributeTable signedAttrTable = this.getSignedAttributes();
690e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (signedAttrTable == null)
691e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
692e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            return null;
693e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
694e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
695e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1EncodableVector v = signedAttrTable.getAll(attrOID);
696e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        switch (v.size())
697e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
698e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            case 0:
699e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                return null;
700e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            case 1:
701e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
702e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                Attribute t = (Attribute)v.get(0);
703e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                ASN1Set attrValues = t.getAttrValues();
704e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                if (attrValues.size() != 1)
705e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
706e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    throw new CMSException("A " + printableName
707e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                        + " attribute MUST have a single attribute value");
708e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
709e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
710e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                return attrValues.getObjectAt(0).toASN1Primitive();
711e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
712e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            default:
713e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                throw new CMSException("The SignedAttributes in a signerInfo MUST NOT include multiple instances of the "
714e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    + printableName + " attribute");
715e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
716e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
717e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
718e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private Time getSigningTime() throws CMSException
719e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
720e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1Primitive validSigningTime = getSingleValuedSignedAttribute(
721e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            CMSAttributes.signingTime, "signing-time");
722e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
723e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (validSigningTime == null)
724e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
725e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            return null;
726e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
727e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
728e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        try
729e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
730e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            return Time.getInstance(validSigningTime);
731e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
732e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        catch (IllegalArgumentException e)
733e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
734e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            throw new CMSException("signing-time attribute value not a valid 'Time' structure");
735e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
736e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
737e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
738e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
739e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * Return a signer information object with the passed in unsigned
740e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * attributes replacing the ones that are current associated with
741e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * the object passed in.
742e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     *
743e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @param signerInformation the signerInfo to be used as the basis.
744e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @param unsignedAttributes the unsigned attributes to add.
745e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @return a copy of the original SignerInformationObject with the changed attributes.
746e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
747e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public static SignerInformation replaceUnsignedAttributes(
748e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        SignerInformation   signerInformation,
749e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        AttributeTable      unsignedAttributes)
750e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
751e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        SignerInfo  sInfo = signerInformation.info;
752e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1Set     unsignedAttr = null;
753e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
754e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (unsignedAttributes != null)
755e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
756e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            unsignedAttr = new DERSet(unsignedAttributes.toASN1EncodableVector());
757e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
758e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
759e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return new SignerInformation(
760e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                new SignerInfo(sInfo.getSID(), sInfo.getDigestAlgorithm(),
761e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    sInfo.getAuthenticatedAttributes(), sInfo.getDigestEncryptionAlgorithm(), sInfo.getEncryptedDigest(), unsignedAttr),
762e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    signerInformation.contentType, signerInformation.content, null);
763e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
764e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
765e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
766e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * Return a signer information object with passed in SignerInformationStore representing counter
767e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * signatures attached as an unsigned attribute.
768e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     *
769e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @param signerInformation the signerInfo to be used as the basis.
770e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @param counterSigners signer info objects carrying counter signature.
771e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @return a copy of the original SignerInformationObject with the changed attributes.
772e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
773e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public static SignerInformation addCounterSigners(
774e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        SignerInformation        signerInformation,
775e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        SignerInformationStore   counterSigners)
776e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
777e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        // TODO Perform checks from RFC 3852 11.4
778e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
779e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        SignerInfo          sInfo = signerInformation.info;
780e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        AttributeTable      unsignedAttr = signerInformation.getUnsignedAttributes();
781e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1EncodableVector v;
782e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
783e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (unsignedAttr != null)
784e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
785e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            v = unsignedAttr.toASN1EncodableVector();
786e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
787e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        else
788e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
789e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            v = new ASN1EncodableVector();
790e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
791e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
792e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1EncodableVector sigs = new ASN1EncodableVector();
793e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
794e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        for (Iterator it = counterSigners.getSigners().iterator(); it.hasNext();)
795e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
79670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom            sigs.add(((SignerInformation)it.next()).toASN1Structure());
797e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
798e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
799e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        v.add(new Attribute(CMSAttributes.counterSignature, new DERSet(sigs)));
800e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
801e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return new SignerInformation(
802e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                new SignerInfo(sInfo.getSID(), sInfo.getDigestAlgorithm(),
803e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    sInfo.getAuthenticatedAttributes(), sInfo.getDigestEncryptionAlgorithm(), sInfo.getEncryptedDigest(), new DERSet(v)),
804e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    signerInformation.contentType, signerInformation.content, null);
805e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
806e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom}
807