/*
 * Copyright 2003-2006 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.security.provider.certpath;

import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CRLReason;
import java.security.cert.X509Certificate;
import java.security.cert.PKIXParameters;
import javax.security.auth.x500.X500Principal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;
import sun.misc.HexDumpEncoder;
import sun.security.x509.*;
import sun.security.util.*;

/**
 * This class is used to process an OCSP response.
 * The OCSP Response is defined
 * in RFC 2560 and the ASN.1 encoding is as follows:
 * <pre>
 *
 *  OCSPResponse ::= SEQUENCE {
 *      responseStatus         OCSPResponseStatus,
 *      responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
 *
 *   OCSPResponseStatus ::= ENUMERATED {
 *       successful            (0),  --Response has valid confirmations
 *       malformedRequest      (1),  --Illegal confirmation request
 *       internalError         (2),  --Internal error in issuer
 *       tryLater              (3),  --Try again later
 *                                   --(4) is not used
 *       sigRequired           (5),  --Must sign the request
 *       unauthorized          (6)   --Request unauthorized
 *   }
 *
 *   ResponseBytes ::=       SEQUENCE {
 *       responseType   OBJECT IDENTIFIER,
 *       response       OCTET STRING }
 *
 *   BasicOCSPResponse       ::= SEQUENCE {
 *      tbsResponseData      ResponseData,
 *      signatureAlgorithm   AlgorithmIdentifier,
 *      signature            BIT STRING,
 *      certs                [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
 *
 *   The value for signature SHALL be computed on the hash of the DER
 *   encoding ResponseData.
 *
 *   ResponseData ::= SEQUENCE {
 *      version              [0] EXPLICIT Version DEFAULT v1,
 *      responderID              ResponderID,
 *      producedAt               GeneralizedTime,
 *      responses                SEQUENCE OF SingleResponse,
 *      responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
 *
 *   ResponderID ::= CHOICE {
 *      byName               [1] Name,
 *      byKey                [2] KeyHash }
 *
 *   KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
 *   (excluding the tag and length fields)
 *
 *   SingleResponse ::= SEQUENCE {
 *      certID                       CertID,
 *      certStatus                   CertStatus,
 *      thisUpdate                   GeneralizedTime,
 *      nextUpdate         [0]       EXPLICIT GeneralizedTime OPTIONAL,
 *      singleExtensions   [1]       EXPLICIT Extensions OPTIONAL }
 *
 *   CertStatus ::= CHOICE {
 *       good        [0]     IMPLICIT NULL,
 *       revoked     [1]     IMPLICIT RevokedInfo,
 *       unknown     [2]     IMPLICIT UnknownInfo }
 *
 *   RevokedInfo ::= SEQUENCE {
 *       revocationTime              GeneralizedTime,
 *       revocationReason    [0]     EXPLICIT CRLReason OPTIONAL }
 *
 *   UnknownInfo ::= NULL -- this can be replaced with an enumeration
 *
 * </pre>
 *
 * @author      Ram Marti
 */

class OCSPResponse {

    // Certificate status CHOICE
    public static final int CERT_STATUS_GOOD = 0;
    public static final int CERT_STATUS_REVOKED = 1;
    public static final int CERT_STATUS_UNKNOWN = 2;

    private static final Debug DEBUG = Debug.getInstance("certpath");
    private static final boolean dump = false;
    private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID;
    private static final ObjectIdentifier OCSP_NONCE_EXTENSION_OID;
    static {
        ObjectIdentifier tmp1 = null;
        ObjectIdentifier tmp2 = null;
        try {
            tmp1 = new ObjectIdentifier("1.3.6.1.5.5.7.48.1.1");
            tmp2 = new ObjectIdentifier("1.3.6.1.5.5.7.48.1.2");
        } catch (Exception e) {
            // should not happen; log and exit
        }
        OCSP_BASIC_RESPONSE_OID = tmp1;
        OCSP_NONCE_EXTENSION_OID = tmp2;
    }

