1 /*
2  * Copyright (c) 2003, 2013, 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.timestamp;
27 
28 import java.io.IOException;
29 import java.math.BigInteger;
30 import java.util.Date;
31 import sun.security.util.DerValue;
32 import sun.security.util.ObjectIdentifier;
33 import sun.security.x509.AlgorithmId;
34 
35 /**
36  * This class provides the timestamp token info resulting from a successful
37  * timestamp request, as defined in
38  * <a href="http://www.ietf.org/rfc/rfc3161.txt">RFC 3161</a>.
39  *
40  * The timestampTokenInfo ASN.1 type has the following definition:
41  * <pre>
42  *
43  *     TSTInfo ::= SEQUENCE {
44  *         version                INTEGER  { v1(1) },
45  *         policy                 TSAPolicyId,
46  *         messageImprint         MessageImprint,
47  *           -- MUST have the same value as the similar field in
48  *           -- TimeStampReq
49  *         serialNumber           INTEGER,
50  *          -- Time-Stamping users MUST be ready to accommodate integers
51  *          -- up to 160 bits.
52  *         genTime                GeneralizedTime,
53  *         accuracy               Accuracy                 OPTIONAL,
54  *         ordering               BOOLEAN             DEFAULT FALSE,
55  *         nonce                  INTEGER                  OPTIONAL,
56  *           -- MUST be present if the similar field was present
57  *           -- in TimeStampReq.  In that case it MUST have the same value.
58  *         tsa                    [0] GeneralName          OPTIONAL,
59  *         extensions             [1] IMPLICIT Extensions  OPTIONAL }
60  *
61  *     Accuracy ::= SEQUENCE {
62  *         seconds        INTEGER           OPTIONAL,
63  *         millis     [0] INTEGER  (1..999) OPTIONAL,
64  *         micros     [1] INTEGER  (1..999) OPTIONAL  }
65  *
66  * </pre>
67  *
68  * @since 1.5
69  * @see Timestamper
70  * @author Vincent Ryan
71  */
72 
73 public class TimestampToken {
74 
75     private int version;
76     private ObjectIdentifier policy;
77     private BigInteger serialNumber;
78     private AlgorithmId hashAlgorithm;
79     private byte[] hashedMessage;
80     private Date genTime;
81     private BigInteger nonce;
82 
83     /**
84      * Constructs an object to store a timestamp token.
85      *
86      * @param status A buffer containing the ASN.1 BER encoding of the
87      *               TSTInfo element defined in RFC 3161.
88      */
TimestampToken(byte[] timestampTokenInfo)89     public TimestampToken(byte[] timestampTokenInfo) throws IOException {
90         if (timestampTokenInfo == null) {
91             throw new IOException("No timestamp token info");
92         }
93         parse(timestampTokenInfo);
94     }
95 
96     /**
97      * Extract the date and time from the timestamp token.
98      *
99      * @return The date and time when the timestamp was generated.
100      */
getDate()101     public Date getDate() {
102         return genTime;
103     }
104 
getHashAlgorithm()105     public AlgorithmId getHashAlgorithm() {
106         return hashAlgorithm;
107     }
108 
109     // should only be used internally, otherwise return a clone
getHashedMessage()110     public byte[] getHashedMessage() {
111         return hashedMessage;
112     }
113 
getNonce()114     public BigInteger getNonce() {
115         return nonce;
116     }
117 
getPolicyID()118     public String getPolicyID() {
119         return policy.toString();
120     }
121 
getSerialNumber()122     public BigInteger getSerialNumber() {
123         return serialNumber;
124     }
125 
126     /*
127      * Parses the timestamp token info.
128      *
129      * @param timestampTokenInfo A buffer containing an ASN.1 BER encoded
130      *                           TSTInfo.
131      * @throws IOException The exception is thrown if a problem is encountered
132      *         while parsing.
133      */
parse(byte[] timestampTokenInfo)134     private void parse(byte[] timestampTokenInfo) throws IOException {
135 
136         DerValue tstInfo = new DerValue(timestampTokenInfo);
137         if (tstInfo.tag != DerValue.tag_Sequence) {
138             throw new IOException("Bad encoding for timestamp token info");
139         }
140         // Parse version
141         version = tstInfo.data.getInteger();
142 
143         // Parse policy
144         policy = tstInfo.data.getOID();
145 
146         // Parse messageImprint
147         DerValue messageImprint = tstInfo.data.getDerValue();
148         hashAlgorithm = AlgorithmId.parse(messageImprint.data.getDerValue());
149         hashedMessage = messageImprint.data.getOctetString();
150 
151         // Parse serialNumber
152         serialNumber = tstInfo.data.getBigInteger();
153 
154         // Parse genTime
155         genTime = tstInfo.data.getGeneralizedTime();
156 
157         // Parse optional elements, if present
158         while (tstInfo.data.available() > 0) {
159             DerValue d = tstInfo.data.getDerValue();
160             if (d.tag == DerValue.tag_Integer) {    // must be the nonce
161                 nonce = d.getBigInteger();
162                 break;
163             }
164 
165             // Additional fields:
166             // Parse accuracy
167             // Parse ordering
168             // Parse tsa
169             // Parse extensions
170         }
171     }
172 }
173