test/jdk/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/CertStatusReqItemV2Tests.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
parent 56541 92cbbfc996f3
child 56543 2352538d2f6e
equal deleted inserted replaced
56541:92cbbfc996f3 56542:56aaa6cb3693
     1 /*
       
     2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 package sun.security.ssl;
       
    25 
       
    26 import java.security.cert.*;
       
    27 import java.util.*;
       
    28 import java.nio.ByteBuffer;
       
    29 import javax.net.ssl.SSLException;
       
    30 import javax.security.auth.x500.X500Principal;
       
    31 import sun.security.provider.certpath.ResponderId;
       
    32 import sun.security.provider.certpath.OCSPNonceExtension;
       
    33 
       
    34 /*
       
    35  * Checks that the hash value for a certificate's issuer name is generated
       
    36  * correctly. Requires any certificate that is not self-signed.
       
    37  *
       
    38  * NOTE: this test uses Sun private classes which are subject to change.
       
    39  */
       
    40 public class CertStatusReqItemV2Tests {
       
    41 
       
    42     private static final boolean debug = false;
       
    43 
       
    44     private static final byte[] DEF_CSRIV2_OCSP_MULTI_BYTES = {
       
    45            2,    0,    4,    0,    0,    0,    0
       
    46     };
       
    47 
       
    48     private static final byte[] DEF_CSRIV2_OCSP_BYTES = {
       
    49            1,    0,    4,    0,    0,    0,    0
       
    50     };
       
    51 
       
    52     // This is a CSRIV2 (ocsp_multi) that has a single
       
    53     // responder ID and no extensions.
       
    54     private static final byte[] CSRIV2_1RID = {
       
    55             2,    0,   32,     0,   28,    0,   26,  -95,
       
    56            24,   48,   22,    49,   20,   48,   18,    6,
       
    57             3,   85,    4,     3,   19,   11,   79,   67,
       
    58            83,   80,   32,    83,  105,  103,  110,  101,
       
    59           114,    0 ,   0
       
    60     };
       
    61 
       
    62     // This is a CSRIV2 (ocsp_multi) that has a single
       
    63     // responder ID and no extensions.  The request_length
       
    64     // field is too short in this case.
       
    65     private static final byte[] CSRIV2_LENGTH_TOO_SHORT = {
       
    66             2,    0,   27,     0,   28,    0,   26,  -95,
       
    67            24,   48,   22,    49,   20,   48,   18,    6,
       
    68             3,   85,    4,     3,   19,   11,   79,   67,
       
    69            83,   80,   32,    83,  105,  103,  110,  101,
       
    70           114,    0 ,   0
       
    71     };
       
    72 
       
    73     // This is a CSRIV2 (ocsp_multi) that has a single
       
    74     // responder ID and no extensions.  The request_length
       
    75     // field is too long in this case.
       
    76     private static final byte[] CSRIV2_LENGTH_TOO_LONG = {
       
    77             2,    0,   54,     0,   28,    0,   26,  -95,
       
    78            24,   48,   22,    49,   20,   48,   18,    6,
       
    79             3,   85,    4,     3,   19,   11,   79,   67,
       
    80            83,   80,   32,    83,  105,  103,  110,  101,
       
    81           114,    0 ,   0
       
    82     };
       
    83 
       
    84     // A CSRIV2 (ocsp) with one Responder ID (byName: CN=OCSP Signer)
       
    85     // and a nonce extension (32 bytes).
       
    86     private static final byte[] CSRIV2_OCSP_1RID_1EXT = {
       
    87             1,    0,   83,    0,   28,    0,   26,  -95,
       
    88            24,   48,   22,   49,   20,   48,   18,    6,
       
    89             3,   85,    4,    3,   19,   11,   79,   67,
       
    90            83,   80,   32,   83,  105,  103,  110,  101,
       
    91           114,    0,   51,   48,   49,   48,   47,    6,
       
    92             9,   43,    6,    1,    5,    5,    7,   48,
       
    93             1,    2,    4,   34,    4,   32,  -34,  -83,
       
    94           -66,  -17,  -34,  -83,  -66,  -17,  -34,  -83,
       
    95           -66,  -17,  -34,  -83,  -66,  -17,  -34,  -83,
       
    96           -66,  -17,  -34,  -83,  -66,  -17,  -34,  -83,
       
    97           -66,  -17,  -34,  -83,  -66,  -17
       
    98     };
       
    99 
       
   100     public static void main(String[] args) throws Exception {
       
   101         Map<String, TestCase> testList =
       
   102                 new LinkedHashMap<String, TestCase>() {{
       
   103             put("CTOR (Default)", testCtorTypeStatReq);
       
   104             put("CTOR (Byte array)", testCtorByteArray);
       
   105             put("CTOR (invalid lengths)", testCtorInvalidLengths);
       
   106         }};
       
   107 
       
   108         TestUtils.runTests(testList);
       
   109     }
       
   110 
       
   111     public static final TestCase testCtorTypeStatReq = new TestCase() {
       
   112         @Override
       
   113         public Map.Entry<Boolean, String> runTest() {
       
   114             Boolean pass = Boolean.FALSE;
       
   115             String message = null;
       
   116             try {
       
   117                 // Attempt to create CSRIv2 objects using null pointers
       
   118                 // for either parameter.  In either case NPE should be thrown
       
   119                 CertStatusReqItemV2 csriNull;
       
   120                 try {
       
   121                     csriNull = new CertStatusReqItemV2(null,
       
   122                             new OCSPStatusRequest());
       
   123                     throw new RuntimeException("Did not catch expected NPE " +
       
   124                             "for null status_type parameter");
       
   125                 } catch (NullPointerException npe) { }
       
   126 
       
   127                 try {
       
   128                     csriNull = new CertStatusReqItemV2(StatusRequestType.OCSP,
       
   129                             null);
       
   130                     throw new RuntimeException("Did not catch expected NPE " +
       
   131                             "for null StatusRequest parameter");
       
   132                 } catch (NullPointerException npe) { }
       
   133 
       
   134                 // Create an "ocsp_multi" type request using a default
       
   135                 // (no Responder IDs, no Extensions) OCSPStatusRequest
       
   136                 CertStatusReqItemV2 csriMulti =
       
   137                         new CertStatusReqItemV2(StatusRequestType.OCSP_MULTI,
       
   138                                 new OCSPStatusRequest());
       
   139                 HandshakeOutStream hsout = new HandshakeOutStream(null);
       
   140                 csriMulti.send(hsout);
       
   141                 TestUtils.valueCheck(DEF_CSRIV2_OCSP_MULTI_BYTES,
       
   142                         hsout.toByteArray());
       
   143                 hsout.reset();
       
   144 
       
   145                 // Create an "ocsp" type request using a default
       
   146                 // (no Responder IDs, no Extensions) OCSPStatusRequest
       
   147                 CertStatusReqItemV2 csriSingle =
       
   148                         new CertStatusReqItemV2(StatusRequestType.OCSP,
       
   149                                 new OCSPStatusRequest(new LinkedList<>(),
       
   150                                         new LinkedList<>()));
       
   151                 csriSingle.send(hsout);
       
   152                 TestUtils.valueCheck(DEF_CSRIV2_OCSP_BYTES,
       
   153                         hsout.toByteArray());
       
   154 
       
   155                 // Create the CertStatusRequestItemV2 with a user-defined
       
   156                 // StatusRequestType value
       
   157                 CertStatusReqItemV2 csriNine =
       
   158                         new CertStatusReqItemV2(StatusRequestType.get(9),
       
   159                                 new OCSPStatusRequest(null, null));
       
   160                 if (csriNine.getType().id != 9) {
       
   161                     throw new RuntimeException("Expected status_type = 9, " +
       
   162                             "got " + csriNine.getType().id);
       
   163                 } else {
       
   164                     StatusRequest sr = csriNine.getRequest();
       
   165                     if (!(sr instanceof OCSPStatusRequest)) {
       
   166                         throw new RuntimeException("Expected " +
       
   167                                 "OCSPStatusRequest, got " +
       
   168                                 sr.getClass().getName());
       
   169                     }
       
   170                 }
       
   171 
       
   172                 // Create the CertStatusRequestItemV2 with a StatusRequest
       
   173                 // that does not match the status_type argument.
       
   174                 // We expect IllegalArgumentException in this case.
       
   175                 try {
       
   176                     CertStatusReqItemV2 csriBadSR = new CertStatusReqItemV2(
       
   177                             StatusRequestType.OCSP_MULTI,
       
   178                             new BogusStatusRequest());
       
   179                     throw new RuntimeException("Constructor accepted a " +
       
   180                             "StatusRequest that is inconsistent with " +
       
   181                             "the status_type");
       
   182                 } catch (IllegalArgumentException iae) {
       
   183                     // The expected result...nothing to do here
       
   184                 }
       
   185 
       
   186                 pass = Boolean.TRUE;
       
   187             } catch (Exception e) {
       
   188                 e.printStackTrace(System.out);
       
   189                 message = e.getClass().getName();
       
   190             }
       
   191 
       
   192             return new AbstractMap.SimpleEntry<>(pass, message);
       
   193         }
       
   194     };
       
   195 
       
   196     // Test the constructor form that takes the data from a byte array
       
   197     public static final TestCase testCtorByteArray = new TestCase() {
       
   198         @Override
       
   199         public Map.Entry<Boolean, String> runTest() {
       
   200             Boolean pass = Boolean.FALSE;
       
   201             String message = null;
       
   202             try {
       
   203                 StatusRequestType sType;
       
   204                 StatusRequest sReq;
       
   205                 ResponderId checkRid =
       
   206                         new ResponderId(new X500Principal("CN=OCSP Signer"));
       
   207                 Extension checkExt = new OCSPNonceExtension(32);
       
   208 
       
   209                 CertStatusReqItemV2 csriv =
       
   210                         new CertStatusReqItemV2(CSRIV2_OCSP_1RID_1EXT);
       
   211                 sType = csriv.getType();
       
   212                 if (sType != StatusRequestType.OCSP) {
       
   213                     throw new RuntimeException("Unexpected StatusRequestType " +
       
   214                             sType.getClass().getName());
       
   215                 }
       
   216 
       
   217                 sReq = csriv.getRequest();
       
   218                 if (sReq instanceof OCSPStatusRequest) {
       
   219                     OCSPStatusRequest osr = (OCSPStatusRequest)sReq;
       
   220                     List<ResponderId> ridList = osr.getResponderIds();
       
   221                     List<Extension> extList = osr.getExtensions();
       
   222 
       
   223                     if (ridList.size() != 1 || !ridList.contains(checkRid)) {
       
   224                         throw new RuntimeException("Responder list mismatch");
       
   225                     } else if (extList.size() !=  1 ||
       
   226                             !extList.get(0).getId().equals(checkExt.getId())) {
       
   227                         throw new RuntimeException("Extension list mismatch");
       
   228                     }
       
   229                 } else {
       
   230                     throw new RuntimeException("Expected OCSPStatusRequest " +
       
   231                             "from decoded bytes, got " +
       
   232                             sReq.getClass().getName());
       
   233                 }
       
   234 
       
   235                 // Create a CSRIV2 out of random data.  A non-OCSP/OCSP_MULTI
       
   236                 // type will be forcibly set and the outer length field will
       
   237                 // be correct.
       
   238                 // The constructor should create a StatusRequestType object
       
   239                 // and an UnknownStatusRequest object consisting of the
       
   240                 // data segment.
       
   241                 byte[] junkData = new byte[48];
       
   242                 Random r = new Random(System.currentTimeMillis());
       
   243                 r.nextBytes(junkData);
       
   244                 junkData[0] = 7;        // status_type = 7
       
   245                 junkData[1] = 0;
       
   246                 junkData[2] = 45;       // request_length = 45
       
   247                 csriv = new CertStatusReqItemV2(junkData);
       
   248 
       
   249                 sType = csriv.getType();
       
   250                 sReq = csriv.getRequest();
       
   251                 if (sType.id != junkData[0]) {
       
   252                     throw new RuntimeException("StatusRequestType mismatch: " +
       
   253                             "expected 7, got " + sType.id);
       
   254                 }
       
   255                 if (sReq instanceof UnknownStatusRequest) {
       
   256                     // Verify the underlying StatusRequest bytes have been
       
   257                     // preserved correctly.
       
   258                     HandshakeOutStream hsout = new HandshakeOutStream(null);
       
   259                     sReq.send(hsout);
       
   260                     byte[] srDataOut = hsout.toByteArray();
       
   261                     TestUtils.valueCheck(srDataOut, junkData, 0, 3,
       
   262                             srDataOut.length);
       
   263                 } else {
       
   264                     throw new RuntimeException("StatusRequest mismatch: " +
       
   265                             "expected UnknownStatusRequest, got " +
       
   266                             sReq.getClass().getName());
       
   267                 }
       
   268 
       
   269                 // Test the parsing of the default OCSP/OCSP_MULTI extensions
       
   270                 // and make sure the underlying StatusRequestType and
       
   271                 // StatusRequest objects are correct.
       
   272                 csriv = new CertStatusReqItemV2(DEF_CSRIV2_OCSP_MULTI_BYTES);
       
   273                 sType = csriv.getType();
       
   274                 sReq = csriv.getRequest();
       
   275                 if (sType != StatusRequestType.OCSP_MULTI) {
       
   276                     throw new RuntimeException("StatusRequestType mismatch: " +
       
   277                             "expected OCSP_MULTI (2), got " + sType.id);
       
   278                 }
       
   279                 if (!(sReq instanceof OCSPStatusRequest)) {
       
   280                     throw new RuntimeException("StatusRequest mismatch: " +
       
   281                             "expected OCSPStatusRequest, got " +
       
   282                             sReq.getClass().getName());
       
   283                 }
       
   284 
       
   285                 csriv = new CertStatusReqItemV2(DEF_CSRIV2_OCSP_BYTES);
       
   286                 sType = csriv.getType();
       
   287                 sReq = csriv.getRequest();
       
   288                 if (sType != StatusRequestType.OCSP) {
       
   289                     throw new RuntimeException("StatusRequestType mismatch: " +
       
   290                             "expected OCSP (1), got " + sType.id);
       
   291                 }
       
   292                 if (!(sReq instanceof OCSPStatusRequest)) {
       
   293                     throw new RuntimeException("StatusRequest mismatch: " +
       
   294                             "expected OCSPStatusRequest, got " +
       
   295                             sReq.getClass().getName());
       
   296                 }
       
   297 
       
   298                 pass = Boolean.TRUE;
       
   299             } catch (Exception e) {
       
   300                 e.printStackTrace(System.out);
       
   301                 message = e.getClass().getName();
       
   302             }
       
   303 
       
   304             return new AbstractMap.SimpleEntry<>(pass, message);
       
   305         }
       
   306     };
       
   307 
       
   308     public static final TestCase testCtorInvalidLengths = new TestCase() {
       
   309         @Override
       
   310         public Map.Entry<Boolean, String> runTest() {
       
   311             Boolean pass = Boolean.FALSE;
       
   312             String message = null;
       
   313             try {
       
   314                 try {
       
   315                     CertStatusReqItemV2 csriTooShort =
       
   316                             new CertStatusReqItemV2(CSRIV2_LENGTH_TOO_SHORT);
       
   317                     throw new RuntimeException("Expected exception not thrown");
       
   318                 } catch (SSLException ssle) { }
       
   319 
       
   320                 try {
       
   321                     CertStatusReqItemV2 csriTooLong =
       
   322                             new CertStatusReqItemV2(CSRIV2_LENGTH_TOO_LONG);
       
   323                     throw new RuntimeException("Expected exception not thrown");
       
   324                 } catch (SSLException ssle) { }
       
   325 
       
   326                 pass = Boolean.TRUE;
       
   327             } catch (Exception e) {
       
   328                 e.printStackTrace(System.out);
       
   329                 message = e.getClass().getName();
       
   330             }
       
   331 
       
   332             return new AbstractMap.SimpleEntry<>(pass, message);
       
   333         }
       
   334     };
       
   335 
       
   336     // Test the constructor form that takes the data from HandshakeInputStream
       
   337     public static final TestCase testCtorInputStream = new TestCase() {
       
   338         @Override
       
   339         public Map.Entry<Boolean, String> runTest() {
       
   340             Boolean pass = Boolean.FALSE;
       
   341             String message = null;
       
   342             try {
       
   343                 StatusRequestType sType;
       
   344                 StatusRequest sReq;
       
   345                 ResponderId checkRid =
       
   346                         new ResponderId(new X500Principal("CN=OCSP Signer"));
       
   347                 Extension checkExt = new OCSPNonceExtension(32);
       
   348 
       
   349                 HandshakeInStream hsis = new HandshakeInStream();
       
   350                 hsis.incomingRecord(ByteBuffer.wrap(CSRIV2_OCSP_1RID_1EXT));
       
   351                 CertStatusReqItemV2 csriv = new CertStatusReqItemV2(hsis);
       
   352                 sType = csriv.getType();
       
   353                 if (sType != StatusRequestType.OCSP) {
       
   354                     throw new RuntimeException("Unexpected StatusRequestType " +
       
   355                             sType.getClass().getName());
       
   356                 }
       
   357 
       
   358                 sReq = csriv.getRequest();
       
   359                 if (sReq instanceof OCSPStatusRequest) {
       
   360                     OCSPStatusRequest osr = (OCSPStatusRequest)sReq;
       
   361                     List<ResponderId> ridList = osr.getResponderIds();
       
   362                     List<Extension> extList = osr.getExtensions();
       
   363 
       
   364                     if (ridList.size() != 1 || !ridList.contains(checkRid)) {
       
   365                         throw new RuntimeException("Responder list mismatch");
       
   366                     } else if (extList.size() !=  1 ||
       
   367                             !extList.get(0).getId().equals(checkExt.getId())) {
       
   368                         throw new RuntimeException("Extension list mismatch");
       
   369                     }
       
   370                 } else {
       
   371                     throw new RuntimeException("Expected OCSPStatusRequest " +
       
   372                             "from decoded bytes, got " +
       
   373                             sReq.getClass().getName());
       
   374                 }
       
   375 
       
   376                 // Create a CSRIV2 out of random data.  A non-OCSP/OCSP_MULTI
       
   377                 // type will be forcibly set and the outer length field will
       
   378                 // be correct.
       
   379                 // The constructor should create a StatusRequestType object
       
   380                 // and an UnknownStatusRequest object consisting of the
       
   381                 // data segment.
       
   382                 byte[] junkData = new byte[48];
       
   383                 Random r = new Random(System.currentTimeMillis());
       
   384                 r.nextBytes(junkData);
       
   385                 junkData[0] = 7;        // status_type = 7
       
   386                 junkData[1] = 0;
       
   387                 junkData[2] = 45;       // request_length = 45
       
   388                 hsis = new HandshakeInStream();
       
   389                 hsis.incomingRecord(ByteBuffer.wrap(junkData));
       
   390                 csriv = new CertStatusReqItemV2(hsis);
       
   391 
       
   392                 sType = csriv.getType();
       
   393                 sReq = csriv.getRequest();
       
   394                 if (sType.id != junkData[0]) {
       
   395                     throw new RuntimeException("StatusRequestType mismatch: " +
       
   396                             "expected 7, got " + sType.id);
       
   397                 }
       
   398                 if (sReq instanceof UnknownStatusRequest) {
       
   399                     // Verify the underlying StatusRequest bytes have been
       
   400                     // preserved correctly.
       
   401                     HandshakeOutStream hsout = new HandshakeOutStream(null);
       
   402                     sReq.send(hsout);
       
   403                     byte[] srDataOut = hsout.toByteArray();
       
   404                     TestUtils.valueCheck(srDataOut, junkData, 0, 3,
       
   405                             srDataOut.length);
       
   406                 } else {
       
   407                     throw new RuntimeException("StatusRequest mismatch: " +
       
   408                             "expected UnknownStatusRequest, got " +
       
   409                             sReq.getClass().getName());
       
   410                 }
       
   411 
       
   412                 // Test the parsing of the default OCSP/OCSP_MULTI extensions
       
   413                 // and make sure the underlying StatusRequestType and
       
   414                 // StatusRequest objects are correct.
       
   415                 hsis = new HandshakeInStream();
       
   416                 hsis.incomingRecord(
       
   417                         ByteBuffer.wrap(DEF_CSRIV2_OCSP_MULTI_BYTES));
       
   418                 csriv = new CertStatusReqItemV2(hsis);
       
   419                 sType = csriv.getType();
       
   420                 sReq = csriv.getRequest();
       
   421                 if (sType != StatusRequestType.OCSP_MULTI) {
       
   422                     throw new RuntimeException("StatusRequestType mismatch: " +
       
   423                             "expected OCSP_MULTI (2), got " + sType.id);
       
   424                 }
       
   425                 if (!(sReq instanceof OCSPStatusRequest)) {
       
   426                     throw new RuntimeException("StatusRequest mismatch: " +
       
   427                             "expected OCSPStatusRequest, got " +
       
   428                             sReq.getClass().getName());
       
   429                 }
       
   430 
       
   431                 hsis = new HandshakeInStream();
       
   432                 hsis.incomingRecord(ByteBuffer.wrap(DEF_CSRIV2_OCSP_BYTES));
       
   433                 csriv = new CertStatusReqItemV2(hsis);
       
   434                 sType = csriv.getType();
       
   435                 sReq = csriv.getRequest();
       
   436                 if (sType != StatusRequestType.OCSP) {
       
   437                     throw new RuntimeException("StatusRequestType mismatch: " +
       
   438                             "expected OCSP (1), got " + sType.id);
       
   439                 }
       
   440                 if (!(sReq instanceof OCSPStatusRequest)) {
       
   441                     throw new RuntimeException("StatusRequest mismatch: " +
       
   442                             "expected OCSPStatusRequest, got " +
       
   443                             sReq.getClass().getName());
       
   444                 }
       
   445 
       
   446                 pass = Boolean.TRUE;
       
   447             } catch (Exception e) {
       
   448                 e.printStackTrace(System.out);
       
   449                 message = e.getClass().getName();
       
   450             }
       
   451 
       
   452             return new AbstractMap.SimpleEntry<>(pass, message);
       
   453         }
       
   454     };
       
   455 }