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      */
  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      */
 101     public Date getDate() {
 102         return genTime;
 103     }
 104 
 105     public AlgorithmId getHashAlgorithm() {
 106         return hashAlgorithm;
 107     }
 108 
 109     // should only be used internally, otherwise return a clone
 110     public byte[] getHashedMessage() {
 111         return hashedMessage;
 112     }
 113 
 114     public BigInteger getNonce() {
 115         return nonce;
 116     }
 117 
 118     public BigInteger getSerialNumber() {
 119         return serialNumber;
 120     }
 121 
 122     public String getPolicyID() {
 123         return policy.toString();
 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      */
 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 }