/** Write the extension to the DerOutputStream. (Also called by the subclass) */ protected void encode(OutputStream out, ObjectIdentifier extensionId, boolean isCritical) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { this.extensionId = extensionId; this.critical = isCritical; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); }
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_REVOKED) { certStatus = CertStatus.REVOKED; revocationTime = derVal.data.getGeneralizedTime(); if (derVal.data.available() != 0) { DerValue dv = derVal.data.getDerValue(); tag = (byte) (dv.tag & 0x1f); if (tag == 0) { int reason = dv.data.getEnumerated(); // if reason out-of-range just leave as UNSPECIFIED if (reason >= 0 && reason < values.length) { revocationReason = values[reason]; } else { revocationReason = CRLReason.UNSPECIFIED; } } else { revocationReason = CRLReason.UNSPECIFIED; } } else { revocationReason = CRLReason.UNSPECIFIED; } // RevokedInfo if (debug != null) { debug.println("Revocation time: " + revocationTime); debug.println("Revocation reason: " + revocationReason); } } else { revocationTime = null; revocationReason = CRLReason.UNSPECIFIED; if (tag == CERT_STATUS_GOOD) { certStatus = CertStatus.GOOD; } else if (tag == CERT_STATUS_UNKNOWN) { certStatus = CertStatus.UNKNOWN; } else { throw new IOException("Invalid certificate status"); } } thisUpdate = tmp.getGeneralizedTime(); if (tmp.available() == 0) { // we are done nextUpdate = null; } 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); } } else { nextUpdate = null; } } // 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]); if (debug != null) { debug.println("OCSP single extension: " + ext); } // We don't support any extensions yet. Therefore, if it // is critical we must throw an exception because we // don't know how to process it. if (ext.isCritical()) { throw new IOException("Unsupported OCSP critical extension: " + ext.getExtensionId()); } singleExtensions.put(ext.getId(), ext); } } else { singleExtensions = Collections.emptyMap(); } } else { singleExtensions = Collections.emptyMap(); } }
/* * Create an OCSP response from its ASN.1 DER encoding. */ OCSPResponse(byte[] bytes) throws IOException { 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 int status = derIn.getEnumerated(); if (status >= 0 && status < rsvalues.length) { responseStatus = rsvalues[status]; } else { // unspecified responseStatus throw new IOException("Unknown OCSPResponse status: " + status); } if (debug != null) { debug.println("OCSP response status: " + responseStatus); } if (responseStatus != ResponseStatus.SUCCESSFUL) { // no need to continue, responseBytes are not set. singleResponseMap = Collections.emptyMap(); certs = Collections.<X509CertImpl>emptyList(); sigAlgId = null; signature = null; tbsResponseData = null; responseNonce = null; return; } // 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; ObjectIdentifier responseType = derIn.getOID(); if (responseType.equals((Object) 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); if (seqTmp.length < 3) { throw new IOException("Unexpected BasicOCSPResponse value"); } DerValue responseData = seqTmp[0]; // Need the DER encoded ResponseData to verify the signature later tbsResponseData = 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(); int 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) { if (debug != null) { X500Principal responderName = new X500Principal(seq.getData().toByteArray()); debug.println("OCSP Responder name: " + responderName); } } else if (tag == KEY_TAG) { if (debug != null) { byte[] responderKey = seq.getData().getOctetString(); debug.println("OCSP Responder key: " + Debug.toString(responderKey)); } } 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(); if (debug != null) { Date producedAtDate = seq.getGeneralizedTime(); debug.println("OCSP response produced at: " + producedAtDate); } // responses DerValue[] singleResponseDer = seqDerIn.getSequence(1); singleResponseMap = new HashMap<>(singleResponseDer.length); if (debug != null) { debug.println("OCSP number of SingleResponses: " + singleResponseDer.length); } for (int i = 0; i < singleResponseDer.length; i++) { SingleResponse singleResponse = new SingleResponse(singleResponseDer[i]); singleResponseMap.put(singleResponse.getCertId(), singleResponse); } // responseExtensions byte[] nonce = null; if (seqDerIn.available() > 0) { seq = seqDerIn.getDerValue(); if (seq.isContextSpecific((byte) 1)) { DerValue[] responseExtDer = seq.data.getSequence(3); for (int i = 0; i < responseExtDer.length; i++) { Extension ext = new Extension(responseExtDer[i]); if (debug != null) { debug.println("OCSP extension: " + ext); } // Only the NONCE extension is recognized if (ext.getExtensionId().equals((Object) OCSP.NONCE_EXTENSION_OID)) { nonce = ext.getExtensionValue(); } else if (ext.isCritical()) { throw new IOException("Unsupported OCSP critical extension: " + ext.getExtensionId()); } } } } responseNonce = nonce; // signatureAlgorithmId sigAlgId = AlgorithmId.parse(seqTmp[1]); // signature signature = seqTmp[2].getBitString(); // 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[] derCerts = seqCert.getData().getSequence(3); certs = new ArrayList<X509CertImpl>(derCerts.length); try { for (int i = 0; i < derCerts.length; i++) { certs.add(new X509CertImpl(derCerts[i].toByteArray())); } } catch (CertificateException ce) { throw new IOException("Bad encoding in X509 Certificate", ce); } } else { certs = Collections.<X509CertImpl>emptyList(); } }