Path: blob/master/src/java.base/share/classes/sun/security/timestamp/TSResponse.java
41159 views
/*1* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.timestamp;2627import java.io.IOException;28import sun.security.pkcs.PKCS7;29import sun.security.util.Debug;30import sun.security.util.DerValue;3132/**33* This class provides the response corresponding to a timestamp request,34* as defined in35* <a href="http://www.ietf.org/rfc/rfc3161.txt">RFC 3161</a>.36*37* The TimeStampResp ASN.1 type has the following definition:38* <pre>39*40* TimeStampResp ::= SEQUENCE {41* status PKIStatusInfo,42* timeStampToken TimeStampToken OPTIONAL ]43*44* PKIStatusInfo ::= SEQUENCE {45* status PKIStatus,46* statusString PKIFreeText OPTIONAL,47* failInfo PKIFailureInfo OPTIONAL }48*49* PKIStatus ::= INTEGER {50* granted (0),51* -- when the PKIStatus contains the value zero a TimeStampToken, as52* -- requested, is present.53* grantedWithMods (1),54* -- when the PKIStatus contains the value one a TimeStampToken,55* -- with modifications, is present.56* rejection (2),57* waiting (3),58* revocationWarning (4),59* -- this message contains a warning that a revocation is60* -- imminent61* revocationNotification (5)62* -- notification that a revocation has occurred }63*64* PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String65* -- text encoded as UTF-8 String (note: each UTF8String SHOULD66* -- include an RFC 1766 language tag to indicate the language67* -- of the contained text)68*69* PKIFailureInfo ::= BIT STRING {70* badAlg (0),71* -- unrecognized or unsupported Algorithm Identifier72* badRequest (2),73* -- transaction not permitted or supported74* badDataFormat (5),75* -- the data submitted has the wrong format76* timeNotAvailable (14),77* -- the TSA's time source is not available78* unacceptedPolicy (15),79* -- the requested TSA policy is not supported by the TSA80* unacceptedExtension (16),81* -- the requested extension is not supported by the TSA82* addInfoNotAvailable (17)83* -- the additional information requested could not be understood84* -- or is not available85* systemFailure (25)86* -- the request cannot be handled due to system failure }87*88* TimeStampToken ::= ContentInfo89* -- contentType is id-signedData90* -- content is SignedData91* -- eContentType within SignedData is id-ct-TSTInfo92* -- eContent within SignedData is TSTInfo93*94* </pre>95*96* @since 1.597* @author Vincent Ryan98* @see Timestamper99*/100101public class TSResponse {102103// Status codes (from RFC 3161)104105/**106* The requested timestamp was granted.107*/108public static final int GRANTED = 0;109110/**111* The requested timestamp was granted with some modifications.112*/113public static final int GRANTED_WITH_MODS = 1;114115/**116* The requested timestamp was not granted.117*/118public static final int REJECTION = 2;119120/**121* The requested timestamp has not yet been processed.122*/123public static final int WAITING = 3;124125/**126* A warning that a certificate revocation is imminent.127*/128public static final int REVOCATION_WARNING = 4;129130/**131* Notification that a certificate revocation has occurred.132*/133public static final int REVOCATION_NOTIFICATION = 5;134135// Failure codes (from RFC 3161)136137/**138* Unrecognized or unsupported algorithm identifier.139*/140public static final int BAD_ALG = 0;141142/**143* The requested transaction is not permitted or supported.144*/145public static final int BAD_REQUEST = 2;146147/**148* The data submitted has the wrong format.149*/150public static final int BAD_DATA_FORMAT = 5;151152/**153* The TSA's time source is not available.154*/155public static final int TIME_NOT_AVAILABLE = 14;156157/**158* The requested TSA policy is not supported by the TSA.159*/160public static final int UNACCEPTED_POLICY = 15;161162/**163* The requested extension is not supported by the TSA.164*/165public static final int UNACCEPTED_EXTENSION = 16;166167/**168* The additional information requested could not be understood or is not169* available.170*/171public static final int ADD_INFO_NOT_AVAILABLE = 17;172173/**174* The request cannot be handled due to system failure.175*/176public static final int SYSTEM_FAILURE = 25;177178private static final Debug debug = Debug.getInstance("ts");179180private int status;181182private String[] statusString = null;183184private boolean[] failureInfo = null;185186private byte[] encodedTsToken = null;187188private PKCS7 tsToken = null;189190private TimestampToken tstInfo;191192/**193* Constructs an object to store the response to a timestamp request.194*195* @param tsReply A buffer containing the ASN.1 BER encoded response.196* @throws IOException The exception is thrown if a problem is encountered197* parsing the timestamp response.198*/199TSResponse(byte[] tsReply) throws IOException {200parse(tsReply);201}202203/**204* Retrieve the status code returned by the TSA.205*/206public int getStatusCode() {207return status;208}209210/**211* Retrieve the status messages returned by the TSA.212*213* @return If null then no status messages were received.214*/215public String[] getStatusMessages() {216return statusString;217}218219/**220* Retrieve the failure info returned by the TSA.221*222* @return the failure info, or null if no failure code was received.223*/224public boolean[] getFailureInfo() {225return failureInfo;226}227228public String getStatusCodeAsText() {229230switch (status) {231case GRANTED:232return "the timestamp request was granted.";233234case GRANTED_WITH_MODS:235return236"the timestamp request was granted with some modifications.";237238case REJECTION:239return "the timestamp request was rejected.";240241case WAITING:242return "the timestamp request has not yet been processed.";243244case REVOCATION_WARNING:245return "warning: a certificate revocation is imminent.";246247case REVOCATION_NOTIFICATION:248return "notification: a certificate revocation has occurred.";249250default:251return ("unknown status code " + status + ".");252}253}254255private boolean isSet(int position) {256return failureInfo[position];257}258259public String getFailureCodeAsText() {260261if (failureInfo == null) {262return "";263}264265try {266if (isSet(BAD_ALG))267return "Unrecognized or unsupported algorithm identifier.";268if (isSet(BAD_REQUEST))269return "The requested transaction is not permitted or " +270"supported.";271if (isSet(BAD_DATA_FORMAT))272return "The data submitted has the wrong format.";273if (isSet(TIME_NOT_AVAILABLE))274return "The TSA's time source is not available.";275if (isSet(UNACCEPTED_POLICY))276return "The requested TSA policy is not supported by the TSA.";277if (isSet(UNACCEPTED_EXTENSION))278return "The requested extension is not supported by the TSA.";279if (isSet(ADD_INFO_NOT_AVAILABLE))280return "The additional information requested could not be " +281"understood or is not available.";282if (isSet(SYSTEM_FAILURE))283return "The request cannot be handled due to system failure.";284} catch (ArrayIndexOutOfBoundsException ex) {}285286return ("unknown failure code");287}288289/**290* Retrieve the timestamp token returned by the TSA.291*292* @return If null then no token was received.293*/294public PKCS7 getToken() {295return tsToken;296}297298public TimestampToken getTimestampToken() {299return tstInfo;300}301302/**303* Retrieve the ASN.1 BER encoded timestamp token returned by the TSA.304*305* @return If null then no token was received.306*/307public byte[] getEncodedToken() {308return encodedTsToken;309}310311/*312* Parses the timestamp response.313*314* @param status A buffer containing the ASN.1 BER encoded response.315* @throws IOException The exception is thrown if a problem is encountered316* parsing the timestamp response.317*/318private void parse(byte[] tsReply) throws IOException {319// Decode TimeStampResp320321DerValue derValue = new DerValue(tsReply);322if (derValue.tag != DerValue.tag_Sequence) {323throw new IOException("Bad encoding for timestamp response");324}325326// Parse status327328DerValue statusInfo = derValue.data.getDerValue();329this.status = statusInfo.data.getInteger();330if (debug != null) {331debug.println("timestamp response: status=" + this.status);332}333// Parse statusString, if present334if (statusInfo.data.available() > 0) {335byte tag = (byte)statusInfo.data.peekByte();336if (tag == DerValue.tag_SequenceOf) {337DerValue[] strings = statusInfo.data.getSequence(1);338statusString = new String[strings.length];339for (int i = 0; i < strings.length; i++) {340statusString[i] = strings[i].getUTF8String();341if (debug != null) {342debug.println("timestamp response: statusString=" +343statusString[i]);344}345}346}347}348// Parse failInfo, if present349if (statusInfo.data.available() > 0) {350this.failureInfo351= statusInfo.data.getUnalignedBitString().toBooleanArray();352}353354// Parse timeStampToken, if present355if (derValue.data.available() > 0) {356DerValue timestampToken = derValue.data.getDerValue();357encodedTsToken = timestampToken.toByteArray();358tsToken = new PKCS7(encodedTsToken);359tstInfo = new TimestampToken(tsToken.getContentInfo().getData());360}361362// Check the format of the timestamp response363if (this.status == 0 || this.status == 1) {364if (tsToken == null) {365throw new TimestampException(366"Bad encoding for timestamp response: " +367"expected a timeStampToken element to be present");368}369} else if (tsToken != null) {370throw new TimestampException(371"Bad encoding for timestamp response: " +372"expected no timeStampToken element to be present");373}374}375376static final class TimestampException extends IOException {377@java.io.Serial378private static final long serialVersionUID = -1631631794891940953L;379380TimestampException(String message) {381super(message);382}383}384}385386387