/* * 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(); } }
private void parse(DerValue val) throws CRLException, IOException { if (readOnly) { throw new CRLException("cannot over-write existing CRL"); } if (val.getData() == null || val.tag != DerValue.tag_Sequence) { throw new CRLException("Invalid DER-encoded CRL data"); } signedCRL = val.toByteArray(); DerValue seq[] = new DerValue[3]; seq[0] = val.data.getDerValue(); seq[1] = val.data.getDerValue(); seq[2] = val.data.getDerValue(); if (val.data.available() != 0) { throw new CRLException("signed overrun, bytes = " + val.data.available()); } if (seq[0].tag != DerValue.tag_Sequence) { throw new CRLException("signed CRL fields invalid"); } sigAlgId = AlgorithmId.parse(seq[1]); signature = seq[2].getBitString(); if (seq[1].data.available() != 0) { throw new CRLException("AlgorithmId field overrun"); } if (seq[2].data.available() != 0) { throw new CRLException("Signature field overrun"); } tbsCertList = seq[0].toByteArray(); DerInputStream derStrm = seq[0].data; DerValue tmp; byte nextByte; version = 0; nextByte = (byte) derStrm.peekByte(); if (nextByte == DerValue.tag_Integer) { version = derStrm.getInteger(); if (version != 1) { throw new CRLException("Invalid version"); } } tmp = derStrm.getDerValue(); AlgorithmId tmpId = AlgorithmId.parse(tmp); if (!tmpId.equals(sigAlgId)) { throw new CRLException("Signature algorithm mismatch"); } infoSigAlgId = tmpId; issuer = new X500Name(derStrm); if (issuer.isEmpty()) { throw new CRLException("Empty issuer DN not allowed in X509CRLs"); } nextByte = (byte) derStrm.peekByte(); if (nextByte == DerValue.tag_UtcTime) { thisUpdate = derStrm.getUTCTime(); } else if (nextByte == DerValue.tag_GeneralizedTime) { thisUpdate = derStrm.getGeneralizedTime(); } else { throw new CRLException("Invalid encoding for thisUpdate" + " (tag=" + nextByte + ")"); } if (derStrm.available() == 0) { return; } nextByte = (byte) derStrm.peekByte(); if (nextByte == DerValue.tag_UtcTime) { nextUpdate = derStrm.getUTCTime(); } else if (nextByte == DerValue.tag_GeneralizedTime) { nextUpdate = derStrm.getGeneralizedTime(); } if (derStrm.available() == 0) { return; } nextByte = (byte) derStrm.peekByte(); if ((nextByte == DerValue.tag_SequenceOf) && (!((nextByte & 0x0c0) == 0x080))) { DerValue[] badCerts = derStrm.getSequence(4); X500Principal crlIssuer = getIssuerX500Principal(); X500Principal badCertIssuer = crlIssuer; for (int i = 0; i < badCerts.length; i++) { X509CRLEntryImpl entry = new X509CRLEntryImpl(badCerts[i]); badCertIssuer = getCertIssuer(entry, badCertIssuer); entry.setCertificateIssuer(crlIssuer, badCertIssuer); X509IssuerSerial issuerSerial = new X509IssuerSerial(badCertIssuer, entry.getSerialNumber()); revokedMap.put(issuerSerial, entry); revokedList.add(entry); } } if (derStrm.available() == 0) { return; } tmp = derStrm.getDerValue(); if (tmp.isConstructed() && tmp.isContextSpecific((byte) 0)) { extensions = new CRLExtensions(tmp.data); } readOnly = true; }