    // OCSP response status code
    private static final int OCSP_RESPONSE_OK = 0;

    // ResponderID CHOICE tags
    private static final int NAME_TAG = 1;
    private static final int KEY_TAG = 2;

    // Object identifier for the OCSPSigning key purpose
    private static final String KP_OCSP_SIGNING_OID = "1.3.6.1.5.5.7.3.9";

    private SingleResponse singleResponse;

    // an array of all of the CRLReasons (used in SingleResponse)
    private static CRLReason[] values = CRLReason.values();

    /*
     * Create an OCSP response from its ASN.1 DER encoding.
     */
    // used by OCSPChecker
    OCSPResponse(byte[] bytes, PKIXParameters params,
        X509Certificate responderCert)
        throws IOException, CertPathValidatorException {

        try {
            int responseStatus;
            ObjectIdentifier  responseType;
            int version;
            CertificateIssuerName responderName = null;
            Date producedAtDate;
            AlgorithmId sigAlgId;
            byte[] ocspNonce;

            // OCSPResponse
            if (dump) {
                HexDumpEncoder hexEnc = new HexDumpEncoder();
                System.out.println("OCSPResponse bytes are...");
                System.out.println(hexEnc.encode(bytes));
            }
            DerValue der = new DerValue(bytes);
            if (der.tag != DerValue.tag_Sequence) {
                throw new IOException("Bad encoding in OCSP response: " +
                    "expected ASN.1 SEQUENCE tag.");
            }
            DerInputStream derIn = der.getData();

            // responseStatus
            responseStatus = derIn.getEnumerated();
            if (DEBUG != null) {
                DEBUG.println("OCSP response: " +
                    responseToText(responseStatus));
            }
            if (responseStatus != OCSP_RESPONSE_OK) {
                throw new CertPathValidatorException(
                    "OCSP Response Failure: " +
                        responseToText(responseStatus));
            }

            // responseBytes
            der = derIn.getDerValue();
            if (! der.isContextSpecific((byte)0)) {
                throw new IOException("Bad encoding in responseBytes element " +
                    "of OCSP response: expected ASN.1 context specific tag 0.");
            };
            DerValue tmp = der.data.getDerValue();
            if (tmp.tag != DerValue.tag_Sequence) {
                throw new IOException("Bad encoding in responseBytes element " +
                    "of OCSP response: expected ASN.1 SEQUENCE tag.");
            }

            // responseType
            derIn = tmp.data;
            responseType = derIn.getOID();
            if (responseType.equals(OCSP_BASIC_RESPONSE_OID)) {
                if (DEBUG != null) {
                    DEBUG.println("OCSP response type: basic");
                }
            } else {
                if (DEBUG != null) {
                    DEBUG.println("OCSP response type: " + responseType);
                }
                throw new IOException("Unsupported OCSP response type: " +
                    responseType);
            }

            // BasicOCSPResponse
            DerInputStream basicOCSPResponse =
                new DerInputStream(derIn.getOctetString());

            DerValue[]  seqTmp = basicOCSPResponse.getSequence(2);
            DerValue responseData = seqTmp[0];

            // Need the DER encoded ResponseData to verify the signature later
            byte[] responseDataDer = seqTmp[0].toByteArray();

            // tbsResponseData
            if (responseData.tag != DerValue.tag_Sequence) {
                throw new IOException("Bad encoding in tbsResponseData " +
                    " element of OCSP response: expected ASN.1 SEQUENCE tag.");
            }
            DerInputStream seqDerIn = responseData.data;
            DerValue seq = seqDerIn.getDerValue();

            // version
            if (seq.isContextSpecific((byte)0)) {
                // seq[0] is version
                if (seq.isConstructed() && seq.isContextSpecific()) {
                    //System.out.println ("version is available");
                    seq = seq.data.getDerValue();
                    version = seq.getInteger();
                    if (seq.data.available() != 0) {
                        throw new IOException("Bad encoding in version " +
                            " element of OCSP response: bad format");
                    }
                    seq = seqDerIn.getDerValue();
                }
            }

            // responderID
            short tag = (byte)(seq.tag & 0x1f);
            if (tag == NAME_TAG) {
                responderName = new CertificateIssuerName(seq.getData());
                if (DEBUG != null) {
                    DEBUG.println("OCSP Responder name: " + responderName);
                }
            } else if (tag == KEY_TAG) {
                // Ignore, for now
            } else {
                throw new IOException("Bad encoding in responderID element " +
                    "of OCSP response: expected ASN.1 context specific tag 0 " +
                    "or 1");
            }

            // producedAt
            seq = seqDerIn.getDerValue();
            producedAtDate = seq.getGeneralizedTime();

            // responses
            DerValue[] singleResponseDer = seqDerIn.getSequence(1);
            // Examine only the first response
            singleResponse = new SingleResponse(singleResponseDer[0]);

            // responseExtensions
            if (seqDerIn.available() > 0) {
                seq = seqDerIn.getDerValue();
                if (seq.isContextSpecific((byte)1)) {
                    DerValue[]  responseExtDer = seq.data.getSequence(3);
                    Extension[] responseExtension =
                        new Extension[responseExtDer.length];
                    for (int i = 0; i < responseExtDer.length; i++) {
                        responseExtension[i] = new Extension(responseExtDer[i]);
                        if (DEBUG != null) {
                            DEBUG.println("OCSP extension: " +
                                responseExtension[i]);
                        }
                        if ((responseExtension[i].getExtensionId()).equals(
                            OCSP_NONCE_EXTENSION_OID)) {
                            ocspNonce =
                                responseExtension[i].getExtensionValue();

                        } else if (responseExtension[i].isCritical())  {
                            throw new IOException(
                                "Unsupported OCSP critical extension: " +
                                responseExtension[i].getExtensionId());
                        }
                    }
                }
            }

            // signatureAlgorithmId
            sigAlgId = AlgorithmId.parse(seqTmp[1]);

            // signature
            byte[] signature = seqTmp[2].getBitString();
            X509CertImpl[] x509Certs = null;

            // if seq[3] is available , then it is a sequence of certificates
            if (seqTmp.length > 3) {
                // certs are available
                DerValue seqCert = seqTmp[3];
                if (! seqCert.isContextSpecific((byte)0)) {
                    throw new IOException("Bad encoding in certs element " +
                    "of OCSP response: expected ASN.1 context specific tag 0.");
                }
                DerValue[] certs = (seqCert.getData()).getSequence(3);
                x509Certs = new X509CertImpl[certs.length];
                for (int i = 0; i < certs.length; i++) {
                    x509Certs[i] = new X509CertImpl(certs[i].toByteArray());
                }
            }

            // Check whether the cert returned by the responder is trusted
            if (x509Certs != null && x509Certs[0] != null) {
                X509Certificate cert = x509Certs[0];

                // First check if the cert matches the responder cert which
                // was set locally.
                if (cert.equals(responderCert)) {
                    // cert is trusted, now verify the signed response

                // Next check if the cert was issued by the responder cert
                // which was set locally.
                } else if (cert.getIssuerDN().equals(
                    responderCert.getSubjectDN())) {

                    // Check for the OCSPSigning key purpose
                    List<String> keyPurposes = cert.getExtendedKeyUsage();
                    if (keyPurposes == null ||
                        !keyPurposes.contains(KP_OCSP_SIGNING_OID)) {
                        if (DEBUG != null) {
                            DEBUG.println("Responder's certificate is not " +
                                "valid for signing OCSP responses.");
                        }
                        throw new CertPathValidatorException(
                            "Responder's certificate not valid for signing " +
                            "OCSP responses");
                    }

                    // verify the signature
                    try {
                        cert.verify(responderCert.getPublicKey());
                        responderCert = cert;
                        // cert is trusted, now verify the signed response

                    } catch (GeneralSecurityException e) {
                        responderCert = null;
                    }
                }
            }

            // Confirm that the signed response was generated using the public
            // key from the trusted responder cert
            if (responderCert != null) {

                if (! verifyResponse(responseDataDer, responderCert,
                    sigAlgId, signature, params)) {
                    if (DEBUG != null) {
                        DEBUG.println("Error verifying OCSP Responder's " +
                            "signature");
                    }
                    throw new CertPathValidatorException(
                        "Error verifying OCSP Responder's signature");
                }
            } else {
                // Need responder's cert in order to verify the signature
                if (DEBUG != null) {
                    DEBUG.println("Unable to verify OCSP Responder's " +
                        "signature");
                }
                throw new CertPathValidatorException(
                    "Unable to verify OCSP Responder's signature");
            }
        } catch (CertPathValidatorException cpve) {
            throw cpve;
        } catch (Exception e) {
            throw new CertPathValidatorException(e);
        }
    }

