1 /*
   2  * Copyright (c) 2007, 2013, 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 4898484 6604496 8001284
  27  * @summary basic test for symmetric ciphers with no padding
  28  * @author Valerie Peng
  29  * @library ..
  30  */
  31 
  32 import java.io.*;
  33 import java.nio.*;
  34 import java.util.*;
  35 
  36 import java.security.*;
  37 import java.security.spec.AlgorithmParameterSpec;
  38 
  39 import javax.crypto.*;
  40 import javax.crypto.spec.IvParameterSpec;
  41 
  42 public class TestSymmCiphersNoPad extends PKCS11Test {
  43 
  44     private static class CI { // class for holding Cipher Information
  45         String transformation;
  46         String keyAlgo;
  47         int dataSize;
  48 
  49         CI(String transformation, String keyAlgo, int dataSize) {
  50             this.transformation = transformation;
  51             this.keyAlgo = keyAlgo;
  52             this.dataSize = dataSize;
  53         }
  54     }
  55 
  56     private static final CI TEST_LIST[] = {
  57         new CI("ARCFOUR", "ARCFOUR", 400),
  58         new CI("RC4", "RC4", 401),
  59         new CI("DES/CBC/NoPadding", "DES", 400),
  60         new CI("DESede/CBC/NoPadding", "DESede", 160),
  61         new CI("AES/CBC/NoPadding", "AES", 4800),
  62         new CI("Blowfish/CBC/NoPadding", "Blowfish", 24),
  63         new CI("AES/CTR/NoPadding", "AES", 1600),
  64         new CI("AES/CTR/NoPadding", "AES", 65)
  65     };
  66 
  67     private static StringBuffer debugBuf;
  68 
  69     public void main(Provider p) throws Exception {
  70         boolean status = true;
  71         Random random = new Random();
  72         try {
  73             for (int i = 0; i < TEST_LIST.length; i++) {
  74                 CI currTest = TEST_LIST[i];
  75                 System.out.println("===" + currTest.transformation + "===");
  76                 try {
  77                     KeyGenerator kg =
  78                         KeyGenerator.getInstance(currTest.keyAlgo, p);
  79                     SecretKey key = kg.generateKey();
  80                     Cipher c1 = Cipher.getInstance(currTest.transformation, p);
  81                     Cipher c2 = Cipher.getInstance(currTest.transformation,
  82                                                    "SunJCE");
  83 
  84                     byte[] plainTxt = new byte[currTest.dataSize];
  85                     random.nextBytes(plainTxt);
  86                     System.out.println("Testing inLen = " + plainTxt.length);
  87 
  88                     c2.init(Cipher.ENCRYPT_MODE, key);
  89                     AlgorithmParameters params = c2.getParameters();
  90                     byte[] answer = c2.doFinal(plainTxt);
  91                     test(c1, Cipher.ENCRYPT_MODE, key, params,
  92                          plainTxt, answer);
  93                     System.out.println("Encryption tests: DONE");
  94                     c2.init(Cipher.DECRYPT_MODE, key, params);
  95                     byte[] answer2 = c2.doFinal(answer);
  96                     test(c1, Cipher.DECRYPT_MODE, key, params,
  97                          answer, answer2);
  98                     System.out.println("Decryption tests: DONE");
  99                 } catch (NoSuchAlgorithmException nsae) {
 100                     System.out.println("Skipping unsupported algorithm: " +
 101                                        nsae);
 102                 }
 103             }
 104         } catch (Exception ex) {
 105             // print out debug info when exception is encountered
 106             if (debugBuf != null) {
 107                 System.out.println(debugBuf.toString());
 108             }
 109             throw ex;
 110         }
 111     }
 112 
 113     private static void test(Cipher cipher, int mode, SecretKey key,
 114                              AlgorithmParameters params,
 115                              byte[] in, byte[] answer) throws Exception {
 116         // test setup
 117         debugBuf = new StringBuffer();
 118         cipher.init(mode, key, params);
 119         int outLen = cipher.getOutputSize(in.length);
 120         debugBuf.append("Estimated output size = " + outLen + "\n");
 121 
 122         // test data preparation
 123         ByteBuffer inBuf = ByteBuffer.allocate(in.length);
 124         inBuf.put(in);
 125         inBuf.position(0);
 126         ByteBuffer inDirectBuf = ByteBuffer.allocateDirect(in.length);
 127         inDirectBuf.put(in);
 128         inDirectBuf.position(0);
 129         ByteBuffer outBuf = ByteBuffer.allocate(outLen);
 130         ByteBuffer outDirectBuf = ByteBuffer.allocateDirect(outLen);
 131 
 132         // test#1: byte[] in + byte[] out
 133         debugBuf.append("Test#1:\n");
 134         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 135         byte[] testOut1 = cipher.update(in, 0, 16);
 136         if (testOut1 != null) baos.write(testOut1, 0, testOut1.length);
 137         testOut1 = cipher.doFinal(in, 16, in.length-16);
 138         if (testOut1 != null) baos.write(testOut1, 0, testOut1.length);
 139         testOut1 = baos.toByteArray();
 140         match(testOut1, answer);
 141 
 142         // test#2: Non-direct Buffer in + non-direct Buffer out
 143         debugBuf.append("Test#2:\n");
 144         debugBuf.append("inputBuf: " + inBuf + "\n");
 145         debugBuf.append("outputBuf: " + outBuf + "\n");
 146         cipher.update(inBuf, outBuf);
 147         cipher.doFinal(inBuf, outBuf);
 148         match(outBuf, answer);
 149 
 150         // test#3: Direct Buffer in + direc Buffer out
 151         debugBuf.append("Test#3:\n");
 152         debugBuf.append("(pre) inputBuf: " + inDirectBuf + "\n");
 153         debugBuf.append("(pre) outputBuf: " + outDirectBuf + "\n");
 154         cipher.update(inDirectBuf, outDirectBuf);
 155         cipher.doFinal(inDirectBuf, outDirectBuf);
 156 
 157         debugBuf.append("(post) inputBuf: " + inDirectBuf + "\n");
 158         debugBuf.append("(post) outputBuf: " + outDirectBuf + "\n");
 159         match(outDirectBuf, answer);
 160 
 161         // test#4: Direct Buffer in + non-direct Buffer out
 162         debugBuf.append("Test#4:\n");
 163         inDirectBuf.position(0);
 164         outBuf.position(0);
 165         debugBuf.append("inputBuf: " + inDirectBuf + "\n");
 166         debugBuf.append("outputBuf: " + outBuf + "\n");
 167         cipher.update(inDirectBuf, outBuf);
 168         cipher.doFinal(inDirectBuf, outBuf);
 169         match(outBuf, answer);
 170 
 171         // test#5: Non-direct Buffer in + direct Buffer out
 172         debugBuf.append("Test#5:\n");
 173         inBuf.position(0);
 174         outDirectBuf.position(0);
 175 
 176         debugBuf.append("(pre) inputBuf: " + inBuf + "\n");
 177         debugBuf.append("(pre) outputBuf: " + outDirectBuf + "\n");
 178 
 179         cipher.update(inBuf, outDirectBuf);
 180         cipher.doFinal(inBuf, outDirectBuf);
 181 
 182         debugBuf.append("(post) inputBuf: " + inBuf + "\n");
 183         debugBuf.append("(post) outputBuf: " + outDirectBuf + "\n");
 184         match(outDirectBuf, answer);
 185 
 186         // test#6: Streams
 187         debugBuf.append("Test#6: Streaming\n");
 188         outBuf.position(0);
 189         InputStream stream =
 190             new CipherInputStream(new ByteArrayInputStream(in), cipher);
 191         byte[] data = new byte[1024];
 192         int bytesRead = 0;
 193         try {
 194             while (bytesRead >= 0) {
 195                 bytesRead = stream.read(data);
 196                 if (bytesRead == -1)
 197                     break;
 198                 debugBuf.append("bytesRead: " + bytesRead);
 199                 debugBuf.append("\toutBuf.position(): " + outBuf.position() +
 200                     "\n");
 201                 outBuf.put(data, 0 , bytesRead);
 202             }
 203         } catch (Exception ex) {
 204             debugBuf.append("Caught Exception during stream reading\n");
 205             throw ex;
 206         }
 207         match(outBuf, answer);
 208 
 209         debugBuf = null;
 210     }
 211 
 212     private static void match(byte[] b1, byte[] b2) throws Exception {
 213         if (b1.length != b2.length) {
 214             debugBuf.append("got len   : " + b1.length + "\n");
 215             debugBuf.append("expect len: " + b2.length + "\n");
 216             throw new Exception("mismatch - different length!\n");
 217         } else {
 218             for (int i = 0; i < b1.length; i++) {
 219                 if (b1[i] != b2[i]) {
 220                     debugBuf.append("got   : " + toString(b1) + "\n");
 221                     debugBuf.append("expect: " + toString(b2) + "\n");
 222                     throw new Exception("mismatch");
 223                 }
 224             }
 225         }
 226     }
 227 
 228     private static void match(ByteBuffer bb, byte[] answer) throws Exception {
 229         byte[] bbTemp = new byte[bb.position()];
 230         bb.position(0);
 231         bb.get(bbTemp, 0, bbTemp.length);
 232         match(bbTemp, answer);
 233     }
 234 
 235     public static void main(String[] args) throws Exception {
 236         main(new TestSymmCiphersNoPad());
 237     }
 238 }