1 /*
   2  * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.security.pkcs;
  27 
  28 import java.io.IOException;
  29 import java.util.ArrayList;
  30 
  31 import sun.misc.HexDumpEncoder;
  32 import sun.security.util.DerInputStream;
  33 import sun.security.util.DerValue;
  34 import sun.security.x509.GeneralNames;
  35 import sun.security.x509.SerialNumber;
  36 
  37 /**
  38  * This class represents a signing certificate attribute.
  39  * Its attribute value is defined by the following ASN.1 definition.
  40  * <pre>
  41  *
  42  *   id-aa-signingCertificate OBJECT IDENTIFIER ::= { iso(1)
  43  *     member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
  44  *     smime(16) id-aa(2) 12 }
  45  *
  46  *   SigningCertificate ::=  SEQUENCE {
  47  *       certs       SEQUENCE OF ESSCertID,
  48  *       policies    SEQUENCE OF PolicyInformation OPTIONAL
  49  *   }
  50  *
  51  *   ESSCertID ::=  SEQUENCE {
  52  *       certHash        Hash,
  53  *       issuerSerial    IssuerSerial OPTIONAL
  54  *   }
  55  *
  56  *   Hash ::= OCTET STRING -- SHA1 hash of entire certificate
  57  *
  58  *   IssuerSerial ::= SEQUENCE {
  59  *       issuer         GeneralNames,
  60  *       serialNumber   CertificateSerialNumber
  61  *   }
  62  *
  63  *   PolicyInformation ::= SEQUENCE {
  64  *       policyIdentifier   CertPolicyId,
  65  *       policyQualifiers   SEQUENCE SIZE (1..MAX) OF
  66  *               PolicyQualifierInfo OPTIONAL }
  67  *
  68  *   CertPolicyId ::= OBJECT IDENTIFIER
  69  *
  70  *   PolicyQualifierInfo ::= SEQUENCE {
  71  *       policyQualifierId  PolicyQualifierId,
  72  *       qualifier        ANY DEFINED BY policyQualifierId }
  73  *
  74  *   -- Implementations that recognize additional policy qualifiers MUST
  75  *   -- augment the following definition for PolicyQualifierId
  76  *
  77  *   PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
  78  *
  79  * </pre>
  80  *
  81  * @since 1.5
  82  * @author Vincent Ryan
  83  */
  84 public class SigningCertificateInfo {
  85 
  86     private byte[] ber = null;
  87 
  88     private ESSCertId[] certId = null;
  89 
  90     public SigningCertificateInfo(byte[] ber) throws IOException {
  91         parse(ber);
  92     }
  93 
  94     public String toString() {
  95         StringBuilder sb = new StringBuilder();
  96         sb.append("[\n");
  97         for (int i = 0; i < certId.length; i++) {
  98             sb.append(certId[i].toString());
  99         }
 100         // format policies as a string
 101         sb.append("\n]");
 102 
 103         return sb.toString();
 104     }
 105 
 106     public void parse(byte[] bytes) throws IOException {
 107 
 108         // Parse signingCertificate
 109         DerValue derValue = new DerValue(bytes);
 110         if (derValue.tag != DerValue.tag_Sequence) {
 111             throw new IOException("Bad encoding for signingCertificate");
 112         }
 113 
 114         // Parse certs
 115         DerValue[] certs = derValue.data.getSequence(1);
 116         certId = new ESSCertId[certs.length];
 117         for (int i = 0; i < certs.length; i++) {
 118             certId[i] = new ESSCertId(certs[i]);
 119         }
 120 
 121         // Parse policies, if present
 122         if (derValue.data.available() > 0) {
 123             DerValue[] policies = derValue.data.getSequence(1);
 124             for (int i = 0; i < policies.length; i++) {
 125                 // parse PolicyInformation
 126             }
 127         }
 128     }
 129 }
 130 
 131 class ESSCertId {
 132 
 133     private static volatile HexDumpEncoder hexDumper;
 134 
 135     private byte[] certHash;
 136     private GeneralNames issuer;
 137     private SerialNumber serialNumber;
 138 
 139     ESSCertId(DerValue certId) throws IOException {
 140         // Parse certHash
 141         certHash = certId.data.getDerValue().toByteArray();
 142 
 143         // Parse issuerSerial, if present
 144         if (certId.data.available() > 0) {
 145             DerValue issuerSerial = certId.data.getDerValue();
 146             // Parse issuer
 147             issuer = new GeneralNames(issuerSerial.data.getDerValue());
 148             // Parse serialNumber
 149             serialNumber = new SerialNumber(issuerSerial.data.getDerValue());
 150         }
 151     }
 152 
 153     public String toString() {
 154         StringBuilder sb = new StringBuilder();
 155         sb.append("[\n\tCertificate hash (SHA-1):\n");
 156         if (hexDumper == null) {
 157             hexDumper = new HexDumpEncoder();
 158         }
 159         sb.append(hexDumper.encode(certHash));
 160         if (issuer != null && serialNumber != null) {
 161             sb.append("\n\tIssuer: ").append(issuer).append('\n');
 162             sb.append('\t').append(serialNumber);
 163         }
 164         sb.append("\n]");
 165         return sb.toString();
 166     }
 167 }