/*
 * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.security.timestamp;

import java.io.IOException;
import sun.security.pkcs.PKCS7;
import sun.security.util.Debug;
import sun.security.util.DerValue;

This class provides the response corresponding to a timestamp request, as defined in RFC 3161. The TimeStampResp ASN.1 type has the following definition:
    TimeStampResp ::= SEQUENCE {
        status            PKIStatusInfo,
        timeStampToken    TimeStampToken OPTIONAL ]
    PKIStatusInfo ::= SEQUENCE {
        status        PKIStatus,
        statusString  PKIFreeText OPTIONAL,
        failInfo      PKIFailureInfo OPTIONAL }
    PKIStatus ::= INTEGER {
        granted                (0),
          -- when the PKIStatus contains the value zero a TimeStampToken, as
          -- requested, is present.
        grantedWithMods        (1),
          -- when the PKIStatus contains the value one a TimeStampToken,
          -- with modifications, is present.
        rejection              (2),
        waiting                (3),
        revocationWarning      (4),
          -- this message contains a warning that a revocation is
          -- imminent
        revocationNotification (5)
          -- notification that a revocation has occurred }
    PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
          -- text encoded as UTF-8 String (note:  each UTF8String SHOULD
          -- include an RFC 1766 language tag to indicate the language
          -- of the contained text)
    PKIFailureInfo ::= BIT STRING {
        badAlg              (0),
          -- unrecognized or unsupported Algorithm Identifier
        badRequest          (2),
          -- transaction not permitted or supported
        badDataFormat       (5),
          -- the data submitted has the wrong format
        timeNotAvailable    (14),
          -- the TSA's time source is not available
        unacceptedPolicy    (15),
          -- the requested TSA policy is not supported by the TSA
        unacceptedExtension (16),
          -- the requested extension is not supported by the TSA
        addInfoNotAvailable (17)
          -- the additional information requested could not be understood
          -- or is not available
        systemFailure       (25)
          -- the request cannot be handled due to system failure }
    TimeStampToken ::= ContentInfo
        -- contentType is id-signedData
        -- content is SignedData
        -- eContentType within SignedData is id-ct-TSTInfo
        -- eContent within SignedData is TSTInfo
Author:Vincent Ryan
See Also:
Since:1.5
/** * This class provides the response corresponding to a timestamp request, * as defined in * <a href="http://www.ietf.org/rfc/rfc3161.txt">RFC 3161</a>. * * The TimeStampResp ASN.1 type has the following definition: * <pre> * * TimeStampResp ::= SEQUENCE { * status PKIStatusInfo, * timeStampToken TimeStampToken OPTIONAL ] * * PKIStatusInfo ::= SEQUENCE { * status PKIStatus, * statusString PKIFreeText OPTIONAL, * failInfo PKIFailureInfo OPTIONAL } * * PKIStatus ::= INTEGER { * granted (0), * -- when the PKIStatus contains the value zero a TimeStampToken, as * -- requested, is present. * grantedWithMods (1), * -- when the PKIStatus contains the value one a TimeStampToken, * -- with modifications, is present. * rejection (2), * waiting (3), * revocationWarning (4), * -- this message contains a warning that a revocation is * -- imminent * revocationNotification (5) * -- notification that a revocation has occurred } * * PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String * -- text encoded as UTF-8 String (note: each UTF8String SHOULD * -- include an RFC 1766 language tag to indicate the language * -- of the contained text) * * PKIFailureInfo ::= BIT STRING { * badAlg (0), * -- unrecognized or unsupported Algorithm Identifier * badRequest (2), * -- transaction not permitted or supported * badDataFormat (5), * -- the data submitted has the wrong format * timeNotAvailable (14), * -- the TSA's time source is not available * unacceptedPolicy (15), * -- the requested TSA policy is not supported by the TSA * unacceptedExtension (16), * -- the requested extension is not supported by the TSA * addInfoNotAvailable (17) * -- the additional information requested could not be understood * -- or is not available * systemFailure (25) * -- the request cannot be handled due to system failure } * * TimeStampToken ::= ContentInfo * -- contentType is id-signedData * -- content is SignedData * -- eContentType within SignedData is id-ct-TSTInfo * -- eContent within SignedData is TSTInfo * * </pre> * * @since 1.5 * @author Vincent Ryan * @see Timestamper */
public class TSResponse { // Status codes (from RFC 3161)
The requested timestamp was granted.
/** * The requested timestamp was granted. */
public static final int GRANTED = 0;
The requested timestamp was granted with some modifications.
/** * The requested timestamp was granted with some modifications. */
public static final int GRANTED_WITH_MODS = 1;
The requested timestamp was not granted.
/** * The requested timestamp was not granted. */
public static final int REJECTION = 2;
The requested timestamp has not yet been processed.
/** * The requested timestamp has not yet been processed. */
public static final int WAITING = 3;
A warning that a certificate revocation is imminent.
/** * A warning that a certificate revocation is imminent. */
public static final int REVOCATION_WARNING = 4;
Notification that a certificate revocation has occurred.
/** * Notification that a certificate revocation has occurred. */
public static final int REVOCATION_NOTIFICATION = 5; // Failure codes (from RFC 3161)
Unrecognized or unsupported algorithm identifier.
/** * Unrecognized or unsupported algorithm identifier. */
public static final int BAD_ALG = 0;
The requested transaction is not permitted or supported.
/** * The requested transaction is not permitted or supported. */
public static final int BAD_REQUEST = 2;
The data submitted has the wrong format.
/** * The data submitted has the wrong format. */
public static final int BAD_DATA_FORMAT = 5;
The TSA's time source is not available.
/** * The TSA's time source is not available. */
public static final int TIME_NOT_AVAILABLE = 14;
The requested TSA policy is not supported by the TSA.
/** * The requested TSA policy is not supported by the TSA. */
public static final int UNACCEPTED_POLICY = 15;
The requested extension is not supported by the TSA.
/** * The requested extension is not supported by the TSA. */
public static final int UNACCEPTED_EXTENSION = 16;
The additional information requested could not be understood or is not available.
/** * The additional information requested could not be understood or is not * available. */
public static final int ADD_INFO_NOT_AVAILABLE = 17;
The request cannot be handled due to system failure.
/** * The request cannot be handled due to system failure. */
public static final int SYSTEM_FAILURE = 25; private static final Debug debug = Debug.getInstance("ts"); private int status; private String[] statusString = null; private boolean[] failureInfo = null; private byte[] encodedTsToken = null; private PKCS7 tsToken = null; private TimestampToken tstInfo;
Constructs an object to store the response to a timestamp request.
Params:
  • status – A buffer containing the ASN.1 BER encoded response.
Throws:
  • IOException – The exception is thrown if a problem is encountered parsing the timestamp response.
/** * Constructs an object to store the response to a timestamp request. * * @param status A buffer containing the ASN.1 BER encoded response. * @throws IOException The exception is thrown if a problem is encountered * parsing the timestamp response. */
TSResponse(byte[] tsReply) throws IOException { parse(tsReply); }
Retrieve the status code returned by the TSA.
/** * Retrieve the status code returned by the TSA. */
public int getStatusCode() { return status; }
Retrieve the status messages returned by the TSA.
Returns:If null then no status messages were received.
/** * Retrieve the status messages returned by the TSA. * * @return If null then no status messages were received. */
public String[] getStatusMessages() { return statusString; }
Retrieve the failure info returned by the TSA.
Returns:the failure info, or null if no failure code was received.
/** * Retrieve the failure info returned by the TSA. * * @return the failure info, or null if no failure code was received. */
public boolean[] getFailureInfo() { return failureInfo; } public String getStatusCodeAsText() { switch (status) { case GRANTED: return "the timestamp request was granted."; case GRANTED_WITH_MODS: return "the timestamp request was granted with some modifications."; case REJECTION: return "the timestamp request was rejected."; case WAITING: return "the timestamp request has not yet been processed."; case REVOCATION_WARNING: return "warning: a certificate revocation is imminent."; case REVOCATION_NOTIFICATION: return "notification: a certificate revocation has occurred."; default: return ("unknown status code " + status + "."); } } private boolean isSet(int position) { return failureInfo[position]; } public String getFailureCodeAsText() { if (failureInfo == null) { return ""; } try { if (isSet(BAD_ALG)) return "Unrecognized or unsupported algorithm identifier."; if (isSet(BAD_REQUEST)) return "The requested transaction is not permitted or " + "supported."; if (isSet(BAD_DATA_FORMAT)) return "The data submitted has the wrong format."; if (isSet(TIME_NOT_AVAILABLE)) return "The TSA's time source is not available."; if (isSet(UNACCEPTED_POLICY)) return "The requested TSA policy is not supported by the TSA."; if (isSet(UNACCEPTED_EXTENSION)) return "The requested extension is not supported by the TSA."; if (isSet(ADD_INFO_NOT_AVAILABLE)) return "The additional information requested could not be " + "understood or is not available."; if (isSet(SYSTEM_FAILURE)) return "The request cannot be handled due to system failure."; } catch (ArrayIndexOutOfBoundsException ex) {} return ("unknown failure code"); }
Retrieve the timestamp token returned by the TSA.
Returns:If null then no token was received.
/** * Retrieve the timestamp token returned by the TSA. * * @return If null then no token was received. */
public PKCS7 getToken() { return tsToken; } public TimestampToken getTimestampToken() { return tstInfo; }
Retrieve the ASN.1 BER encoded timestamp token returned by the TSA.
Returns:If null then no token was received.
/** * Retrieve the ASN.1 BER encoded timestamp token returned by the TSA. * * @return If null then no token was received. */
public byte[] getEncodedToken() { return encodedTsToken; } /* * Parses the timestamp response. * * @param status A buffer containing the ASN.1 BER encoded response. * @throws IOException The exception is thrown if a problem is encountered * parsing the timestamp response. */ private void parse(byte[] tsReply) throws IOException { // Decode TimeStampResp DerValue derValue = new DerValue(tsReply); if (derValue.tag != DerValue.tag_Sequence) { throw new IOException("Bad encoding for timestamp response"); } // Parse status DerValue statusInfo = derValue.data.getDerValue(); this.status = statusInfo.data.getInteger(); if (debug != null) { debug.println("timestamp response: status=" + this.status); } // Parse statusString, if present if (statusInfo.data.available() > 0) { byte tag = (byte)statusInfo.data.peekByte(); if (tag == DerValue.tag_SequenceOf) { DerValue[] strings = statusInfo.data.getSequence(1); statusString = new String[strings.length]; for (int i = 0; i < strings.length; i++) { statusString[i] = strings[i].getUTF8String(); if (debug != null) { debug.println("timestamp response: statusString=" + statusString[i]); } } } } // Parse failInfo, if present if (statusInfo.data.available() > 0) { this.failureInfo = statusInfo.data.getUnalignedBitString().toBooleanArray(); } // Parse timeStampToken, if present if (derValue.data.available() > 0) { DerValue timestampToken = derValue.data.getDerValue(); encodedTsToken = timestampToken.toByteArray(); tsToken = new PKCS7(encodedTsToken); tstInfo = new TimestampToken(tsToken.getContentInfo().getData()); } // Check the format of the timestamp response if (this.status == 0 || this.status == 1) { if (tsToken == null) { throw new TimestampException( "Bad encoding for timestamp response: " + "expected a timeStampToken element to be present"); } } else if (tsToken != null) { throw new TimestampException( "Bad encoding for timestamp response: " + "expected no timeStampToken element to be present"); } } static final class TimestampException extends IOException { @java.io.Serial private static final long serialVersionUID = -1631631794891940953L; TimestampException(String message) { super(message); } } }