test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphers.java
changeset 47216 71c04702a3d5
parent 43248 5e15de85a1a0
child 51460 97e361fe3433
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2008, 2017, 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 /*
       
    25  * @test
       
    26  * @bug 4898461 6604496
       
    27  * @summary basic test for symmetric ciphers with padding
       
    28  * @author Valerie Peng
       
    29  * @library ..
       
    30  * @key randomness
       
    31  * @modules jdk.crypto.cryptoki
       
    32  * @run main/othervm TestSymmCiphers
       
    33  * @run main/othervm TestSymmCiphers sm
       
    34  */
       
    35 
       
    36 import java.io.ByteArrayOutputStream;
       
    37 import java.nio.ByteBuffer;
       
    38 import java.security.AlgorithmParameters;
       
    39 import java.security.NoSuchAlgorithmException;
       
    40 import java.security.Provider;
       
    41 import java.util.Random;
       
    42 import javax.crypto.Cipher;
       
    43 import javax.crypto.KeyGenerator;
       
    44 import javax.crypto.SecretKey;
       
    45 
       
    46 public class TestSymmCiphers extends PKCS11Test {
       
    47 
       
    48     private static class CI { // class for holding Cipher Information
       
    49 
       
    50         String transformation;
       
    51         String keyAlgo;
       
    52         int dataSize;
       
    53 
       
    54         CI(String transformation, String keyAlgo, int dataSize) {
       
    55             this.transformation = transformation;
       
    56             this.keyAlgo = keyAlgo;
       
    57             this.dataSize = dataSize;
       
    58         }
       
    59     }
       
    60     private static final CI[] TEST_LIST = {
       
    61         new CI("ARCFOUR", "ARCFOUR", 400),
       
    62         new CI("RC4", "RC4", 401),
       
    63         new CI("DES/CBC/NoPadding", "DES", 400),
       
    64         new CI("DESede/CBC/NoPadding", "DESede", 160),
       
    65         new CI("AES/CBC/NoPadding", "AES", 4800),
       
    66         new CI("Blowfish/CBC/NoPadding", "Blowfish", 24),
       
    67         new CI("DES/cbc/PKCS5Padding", "DES", 6401),
       
    68         new CI("DESede/CBC/PKCS5Padding", "DESede", 402),
       
    69         new CI("AES/CBC/PKCS5Padding", "AES", 30),
       
    70         new CI("Blowfish/CBC/PKCS5Padding", "Blowfish", 19),
       
    71         new CI("DES/ECB/NoPadding", "DES", 400),
       
    72         new CI("DESede/ECB/NoPadding", "DESede", 160),
       
    73         new CI("AES/ECB/NoPadding", "AES", 4800),
       
    74         new CI("DES/ECB/PKCS5Padding", "DES", 32),
       
    75         new CI("DES/ECB/PKCS5Padding", "DES", 6400),
       
    76         new CI("DESede/ECB/PKCS5Padding", "DESede", 400),
       
    77         new CI("AES/ECB/PKCS5Padding", "AES", 64),
       
    78 
       
    79         new CI("DES", "DES", 6400),
       
    80         new CI("DESede", "DESede", 408),
       
    81         new CI("AES", "AES", 128),
       
    82 
       
    83         new CI("AES/CTR/NoPadding", "AES", 3200)
       
    84 
       
    85     };
       
    86     private static StringBuffer debugBuf = new StringBuffer();
       
    87 
       
    88     @Override
       
    89     public void main(Provider p) throws Exception {
       
    90         // NSS reports CKR_DEVICE_ERROR when the data passed to
       
    91         // its EncryptUpdate/DecryptUpdate is not multiple of blocks
       
    92         int firstBlkSize = 16;
       
    93         boolean status = true;
       
    94         Random random = new Random();
       
    95         try {
       
    96             for (int i = 0; i < TEST_LIST.length; i++) {
       
    97                 CI currTest = TEST_LIST[i];
       
    98                 System.out.println("===" + currTest.transformation + "===");
       
    99                 try {
       
   100                     KeyGenerator kg =
       
   101                             KeyGenerator.getInstance(currTest.keyAlgo, p);
       
   102                     SecretKey key = kg.generateKey();
       
   103                     Cipher c1 = Cipher.getInstance(currTest.transformation, p);
       
   104                     Cipher c2 = Cipher.getInstance(currTest.transformation,
       
   105                             "SunJCE");
       
   106 
       
   107                     byte[] plainTxt = new byte[currTest.dataSize];
       
   108                     random.nextBytes(plainTxt);
       
   109                     System.out.println("Testing inLen = " + plainTxt.length);
       
   110 
       
   111                     c2.init(Cipher.ENCRYPT_MODE, key);
       
   112                     AlgorithmParameters params = c2.getParameters();
       
   113                     byte[] answer = c2.doFinal(plainTxt);
       
   114                     System.out.println("Encryption tests: START");
       
   115                     test(c1, Cipher.ENCRYPT_MODE, key, params, firstBlkSize,
       
   116                             plainTxt, answer);
       
   117                     System.out.println("Encryption tests: DONE");
       
   118                     c2.init(Cipher.DECRYPT_MODE, key, params);
       
   119                     byte[] answer2 = c2.doFinal(answer);
       
   120                     System.out.println("Decryption tests: START");
       
   121                     test(c1, Cipher.DECRYPT_MODE, key, params, firstBlkSize,
       
   122                             answer, answer2);
       
   123                     System.out.println("Decryption tests: DONE");
       
   124                 } catch (NoSuchAlgorithmException nsae) {
       
   125                     System.out.println("Skipping unsupported algorithm: " +
       
   126                             nsae);
       
   127                 }
       
   128             }
       
   129         } catch (Exception ex) {
       
   130             // print out debug info when exception is encountered
       
   131             if (debugBuf != null) {
       
   132                 System.out.println(debugBuf.toString());
       
   133                 debugBuf = new StringBuffer();
       
   134             }
       
   135             throw ex;
       
   136         }
       
   137     }
       
   138 
       
   139     private static void test(Cipher cipher, int mode, SecretKey key,
       
   140             AlgorithmParameters params, int firstBlkSize,
       
   141             byte[] in, byte[] answer) throws Exception {
       
   142         // test setup
       
   143         long startTime, endTime;
       
   144         cipher.init(mode, key, params);
       
   145         int outLen = cipher.getOutputSize(in.length);
       
   146         //debugOut("Estimated output size = " + outLen + "\n");
       
   147 
       
   148         // test data preparation
       
   149         ByteBuffer inBuf = ByteBuffer.allocate(in.length);
       
   150         inBuf.put(in);
       
   151         inBuf.position(0);
       
   152         ByteBuffer inDirectBuf = ByteBuffer.allocateDirect(in.length);
       
   153         inDirectBuf.put(in);
       
   154         inDirectBuf.position(0);
       
   155         ByteBuffer outBuf = ByteBuffer.allocate(outLen);
       
   156         ByteBuffer outDirectBuf = ByteBuffer.allocateDirect(outLen);
       
   157 
       
   158         // test#1: byte[] in + byte[] out
       
   159         //debugOut("Test#1:\n");
       
   160 
       
   161         ByteArrayOutputStream baos = new ByteArrayOutputStream();
       
   162 
       
   163         startTime = System.nanoTime();
       
   164         byte[] temp = cipher.update(in, 0, firstBlkSize);
       
   165         if (temp != null && temp.length > 0) {
       
   166             baos.write(temp, 0, temp.length);
       
   167         }
       
   168         temp = cipher.doFinal(in, firstBlkSize, in.length - firstBlkSize);
       
   169         if (temp != null && temp.length > 0) {
       
   170             baos.write(temp, 0, temp.length);
       
   171         }
       
   172         byte[] testOut1 = baos.toByteArray();
       
   173         endTime = System.nanoTime();
       
   174         perfOut("stream InBuf + stream OutBuf: " +
       
   175                 (endTime - startTime));
       
   176         match(testOut1, answer);
       
   177 
       
   178         // test#2: Non-direct Buffer in + non-direct Buffer out
       
   179         //debugOut("Test#2:\n");
       
   180         //debugOut("inputBuf: " + inBuf + "\n");
       
   181         //debugOut("outputBuf: " + outBuf + "\n");
       
   182 
       
   183         startTime = System.nanoTime();
       
   184         cipher.update(inBuf, outBuf);
       
   185         cipher.doFinal(inBuf, outBuf);
       
   186         endTime = System.nanoTime();
       
   187         perfOut("non-direct InBuf + non-direct OutBuf: " +
       
   188                 (endTime - startTime));
       
   189         match(outBuf, answer);
       
   190 
       
   191         // test#3: Direct Buffer in + direc Buffer out
       
   192         //debugOut("Test#3:\n");
       
   193         //debugOut("(pre) inputBuf: " + inDirectBuf + "\n");
       
   194         //debugOut("(pre) outputBuf: " + outDirectBuf + "\n");
       
   195 
       
   196         startTime = System.nanoTime();
       
   197         cipher.update(inDirectBuf, outDirectBuf);
       
   198         cipher.doFinal(inDirectBuf, outDirectBuf);
       
   199         endTime = System.nanoTime();
       
   200         perfOut("direct InBuf + direct OutBuf: " +
       
   201                 (endTime - startTime));
       
   202 
       
   203         //debugOut("(post) inputBuf: " + inDirectBuf + "\n");
       
   204         //debugOut("(post) outputBuf: " + outDirectBuf + "\n");
       
   205         match(outDirectBuf, answer);
       
   206 
       
   207         // test#4: Direct Buffer in + non-direct Buffer out
       
   208         //debugOut("Test#4:\n");
       
   209         inDirectBuf.position(0);
       
   210         outBuf.position(0);
       
   211         //debugOut("inputBuf: " + inDirectBuf + "\n");
       
   212         //debugOut("outputBuf: " + outBuf + "\n");
       
   213 
       
   214         startTime = System.nanoTime();
       
   215         cipher.update(inDirectBuf, outBuf);
       
   216         cipher.doFinal(inDirectBuf, outBuf);
       
   217         endTime = System.nanoTime();
       
   218         perfOut("direct InBuf + non-direct OutBuf: " +
       
   219                 (endTime - startTime));
       
   220         match(outBuf, answer);
       
   221 
       
   222         // test#5: Non-direct Buffer in + direct Buffer out
       
   223         //debugOut("Test#5:\n");
       
   224         inBuf.position(0);
       
   225         outDirectBuf.position(0);
       
   226 
       
   227         //debugOut("(pre) inputBuf: " + inBuf + "\n");
       
   228         //debugOut("(pre) outputBuf: " + outDirectBuf + "\n");
       
   229 
       
   230         startTime = System.nanoTime();
       
   231         cipher.update(inBuf, outDirectBuf);
       
   232         cipher.doFinal(inBuf, outDirectBuf);
       
   233         endTime = System.nanoTime();
       
   234         perfOut("non-direct InBuf + direct OutBuf: " +
       
   235                 (endTime - startTime));
       
   236 
       
   237         //debugOut("(post) inputBuf: " + inBuf + "\n");
       
   238         //debugOut("(post) outputBuf: " + outDirectBuf + "\n");
       
   239         match(outDirectBuf, answer);
       
   240 
       
   241         debugBuf = null;
       
   242     }
       
   243 
       
   244     private static void perfOut(String msg) {
       
   245         if (debugBuf != null) {
       
   246             debugBuf.append("PERF>" + msg);
       
   247         }
       
   248     }
       
   249 
       
   250     private static void debugOut(String msg) {
       
   251         if (debugBuf != null) {
       
   252             debugBuf.append(msg);
       
   253         }
       
   254     }
       
   255 
       
   256     private static void match(byte[] b1, byte[] b2) throws Exception {
       
   257         if (b1.length != b2.length) {
       
   258             debugOut("got len   : " + b1.length + "\n");
       
   259             debugOut("expect len: " + b2.length + "\n");
       
   260             throw new Exception("mismatch - different length! got: " + b1.length + ", expect: " + b2.length + "\n");
       
   261         } else {
       
   262             for (int i = 0; i < b1.length; i++) {
       
   263                 if (b1[i] != b2[i]) {
       
   264                     debugOut("got   : " + toString(b1) + "\n");
       
   265                     debugOut("expect: " + toString(b2) + "\n");
       
   266                     throw new Exception("mismatch");
       
   267                 }
       
   268             }
       
   269         }
       
   270     }
       
   271 
       
   272     private static void match(ByteBuffer bb, byte[] answer) throws Exception {
       
   273         byte[] bbTemp = new byte[bb.position()];
       
   274         bb.position(0);
       
   275         bb.get(bbTemp, 0, bbTemp.length);
       
   276         match(bbTemp, answer);
       
   277     }
       
   278 
       
   279     public static void main(String[] args) throws Exception {
       
   280         main(new TestSymmCiphers(), args);
       
   281     }
       
   282 }