    /*
     * Verify the signature of the OCSP response.
     * The responder's cert is implicitly trusted.
     */
    private boolean verifyResponse(byte[] responseData, X509Certificate cert,
        AlgorithmId sigAlgId, byte[] signBytes, PKIXParameters params)
        throws SignatureException {

        try {

            Signature respSignature = Signature.getInstance(sigAlgId.getName());
            respSignature.initVerify(cert);
            respSignature.update(responseData);

            if (respSignature.verify(signBytes)) {
                if (DEBUG != null) {
                    DEBUG.println("Verified signature of OCSP Responder");
                }
                return true;

            } else {
                if (DEBUG != null) {
                    DEBUG.println(
                        "Error verifying signature of OCSP Responder");
                }
                return false;
            }
        } catch (InvalidKeyException ike) {
            throw new SignatureException(ike);

        } catch (NoSuchAlgorithmException nsae) {
            throw new SignatureException(nsae);
        }
    }

    /*
     * Return the revocation status code for a given certificate.
     */
    // used by OCSPChecker
    int getCertStatus(SerialNumber sn) {
        // ignore serial number for now; if we support multiple
        // requests/responses then it will be used
        return singleResponse.getStatus();
    }

    // used by OCSPChecker
    CertId getCertId() {
        return singleResponse.getCertId();
    }

