1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18/**
19* @author Alexander Y. Kleymenov
20* @version $Revision$
21*/
22
23package org.apache.harmony.security.x509;
24
25import java.math.BigInteger;
26import javax.security.auth.x500.X500Principal;
27import org.apache.harmony.security.asn1.ASN1BitString;
28import org.apache.harmony.security.asn1.ASN1Explicit;
29import org.apache.harmony.security.asn1.ASN1Implicit;
30import org.apache.harmony.security.asn1.ASN1Integer;
31import org.apache.harmony.security.asn1.ASN1Sequence;
32import org.apache.harmony.security.asn1.ASN1Type;
33import org.apache.harmony.security.asn1.BerInputStream;
34import org.apache.harmony.security.asn1.BitString;
35import org.apache.harmony.security.x501.Name;
36
37/**
38 * The class encapsulates the ASN.1 DER encoding/decoding work
39 * with TBSCertificate structure which is the part of X.509 certificate
40 * (as specified in RFC 3280 -
41 *  Internet X.509 Public Key Infrastructure.
42 *  Certificate and Certificate Revocation List (CRL) Profile.
43 *  http://www.ietf.org/rfc/rfc3280.txt):
44 *
45 * <pre>
46 *  TBSCertificate  ::=  SEQUENCE  {
47 *       version         [0]  EXPLICIT Version DEFAULT v1,
48 *       serialNumber         CertificateSerialNumber,
49 *       signature            AlgorithmIdentifier,
50 *       issuer               Name,
51 *       validity             Validity,
52 *       subject              Name,
53 *       subjectPublicKeyInfo SubjectPublicKeyInfo,
54 *       issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
55 *                            -- If present, version MUST be v2 or v3
56 *       subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
57 *                            -- If present, version MUST be v2 or v3
58 *       extensions      [3]  EXPLICIT Extensions OPTIONAL
59 *                            -- If present, version MUST be v3
60 *  }
61 * </pre>
62 */
63public final class TBSCertificate {
64
65    /** the value of version field of the structure */
66    private final int version;
67    /** the value of serialNumber field of the structure */
68    private final BigInteger serialNumber;
69    /** the value of signature field of the structure */
70    private final AlgorithmIdentifier signature;
71    /** the value of issuer field of the structure */
72    private final Name issuer;
73    /** the value of validity field of the structure */
74    private final Validity validity;
75    /** the value of subject field of the structure */
76    private final Name subject;
77    /** the value of subjectPublicKeyInfo field of the structure */
78    private final SubjectPublicKeyInfo subjectPublicKeyInfo;
79    /** the value of issuerUniqueID field of the structure */
80    private final boolean[] issuerUniqueID;
81    /** the value of subjectUniqueID field of the structure */
82    private final boolean[] subjectUniqueID;
83    /** the value of extensions field of the structure */
84    private final Extensions extensions;
85    /** the ASN.1 encoded form of TBSCertificate */
86    private byte[] encoding;
87
88    public TBSCertificate(int version, BigInteger serialNumber,
89                          AlgorithmIdentifier signature, Name issuer,
90                          Validity validity, Name subject,
91                          SubjectPublicKeyInfo subjectPublicKeyInfo,
92                          boolean[] issuerUniqueID, boolean[] subjectUniqueID,
93                          Extensions extensions) {
94        this.version = version;
95        this.serialNumber = serialNumber;
96        this.signature = signature;
97        this.issuer = issuer;
98        this.validity = validity;
99        this.subject = subject;
100        this.subjectPublicKeyInfo = subjectPublicKeyInfo;
101        this.issuerUniqueID = issuerUniqueID;
102        this.subjectUniqueID = subjectUniqueID;
103        this.extensions = extensions;
104    }
105
106    private TBSCertificate(int version, BigInteger serialNumber,
107                          AlgorithmIdentifier signature, Name issuer,
108                          Validity validity, Name subject,
109                          SubjectPublicKeyInfo subjectPublicKeyInfo,
110                          boolean[] issuerUniqueID, boolean[] subjectUniqueID,
111                          Extensions extensions, byte[] encoding) {
112        this(version, serialNumber, signature, issuer, validity, subject,
113             subjectPublicKeyInfo, issuerUniqueID, subjectUniqueID, extensions);
114        this.encoding = encoding;
115    }
116
117    /**
118     * Returns the value of version field of the structure.
119     */
120    public int getVersion() {
121        return version;
122    }
123
124    /**
125     * Returns the value of serialNumber field of the structure.
126     */
127    public BigInteger getSerialNumber() {
128        return serialNumber;
129    }
130
131    /**
132     * Returns the value of signature field of the structure.
133     */
134    public AlgorithmIdentifier getSignature() {
135        return signature;
136    }
137
138    /**
139     * Returns the value of issuer field of the structure.
140     */
141    public Name getIssuer() {
142        return issuer;
143    }
144
145    /**
146     * Returns the value of validity field of the structure.
147     */
148    public Validity getValidity() {
149        return validity;
150    }
151
152    /**
153     * Returns the value of subject field of the structure.
154     */
155    public Name getSubject() {
156        return subject;
157    }
158
159    /**
160     * Returns the value of subjectPublicKeyInfo field of the structure.
161     */
162    public SubjectPublicKeyInfo getSubjectPublicKeyInfo() {
163        return subjectPublicKeyInfo;
164    }
165
166    /**
167     * Returns the value of issuerUniqueID field of the structure.
168     */
169    public boolean[] getIssuerUniqueID() {
170        return issuerUniqueID;
171    }
172
173    /**
174     * Returns the value of subjectUniqueID field of the structure.
175     */
176    public boolean[] getSubjectUniqueID() {
177        return subjectUniqueID;
178    }
179
180    /**
181     * Returns the value of extensions field of the structure.
182     */
183    public Extensions getExtensions() {
184        return extensions;
185    }
186
187    /**
188     * Returns ASN.1 encoded form of this X.509 TBSCertificate value.
189     */
190    public byte[] getEncoded() {
191        if (encoding == null) {
192            encoding = ASN1.encode(this);
193        }
194        return encoding;
195    }
196
197    public void dumpValue(StringBuilder sb) {
198        sb.append('[');
199        sb.append("\n  Version: V").append(version+1);
200        sb.append("\n  Subject: ").append(subject.getName(X500Principal.RFC2253));
201        sb.append("\n  Signature Algorithm: ");
202        signature.dumpValue(sb);
203        sb.append("\n  Key: ").append(subjectPublicKeyInfo.getPublicKey().toString());
204        sb.append("\n  Validity: [From: ").append(validity.getNotBefore());
205        sb.append("\n               To: ").append(validity.getNotAfter()).append(']');
206        sb.append("\n  Issuer: ").append(issuer.getName(X500Principal.RFC2253));
207        sb.append("\n  Serial Number: ").append(serialNumber);
208        if (issuerUniqueID != null) {
209            sb.append("\n  Issuer Id: ");
210            for (boolean b : issuerUniqueID) {
211                sb.append(b ? '1' : '0');
212            }
213        }
214        if (subjectUniqueID != null) {
215            sb.append("\n  Subject Id: ");
216            for (boolean b : subjectUniqueID) {
217                sb.append(b ? '1' : '0');
218            }
219        }
220        if (extensions != null) {
221            sb.append("\n\n  Extensions: ");
222            sb.append("[\n");
223            extensions.dumpValue(sb, "    ");
224            sb.append("  ]");
225        }
226        sb.append("\n]");
227    }
228
229    /**
230     * X.509 TBSCertificate encoder/decoder.
231     */
232    public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] {
233            new ASN1Explicit(0, ASN1Integer.getInstance()), ASN1Integer.getInstance(),
234            AlgorithmIdentifier.ASN1, Name.ASN1,
235            Validity.ASN1, Name.ASN1, SubjectPublicKeyInfo.ASN1,
236            new ASN1Implicit(1, ASN1BitString.getInstance()),
237            new ASN1Implicit(2, ASN1BitString.getInstance()),
238            new ASN1Explicit(3, Extensions.ASN1)}) {
239        {
240            setDefault(new byte[] {0}, 0);
241            setOptional(7);
242            setOptional(8);
243            setOptional(9);
244        }
245
246        @Override protected Object getDecodedObject(BerInputStream in) {
247            Object[] values = (Object[]) in.content;
248
249            boolean[] issuerUniqueID = (values[7] == null)
250                ? null : ((BitString) values[7]).toBooleanArray();
251            boolean[] subjectUniqueID = (values[8] == null)
252                ? null : ((BitString) values[8]).toBooleanArray();
253            return new TBSCertificate(
254                        ASN1Integer.toIntValue(values[0]),
255                        new BigInteger((byte[]) values[1]),
256                        (AlgorithmIdentifier) values[2],
257                        (Name) values[3],
258                        (Validity) values[4],
259                        (Name) values[5],
260                        (SubjectPublicKeyInfo) values[6],
261                        issuerUniqueID,
262                        subjectUniqueID,
263                        (Extensions) values[9],
264                        in.getEncoded()
265                    );
266        }
267
268        @Override protected void getValues(Object object, Object[] values) {
269            TBSCertificate tbs = (TBSCertificate) object;
270            values[0] = ASN1Integer.fromIntValue(tbs.version);
271            values[1] = tbs.serialNumber.toByteArray();
272            values[2] = tbs.signature;
273            values[3] = tbs.issuer;
274            values[4] = tbs.validity;
275            values[5] = tbs.subject;
276            values[6] = tbs.subjectPublicKeyInfo;
277            if (tbs.issuerUniqueID != null) {
278                values[7] = new BitString(tbs.issuerUniqueID);
279            }
280            if (tbs.subjectUniqueID != null) {
281                values[8] = new BitString(tbs.subjectUniqueID);
282            }
283            values[9] = tbs.extensions;
284        }
285    };
286}
287