OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [java/] [security/] [pkcs/] [PKCS7SignedData.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* PKCS7SignedData.java -- reader/writer for PKCS#7 signedData objects
2
   Copyright (C) 2004, 2005, 2006  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
package gnu.java.security.pkcs;
39
 
40
import gnu.java.security.Configuration;
41
import gnu.java.security.OID;
42
import gnu.java.security.ber.BER;
43
import gnu.java.security.ber.BEREncodingException;
44
import gnu.java.security.ber.BERReader;
45
import gnu.java.security.ber.BERValue;
46
import gnu.java.security.der.DER;
47
import gnu.java.security.der.DERValue;
48
import gnu.java.security.der.DERWriter;
49
import gnu.java.security.util.Util;
50
 
51
import java.io.ByteArrayInputStream;
52
import java.io.ByteArrayOutputStream;
53
import java.io.IOException;
54
import java.io.InputStream;
55
import java.io.OutputStream;
56
import java.math.BigInteger;
57
import java.security.cert.CRL;
58
import java.security.cert.CRLException;
59
import java.security.cert.Certificate;
60
import java.security.cert.CertificateEncodingException;
61
import java.security.cert.CertificateException;
62
import java.security.cert.CertificateFactory;
63
import java.security.cert.X509CRL;
64
import java.util.ArrayList;
65
import java.util.Collections;
66
import java.util.HashSet;
67
import java.util.Iterator;
68
import java.util.LinkedList;
69
import java.util.List;
70
import java.util.Set;
71
import java.util.logging.Logger;
72
 
73
/**
74
 * The SignedData object in PKCS #7. This is a read-only implementation of
75
 * this format, and is used to provide signed Jar file support.
76
 *
77
 * @author Casey Marshall (csm@gnu.org)
78
 */
79
public class PKCS7SignedData
80
{
81
  private static final Logger log = Logger.getLogger(PKCS7SignedData.class.getName());
82
 
83
  public static final OID PKCS7_SIGNED_DATA = new OID("1.2.840.113549.1.7.2");
84
 
85
  private BigInteger version;
86
  private Set digestAlgorithms;
87
  private OID contentType;
88
  private byte[] content;
89
  private Certificate[] certificates;
90
  private CRL[] crls;
91
  private Set signerInfos;
92
 
93
  public PKCS7SignedData(InputStream in)
94
    throws CRLException, CertificateException, IOException
95
  {
96
    this(new BERReader(in));
97
  }
98
 
99
  /**
100
   * Parse an encoded PKCS#7 SignedData object. The ASN.1 format of this
101
   * object is:
102
   *
103
   * <pre>
104
   * SignedData ::= SEQUENCE {
105
   *   version           Version, -- always 1 for PKCS7 v1.5
106
   *   digestAlgorithms  DigestAlgorithmIdentifiers,
107
   *   contentInfo       ContentInfo,
108
   *   certificates  [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
109
   *   crls          [1] IMPLICIT CertificateRevocationLists OPTIONAL,
110
   *   signerInfos       SignerInfos }
111
   *
112
   * Version ::= INTEGER
113
   *
114
   * DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
115
   *
116
   * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
117
   *
118
   * ContentInfo ::= SEQUENCE {
119
   *   contentType   ContentType,
120
   *   content   [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
121
   *
122
   * ContentType ::= OBJECT IDENTIFIER
123
   *
124
   * ExtendedCertificatesAndCertificates ::=
125
   *   SET OF ExtendedCertificatesAndCertificate
126
   *
127
   * ExtendedCertificatesAndCertificate ::= CHOICE {
128
   *   certificate             Certificate, -- from X.509
129
   *   extendedCertificate [0] IMPLICIT ExtendedCertificate }
130
   *
131
   * CertificateRevocationLists ::= SET OF CertificateRevocationList
132
   *   -- from X.509
133
   *
134
   * SignerInfos ::= SET OF SignerInfo
135
   *
136
   * SignerInfo ::= SEQUENCE {
137
   *   version                       Version, -- always 1 for PKCS7 v1.5
138
   *   issuerAndSerialNumber         IssuerAndSerialNumber,
139
   *   digestAlgorithm               DigestAlgorithmIdentifier,
140
   *   authenticatedAttributes   [0] IMPLICIT Attributes OPTIONAL,
141
   *   digestEncryptionAlgorithm     DigestEncryptionAlgorithmIdentifier,
142
   *   encryptedDigest               EncryptedDigest,
143
   *   unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL }
144
   *
145
   * EncryptedDigest ::= OCTET STRING
146
   * </pre>
147
   *
148
   * <p>(Readers who are confused as to why it takes 40 levels of indirection
149
   * to specify "data with a signature", rest assured that the present author
150
   * is as confused as you are).</p>
151
   */
152
  public PKCS7SignedData(BERReader ber)
153
    throws CRLException, CertificateException, IOException
154
  {
155
    CertificateFactory x509 = CertificateFactory.getInstance("X509");
156
    DERValue val = ber.read();
157
    if (!val.isConstructed())
158
      throw new BEREncodingException("malformed ContentInfo");
159
 
160
    val = ber.read();
161
    if (val.getTag() != BER.OBJECT_IDENTIFIER)
162
      throw new BEREncodingException("malformed ContentType");
163
 
164
    if (!PKCS7_SIGNED_DATA.equals(val.getValue()))
165
      throw new BEREncodingException("content is not SignedData");
166
 
167
    val = ber.read();
168
    if (val.getTag() != 0)
169
      throw new BEREncodingException("malformed Content");
170
 
171
    val = ber.read();
172
    if (!val.isConstructed())
173
      throw new BEREncodingException("malformed SignedData");
174
 
175
    if (Configuration.DEBUG)
176
      log.fine("SignedData: " + val);
177
 
178
    val = ber.read();
179
    if (val.getTag() != BER.INTEGER)
180
      throw new BEREncodingException("expecting Version");
181
    version = (BigInteger) val.getValue();
182
    if (Configuration.DEBUG)
183
      log.fine("  Version: " + version);
184
 
185
    digestAlgorithms = new HashSet();
186
    val = ber.read();
187
    if (!val.isConstructed())
188
      throw new BEREncodingException("malformed DigestAlgorithmIdentifiers");
189
    if (Configuration.DEBUG)
190
      log.fine("  DigestAlgorithmIdentifiers: " + val);
191
    int count = 0;
192
    DERValue val2 = ber.read();
193
    while (val2 != BER.END_OF_SEQUENCE &&
194
           (val.getLength() > 0 && val.getLength() > count))
195
      {
196
        if (!val2.isConstructed())
197
          throw new BEREncodingException("malformed AlgorithmIdentifier");
198
        if (Configuration.DEBUG)
199
          log.fine("    AlgorithmIdentifier: " + val2);
200
        count += val2.getEncodedLength();
201
        val2 = ber.read();
202
        if (val2.getTag() != BER.OBJECT_IDENTIFIER)
203
          throw new BEREncodingException("malformed AlgorithmIdentifier");
204
        if (Configuration.DEBUG)
205
          log.fine("      digestAlgorithmIdentifiers OID: " + val2.getValue());
206
        List algId = new ArrayList(2);
207
        algId.add(val2.getValue());
208
        val2 = ber.read();
209
        if (val2 != BER.END_OF_SEQUENCE)
210
          {
211
            count += val2.getEncodedLength();
212
            if (val2.getTag() == BER.NULL)
213
              algId.add(null);
214
            else
215
              algId.add(val2.getEncoded());
216
 
217
            if (val2.isConstructed())
218
              ber.skip(val2.getLength());
219
 
220
            if (BERValue.isIndefinite(val))
221
              val2 = ber.read();
222
          }
223
        else
224
          algId.add(null);
225
 
226
        if (Configuration.DEBUG)
227
          {
228
            log.fine("      digestAlgorithmIdentifiers params: ");
229
            log.fine(Util.dumpString((byte[]) algId.get(1),
230
                                     "      digestAlgorithmIdentifiers params: "));
231
          }
232
        digestAlgorithms.add(algId);
233
      }
234
 
235
    val = ber.read();
236
    if (!val.isConstructed())
237
      throw new BEREncodingException("malformed ContentInfo");
238
    if (Configuration.DEBUG)
239
      log.fine("  ContentInfo: " + val);
240
    val2 = ber.read();
241
    if (val2.getTag() != BER.OBJECT_IDENTIFIER)
242
      throw new BEREncodingException("malformed ContentType");
243
 
244
    contentType = (OID) val2.getValue();
245
    if (Configuration.DEBUG)
246
      log.fine("    ContentType OID: " + contentType);
247
    if (BERValue.isIndefinite(val)
248
        || (val.getLength() > 0 && val.getLength() > val2.getEncodedLength()))
249
      {
250
        val2 = ber.read();
251
        if (val2 != BER.END_OF_SEQUENCE)
252
          {
253
            content = val2.getEncoded();
254
            if (BERValue.isIndefinite(val))
255
              val2 = ber.read();
256
          }
257
      }
258
    if (Configuration.DEBUG)
259
      {
260
        log.fine("    Content: ");
261
        log.fine(Util.dumpString(content, "    Content: "));
262
      }
263
    val = ber.read();
264
    if (val.getTag() == 0)
265
      {
266
        if (!val.isConstructed())
267
          throw new BEREncodingException("malformed ExtendedCertificatesAndCertificates");
268
        if (Configuration.DEBUG)
269
          log.fine("  ExtendedCertificatesAndCertificates: " + val);
270
        count = 0;
271
        val2 = ber.read();
272
        List certs = new LinkedList();
273
        while (val2 != BER.END_OF_SEQUENCE &&
274
               (val.getLength() > 0 && val.getLength() > count))
275
          {
276
            Certificate cert =
277
              x509.generateCertificate(new ByteArrayInputStream(val2.getEncoded()));
278
            if (Configuration.DEBUG)
279
              log.fine("    Certificate: " + cert);
280
            certs.add(cert);
281
            count += val2.getEncodedLength();
282
            ber.skip(val2.getLength());
283
            if (BERValue.isIndefinite(val) || val.getLength() > count)
284
              val2 = ber.read();
285
          }
286
        certificates = (Certificate[]) certs.toArray(new Certificate[certs.size()]);
287
        val = ber.read();
288
      }
289
 
290
    if (val.getTag() == 1)
291
      {
292
        if (!val.isConstructed())
293
          throw new BEREncodingException("malformed CertificateRevocationLists");
294
        if (Configuration.DEBUG)
295
          log.fine("  CertificateRevocationLists: " + val);
296
        count = 0;
297
        val2 = ber.read();
298
        List crls = new LinkedList();
299
        while (val2 != BER.END_OF_SEQUENCE &&
300
               (val.getLength() > 0 && val.getLength() > count))
301
          {
302
            CRL crl = x509.generateCRL(new ByteArrayInputStream(val2.getEncoded()));
303
            if (Configuration.DEBUG)
304
              log.fine("    CRL: " + crl);
305
            crls.add(crl);
306
            count += val2.getEncodedLength();
307
            ber.skip(val2.getLength());
308
            if (BERValue.isIndefinite(val) || val.getLength() > count)
309
              val2 = ber.read();
310
          }
311
        this.crls = (CRL[]) crls.toArray(new CRL[crls.size()]);
312
        val = ber.read();
313
      }
314
 
315
    signerInfos = new HashSet();
316
    if (!val.isConstructed())
317
      throw new BEREncodingException("malformed SignerInfos");
318
    if (Configuration.DEBUG)
319
      log.fine("  SignerInfos: " + val);
320
 
321
    // FIXME read this more carefully.
322
    // Since we are just reading a file (probably) we just read until we
323
    // reach the end.
324
    while (true)
325
      {
326
        int i = ber.peek();
327
        if (i == 0 || i == -1)
328
          break;
329
        signerInfos.add(new SignerInfo(ber));
330
      }
331
  }
332
 
333
  /**
334
   * Constructs a new instance of <code>PKCS7SignedData</code> given a
335
   * designated set of fields.
336
   *
337
   * @param digestAlgorithms the collection of DigestAlgorithm elements. Each
338
   *          DigestAlgorithm is a {@link List} of two elements, the first is an
339
   *          OID while the second is dependent on the value of the OID element.
340
   * @param data an instance of a PKCS#7 (non-signed) data. In its simplest form
341
   *          such an ASN.1 structure would consist of just the OID of a
342
   *          non-signed PKCS#7 Data.
343
   * @param certificates the array of Certificates used to authenticate the
344
   *          enclosed (or referenced, in case the content is null) data.
345
   * @param crls the array of certificate-revocation lists of the used
346
   *          certificates.
347
   * @param signerInfos a set of {@link SignerInfo} elements, one per signer of
348
   *          the data referenced by this <code>PKCS7SignedData</code>
349
   *          instance.
350
   */
351
  public PKCS7SignedData(Set digestAlgorithms, PKCS7Data data,
352
                         Certificate[] certificates, X509CRL[] crls,
353
                         Set signerInfos)
354
  {
355
    super();
356
 
357
    this.version = BigInteger.ONE;
358
    this.digestAlgorithms = digestAlgorithms;
359
    this.contentType = PKCS7_SIGNED_DATA;
360
    this.content = data == null ? null : data.getEncoded();
361
    this.certificates = certificates;
362
    this.crls = crls;
363
    this.signerInfos = signerInfos;
364
  }
365
 
366
  public BigInteger getVersion()
367
  {
368
    return version;
369
  }
370
 
371
  public Certificate[] getCertificates()
372
  {
373
    return (certificates != null ? (Certificate[]) certificates.clone()
374
            : null);
375
  }
376
 
377
  public OID getContentType()
378
  {
379
    return contentType;
380
  }
381
 
382
  public byte[] getContent()
383
  {
384
    return (content != null ? (byte[]) content.clone() : null);
385
  }
386
 
387
  public Set getDigestAlgorithms()
388
  {
389
    // FIXME copy contents too, they are mutable!!!
390
    return Collections.unmodifiableSet(digestAlgorithms);
391
  }
392
 
393
  public Set getSignerInfos()
394
  {
395
    Set copy = new HashSet();
396
    for (Iterator it = signerInfos.iterator(); it.hasNext(); )
397
      copy.add(it.next());
398
    return Collections.unmodifiableSet(copy);
399
  }
400
 
401
  /**
402
   * Writes to the designated output stream the DER encoding of the current
403
   * contents of this instance.
404
   *
405
   * @param out the destination output stream.
406
   * @throws IOException if an I/O related exception occurs during the process.
407
   * @throws CRLException if an exception occurs while encoding the certificate
408
   * revocation lists associated with this instance.
409
   * @throws CertificateEncodingException if an exception occurs while encoding
410
   * the certificate chains associated with this instance.
411
   */
412
  public void encode(OutputStream out) throws IOException, CRLException,
413
      CertificateEncodingException
414
  {
415
    DERValue derVersion = new DERValue(DER.INTEGER, version);
416
 
417
    DERValue derDigestAlgorithms = new DERValue(DER.CONSTRUCTED | DER.SET,
418
                                                digestAlgorithms);
419
 
420
    DERValue derContentType = new DERValue(DER.OBJECT_IDENTIFIER,
421
                                           PKCS7Data.PKCS7_DATA);
422
    ArrayList contentInfo = new ArrayList(2);
423
    contentInfo.add(derContentType);
424
    if (content == null)
425
      contentInfo.add(new DERValue(DER.NULL, null));
426
    else
427
      contentInfo.add(content);
428
 
429
    DERValue derContentInfo = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
430
                                           contentInfo);
431
 
432
    ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
433
    for (int i = 0; i < certificates.length; i++)
434
      baos.write(certificates[i].getEncoded());
435
 
436
    baos.flush();
437
    byte[] b = baos.toByteArray();
438
    DERValue derExtendedCertificatesAndCertificates =
439
        new DERValue(DER.CONSTRUCTED | DER.CONTEXT | 0, b.length, b, null);
440
 
441
    DERValue derCertificateRevocationLists = null;
442
    if (crls != null && crls.length > 0)
443
      {
444
        baos.reset();
445
        for (int i = 0; i < crls.length; i++)
446
          baos.write(((X509CRL) crls[i]).getEncoded());
447
 
448
        baos.flush();
449
        byte[] b2 = baos.toByteArray();
450
        derCertificateRevocationLists =
451
            new DERValue(DER.CONSTRUCTED | DER.CONTEXT | 1, b2.length, b2, null);
452
      }
453
 
454
    baos.reset();
455
    for (Iterator it = signerInfos.iterator(); it.hasNext();)
456
      {
457
        SignerInfo signerInfo = (SignerInfo) it.next();
458
        signerInfo.encode(baos);
459
      }
460
    baos.flush();
461
    byte[] b3 = baos.toByteArray();
462
    DERValue derSignerInfos = new DERValue(DER.CONSTRUCTED | DER.SET,
463
                                           b3.length, b3, null);
464
 
465
    ArrayList signedData = new ArrayList(6);
466
    signedData.add(derVersion);
467
    signedData.add(derDigestAlgorithms);
468
    signedData.add(derContentInfo);
469
    signedData.add(derExtendedCertificatesAndCertificates);
470
    if (derCertificateRevocationLists != null)
471
      signedData.add(derCertificateRevocationLists);
472
 
473
    signedData.add(derSignerInfos);
474
    DERValue derSignedData = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
475
                                          signedData);
476
    // now the outer contents
477
    ArrayList outer = new ArrayList(3);
478
    outer.add(new DERValue(DER.OBJECT_IDENTIFIER, PKCS7_SIGNED_DATA));
479
    outer.add(new DERValue(DER.CONTEXT | 0, null));
480
    outer.add(derSignedData);
481
    DERValue derOuter = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, outer);
482
 
483
    DERWriter.write(out, derOuter);
484
  }
485
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.