    Date getRevocationTime() {
        return singleResponse.getRevocationTime();
    }

    CRLReason getRevocationReason() {
        return singleResponse.getRevocationReason();
    }

    Map<String, java.security.cert.Extension> getSingleExtensions() {
        return singleResponse.getSingleExtensions();
    }

    /*
     * Map an OCSP response status code to a string.
     */
    static private String responseToText(int status) {
        switch (status)  {
        case 0:
            return "Successful";
        case 1:
            return "Malformed request";
        case 2:
            return "Internal error";
        case 3:
            return "Try again later";
        case 4:
            return "Unused status code";
        case 5:
            return "Request must be signed";
        case 6:
            return "Request is unauthorized";
        default:
            return ("Unknown status code: " + status);
        }
    }

    /*
     * Map a certificate's revocation status code to a string.
     */
    // used by OCSPChecker
    static String certStatusToText(int certStatus) {
        switch (certStatus)  {
        case 0:
            return "Good";
        case 1:
            return "Revoked";
        case 2:
            return "Unknown";
        default:
            return ("Unknown certificate status code: " + certStatus);
        }
    }

    /*
     * A class representing a single OCSP response.
     */
    private class SingleResponse {
        private CertId certId;
        private int certStatus;
        private Date thisUpdate;
        private Date nextUpdate;
        private Date revocationTime;
        private CRLReason revocationReason = CRLReason.UNSPECIFIED;
        private HashMap<String, java.security.cert.Extension> singleExtensions;

