Path: blob/master/test/jdk/sun/security/provider/certpath/Extensions/OCSPNonceExtensionTests.java
41154 views
/*1* Copyright (c) 2015, 2021, 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.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 8046321 825689526* @summary Unit tests for OCSPNonceExtension objects27* @modules java.base/sun.security.provider.certpath28* java.base/sun.security.util29* java.base/sun.security.x50930*/3132import java.security.cert.Extension;33import java.io.ByteArrayOutputStream;34import java.io.IOException;35import java.util.*;3637import sun.security.util.DerValue;38import sun.security.util.DerInputStream;39import sun.security.util.ObjectIdentifier;40import sun.security.provider.certpath.OCSPNonceExtension;41import sun.security.x509.PKIXExtensions;4243public class OCSPNonceExtensionTests {44public static final boolean DEBUG = true;45public static final String OCSP_NONCE_OID = "1.3.6.1.5.5.7.48.1.2";46public static final String ELEMENT_NONCE = "nonce";47public static final String EXT_NAME = "OCSPNonce";4849// DER encoding for OCSP nonce extension:50// OID = 1.3.6.1.5.5.7.48.1.251// Critical = true52// 48 bytes of 0xDEADBEEF53public static final byte[] OCSP_NONCE_DER = {5448, 66, 6, 9, 43, 6, 1, 5,555, 7, 48, 1, 2, 1, 1, -1,564, 50, 4, 48, -34, -83, -66, -17,57-34, -83, -66, -17, -34, -83, -66, -17,58-34, -83, -66, -17, -34, -83, -66, -17,59-34, -83, -66, -17, -34, -83, -66, -17,60-34, -83, -66, -17, -34, -83, -66, -17,61-34, -83, -66, -17, -34, -83, -66, -17,62-34, -83, -66, -17,63};6465// 16 bytes of 0xDEADBEEF66public static final byte[] DEADBEEF_16 = {67-34, -83, -66, -17, -34, -83, -66, -17,68-34, -83, -66, -17, -34, -83, -66, -17,69};7071// DER encoded extension using 16 bytes of DEADBEEF72public static final byte[] OCSP_NONCE_DB16 = {7348, 31, 6, 9, 43, 6, 1, 5,745, 7, 48, 1, 2, 4, 18, 4,7516, -34, -83, -66, -17, -34, -83, -66,76-17, -34, -83, -66, -17, -34, -83, -66,77-1778};7980public static void main(String [] args) throws Exception {81Map<String, TestCase> testList =82new LinkedHashMap<String, TestCase>() {{83put("CTOR Test (provide length)", testCtorByLength);84put("CTOR Test (provide nonce bytes)", testCtorByValue);85put("CTOR Test (set criticality forms)", testCtorCritForms);86put("CTOR Test (provide extension DER encoding)",87testCtorSuperByDerValue);88put("Test getName() method", testGetName);89}};9091System.out.println("============ Tests ============");92int testNo = 0;93int numberFailed = 0;94Map.Entry<Boolean, String> result;95for (String testName : testList.keySet()) {96System.out.println("Test " + ++testNo + ": " + testName);97result = testList.get(testName).runTest();98System.out.print("Result: " + (result.getKey() ? "PASS" : "FAIL"));99System.out.println(" " +100(result.getValue() != null ? result.getValue() : ""));101System.out.println("-------------------------------------------");102if (!result.getKey()) {103numberFailed++;104}105}106System.out.println("End Results: " + (testList.size() - numberFailed) +107" Passed" + ", " + numberFailed + " Failed.");108if (numberFailed > 0) {109throw new RuntimeException(110"One or more tests failed, see test output for details");111}112}113114private static void dumpHexBytes(byte[] data) {115if (data != null) {116for (int i = 0; i < data.length; i++) {117if (i % 16 == 0 && i != 0) {118System.out.print("\n");119}120System.out.print(String.format("%02X ", data[i]));121}122System.out.print("\n");123}124}125126private static void debuglog(String message) {127if (DEBUG) {128System.out.println(message);129}130}131132public static void verifyExtStructure(byte[] derData) throws IOException {133debuglog("verifyASN1Extension() received " + derData.length + " bytes");134DerInputStream dis = new DerInputStream(derData);135136// The sequenceItems array should be either two or three elements137// long. If three, then the criticality bit setting has been asserted.138DerValue[] sequenceItems = dis.getSequence(3);139debuglog("Found sequence containing " + sequenceItems.length +140" elements");141if (sequenceItems.length != 2 && sequenceItems.length != 3) {142throw new RuntimeException("Incorrect number of items found in " +143"the SEQUENCE (Got " + sequenceItems.length +144", expected 2 or 3 items)");145}146147int seqIndex = 0;148ObjectIdentifier extOid = sequenceItems[seqIndex++].getOID();149debuglog("Found OID: " + extOid.toString());150if (!extOid.equals((Object)PKIXExtensions.OCSPNonce_Id)) {151throw new RuntimeException("Incorrect OID (Got " +152extOid.toString() + ", expected " +153PKIXExtensions.OCSPNonce_Id.toString() + ")");154}155156if (sequenceItems.length == 3) {157// Non-default criticality bit setting should be at index 1158boolean isCrit = sequenceItems[seqIndex++].getBoolean();159debuglog("Found BOOLEAN (critical): " + isCrit);160}161162// The extnValue is an encapsulating OCTET STRING that contains the163// extension's value. For the OCSP Nonce, that value itself is also164// an OCTET STRING consisting of the random bytes.165DerValue extnValue =166new DerValue(sequenceItems[seqIndex++].getOctetString());167byte[] nonceData = extnValue.getOctetString();168debuglog("Found " + nonceData.length + " bytes of nonce data");169}170171public interface TestCase {172Map.Entry<Boolean, String> runTest();173}174175public static final TestCase testCtorByLength = new TestCase() {176@Override177public Map.Entry<Boolean, String> runTest() {178Boolean pass = Boolean.FALSE;179String message = null;180try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {181// Try sending in a negative length182try {183Extension negLenNonce = new OCSPNonceExtension(-8);184throw new RuntimeException(185"Accepted a negative length nonce");186} catch (IllegalArgumentException iae) { }187188// How about a zero length?189try {190Extension zeroLenNonce = new OCSPNonceExtension(0);191throw new RuntimeException("Accepted a zero length nonce");192} catch (IllegalArgumentException iae) { }193194// Length of the nonce exceeds the maximum 32 bytes195try {196Extension bigLenNonce = new OCSPNonceExtension(33);197throw new RuntimeException("Accepted a larger than 32 bytes of nonce");198} catch (IllegalArgumentException iae) { }199200// Valid input to constructor201Extension nonceByLen = new OCSPNonceExtension(32);202203// Verify overall encoded extension structure204nonceByLen.encode(baos);205verifyExtStructure(baos.toByteArray());206207// Verify the name, elements, and data conform to208// expected values for this specific object.209boolean crit = nonceByLen.isCritical();210String oid = nonceByLen.getId();211DerValue nonceData = new DerValue(nonceByLen.getValue());212213if (crit) {214message = "Extension incorrectly marked critical";215} else if (!oid.equals(OCSP_NONCE_OID)) {216message = "Incorrect OID (Got " + oid + ", Expected " +217OCSP_NONCE_OID + ")";218} else if (nonceData.getTag() != DerValue.tag_OctetString) {219message = "Incorrect nonce data tag type (Got " +220String.format("0x%02X", nonceData.getTag()) +221", Expected 0x04)";222} else if (nonceData.getOctetString().length != 32) {223message = "Incorrect nonce byte length (Got " +224nonceData.getOctetString().length +225", Expected 32)";226} else {227pass = Boolean.TRUE;228}229} catch (Exception e) {230e.printStackTrace(System.out);231message = e.getClass().getName();232}233234return new AbstractMap.SimpleEntry<>(pass, message);235}236};237238public static final TestCase testCtorByValue = new TestCase() {239@Override240public Map.Entry<Boolean, String> runTest() {241Boolean pass = Boolean.FALSE;242String message = null;243try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {244245// Try giving a null value for the nonce246try {247Extension nullNonce = new OCSPNonceExtension(null);248throw new RuntimeException("Accepted a null nonce");249} catch (NullPointerException npe) { }250251// How about a zero-length byte array?252try {253Extension zeroLenNonce =254new OCSPNonceExtension(new byte[0]);255throw new RuntimeException("Accepted a zero length nonce");256} catch (IllegalArgumentException iae) { }257258OCSPNonceExtension nonceByValue =259new OCSPNonceExtension(DEADBEEF_16);260261// Verify overall encoded extension structure262nonceByValue.encode(baos);263verifyExtStructure(baos.toByteArray());264265// Verify the name, elements, and data conform to266// expected values for this specific object.267boolean crit = nonceByValue.isCritical();268String oid = nonceByValue.getId();269byte[] nonceData = nonceByValue.getNonceValue();270271if (crit) {272message = "Extension incorrectly marked critical";273} else if (!oid.equals(OCSP_NONCE_OID)) {274message = "Incorrect OID (Got " + oid + ", Expected " +275OCSP_NONCE_OID + ")";276} else if (!Arrays.equals(nonceData, DEADBEEF_16)) {277message = "Returned nonce value did not match input";278} else {279pass = Boolean.TRUE;280}281} catch (Exception e) {282e.printStackTrace(System.out);283message = e.getClass().getName();284}285286return new AbstractMap.SimpleEntry<>(pass, message);287}288};289290public static final TestCase testCtorCritForms = new TestCase() {291@Override292public Map.Entry<Boolean, String> runTest() {293Boolean pass = Boolean.FALSE;294String message = null;295try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {296Extension nonceByLength = new OCSPNonceExtension(true, 32);297Extension nonceByValue =298new OCSPNonceExtension(true, DEADBEEF_16);299pass = nonceByLength.isCritical() && nonceByValue.isCritical();300if (!pass) {301message = "nonceByLength or nonceByValue was not marked " +302"critical as expected";303}304} catch (Exception e) {305e.printStackTrace(System.out);306message = e.getClass().getName();307}308309return new AbstractMap.SimpleEntry<>(pass, message);310}311};312313314public static final TestCase testCtorSuperByDerValue = new TestCase() {315@Override316public Map.Entry<Boolean, String> runTest() {317Boolean pass = Boolean.FALSE;318String message = null;319try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {320Extension nonceByDer = new sun.security.x509.Extension(321new DerValue(OCSP_NONCE_DER));322323// Verify overall encoded extension structure324nonceByDer.encode(baos);325verifyExtStructure(baos.toByteArray());326327// Verify the name, elements, and data conform to328// expected values for this specific object.329boolean crit = nonceByDer.isCritical();330String oid = nonceByDer.getId();331DerValue nonceData = new DerValue(nonceByDer.getValue());332333if (!crit) {334message = "Extension lacks expected criticality setting";335} else if (!oid.equals(OCSP_NONCE_OID)) {336message = "Incorrect OID (Got " + oid + ", Expected " +337OCSP_NONCE_OID + ")";338} else if (nonceData.getTag() != DerValue.tag_OctetString) {339message = "Incorrect nonce data tag type (Got " +340String.format("0x%02X", nonceData.getTag()) +341", Expected 0x04)";342} else if (nonceData.getOctetString().length != 48) {343message = "Incorrect nonce byte length (Got " +344nonceData.getOctetString().length +345", Expected 48)";346} else {347pass = Boolean.TRUE;348}349} catch (Exception e) {350e.printStackTrace(System.out);351message = e.getClass().getName();352}353354return new AbstractMap.SimpleEntry<>(pass, message);355}356};357358public static final TestCase testGetName = new TestCase() {359@Override360public Map.Entry<Boolean, String> runTest() {361Boolean pass = Boolean.FALSE;362String message = null;363try {364OCSPNonceExtension nonceByLen = new OCSPNonceExtension(32);365pass = new Boolean(nonceByLen.getName().equals(EXT_NAME));366} catch (Exception e) {367e.printStackTrace(System.out);368message = e.getClass().getName();369}370371return new AbstractMap.SimpleEntry<>(pass, message);372}373};374}375376377