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