        private SingleResponse(DerValue der) throws IOException {
            if (der.tag != DerValue.tag_Sequence) {
                throw new IOException("Bad ASN.1 encoding in SingleResponse");
            }
            DerInputStream tmp = der.data;

            certId = new CertId(tmp.getDerValue().data);
            DerValue derVal = tmp.getDerValue();
            short tag = (byte)(derVal.tag & 0x1f);
            if (tag ==  CERT_STATUS_GOOD) {
                certStatus = CERT_STATUS_GOOD;
            } else if (tag == CERT_STATUS_REVOKED) {
                certStatus = CERT_STATUS_REVOKED;
                revocationTime = derVal.data.getGeneralizedTime();
                if (derVal.data.available() != 0) {
                    int reason = derVal.getEnumerated();
                    // if reason out-of-range just leave as UNSPECIFIED
                    if (reason >= 0 && reason < values.length) {
                        revocationReason = values[reason];
                    }
                }
                // RevokedInfo
                if (DEBUG != null) {
                    DEBUG.println("Revocation time: " + revocationTime);
                    DEBUG.println("Revocation reason: " + revocationReason);
                }

            } else if (tag == CERT_STATUS_UNKNOWN) {
                certStatus = CERT_STATUS_UNKNOWN;

            } else {
                throw new IOException("Invalid certificate status");
            }

            thisUpdate = tmp.getGeneralizedTime();

            if (tmp.available() == 0)  {
                // we are done
            } else {
                derVal = tmp.getDerValue();
                tag = (byte)(derVal.tag & 0x1f);
                if (tag == 0) {
                    // next update
                    nextUpdate = derVal.data.getGeneralizedTime();

                    if (tmp.available() == 0)  {
                        // we are done
                    } else {
                        derVal = tmp.getDerValue();
                        tag = (byte)(derVal.tag & 0x1f);
                    }
                }
            }
            // singleExtensions
            if (tmp.available() > 0) {
                derVal = tmp.getDerValue();
                if (derVal.isContextSpecific((byte)1)) {
                    DerValue[] singleExtDer = derVal.data.getSequence(3);
                    singleExtensions =
                        new HashMap<String, java.security.cert.Extension>
                            (singleExtDer.length);
                    for (int i = 0; i < singleExtDer.length; i++) {
                        Extension ext = new Extension(singleExtDer[i]);
                        singleExtensions.put(ext.getId(), ext);
                        if (DEBUG != null) {
                            DEBUG.println("OCSP single extension: " + ext);
                        }
                    }
                }
            }

            Date now = new Date();
            if (DEBUG != null) {
                String until = "";
                if (nextUpdate != null) {
                    until = " until " + nextUpdate;
                }
                DEBUG.println("Response's validity interval is from " +
                    thisUpdate + until);
            }
            // Check that the test date is within the validity interval
            if ((thisUpdate != null && now.before(thisUpdate)) ||
                (nextUpdate != null && now.after(nextUpdate))) {

                if (DEBUG != null) {
                    DEBUG.println("Response is unreliable: its validity " +
                        "interval is out-of-date");
                }
                throw new IOException("Response is unreliable: its validity " +
                    "interval is out-of-date");
            }
        }

        /*
         * Return the certificate's revocation status code
         */
        private int getStatus() {
            return certStatus;
        }

        private CertId getCertId() {
            return certId;
        }

        private Date getRevocationTime() {
            return revocationTime;
        }

        private CRLReason getRevocationReason() {
            return revocationReason;
        }

        private Map<String, java.security.cert.Extension> getSingleExtensions() {
            return singleExtensions;
        }

        /**
         * Construct a string representation of a single OCSP response.
         */
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("SingleResponse:  \n");
            sb.append(certId);
            sb.append("\nCertStatus: "+ certStatusToText(getCertStatus(null)) +
                "\n");
            if (certStatus == CERT_STATUS_REVOKED) {
                sb.append("revocationTime is " + revocationTime + "\n");
                sb.append("revocationReason is " + revocationReason + "\n");
            }
            sb.append("thisUpdate is " + thisUpdate + "\n");
            if (nextUpdate != null) {
                sb.append("nextUpdate is " + nextUpdate + "\n");
            }
            return sb.toString();
        }
    }
}
