jdk/test/com/sun/crypto/provider/Cipher/AES/TestCopySafe.java
changeset 21837 0c41fa97176a
child 25214 78a0f67da1d4
equal deleted inserted replaced
21825:b221b57b93bc 21837:0c41fa97176a
       
     1 /*
       
     2  * Copyright (c) 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 8026943
       
    27  * @summary Verify that same buffer can be used as input and output when
       
    28  * using Cipher objects.
       
    29  * @author Valerie Peng
       
    30  */
       
    31 import java.security.*;
       
    32 import java.security.spec.*;
       
    33 
       
    34 import java.util.Arrays;
       
    35 
       
    36 import javax.crypto.*;
       
    37 import javax.crypto.spec.*;
       
    38 
       
    39 public class TestCopySafe {
       
    40 
       
    41     private static boolean DEBUG = false;
       
    42     private static int INPUT_LENGTH = 160; // must be multiple of block size
       
    43     private static byte[] PT = new byte[INPUT_LENGTH];
       
    44     private static SecretKey KEY = new SecretKeySpec(new byte[16], "AES");
       
    45     private static byte[] IV = new byte[16];
       
    46 
       
    47     private static int[] OFFSETS = { 1, 8, 17 };
       
    48 
       
    49     private static final String[] MODES = {
       
    50         "ECB", "CBC", "PCBC", "CTR", "CTS",
       
    51         "CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40",
       
    52         "CFB48", "CFB56", "CFB64",
       
    53         "OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40",
       
    54         "OFB48", "OFB56", "OFB64",
       
    55         "GCM"
       
    56     };
       
    57 
       
    58     public static void main(String[] argv) throws Exception {
       
    59 
       
    60         Provider p = Security.getProvider("SunJCE");
       
    61 
       
    62         AlgorithmParameterSpec params = null;
       
    63         boolean result = true;
       
    64         for (String mode : MODES) {
       
    65             String transformation = "AES/" + mode + "/NoPadding";
       
    66             boolean isGCM = (mode == "GCM");
       
    67             if (isGCM) {
       
    68                 params = new GCMParameterSpec(128, IV);
       
    69             } else if (mode != "ECB") {
       
    70                 params = new IvParameterSpec(IV);
       
    71             }
       
    72             Cipher c = Cipher.getInstance(transformation, p);
       
    73             System.out.println("Testing " + transformation + ":");
       
    74             for (int offset : OFFSETS) {
       
    75                 System.out.print("=> offset " + offset + ": ");
       
    76                 try {
       
    77                     test(c, params, offset, isGCM);
       
    78                     System.out.println("Passed");
       
    79                 } catch(Exception ex) {
       
    80                     ex.printStackTrace();
       
    81                     result = false;
       
    82                     continue;
       
    83                 }
       
    84             }
       
    85         }
       
    86         if (!result) {
       
    87             throw new Exception("One or more test failed");
       
    88         }
       
    89     }
       
    90 
       
    91     private static void test(Cipher c, AlgorithmParameterSpec params,
       
    92         int offset, boolean isGCM) throws Exception {
       
    93 
       
    94         // Test encryption first
       
    95         if (isGCM) {
       
    96             // re-init with only key value first to bypass the
       
    97             // Key+IV-uniqueness check for GCM encryption
       
    98             c.init(Cipher.ENCRYPT_MODE, KEY);
       
    99         }
       
   100         c.init(Cipher.ENCRYPT_MODE, KEY, params);
       
   101         byte[] answer = c.doFinal(PT);
       
   102         byte[] pt2 = Arrays.copyOf(PT, answer.length + offset);
       
   103 
       
   104         // #1: outOfs = inOfs = 0
       
   105         if (isGCM) {
       
   106             c.init(Cipher.ENCRYPT_MODE, KEY);
       
   107             c.init(Cipher.ENCRYPT_MODE, KEY, params);
       
   108         }
       
   109         c.doFinal(pt2, 0, PT.length, pt2, 0);
       
   110         if (!isTwoArraysEqual(pt2, 0, answer, 0, answer.length)) {
       
   111             throw new Exception("Enc#1 diff check failed!");
       
   112         } else if (DEBUG) {
       
   113             System.out.println("Enc#1 diff check passed");
       
   114         }
       
   115 
       
   116         // #2: inOfs = 0, outOfs = offset
       
   117         System.arraycopy(PT, 0, pt2, 0, PT.length);
       
   118         if (isGCM) {
       
   119             c.init(Cipher.ENCRYPT_MODE, KEY);
       
   120             c.init(Cipher.ENCRYPT_MODE, KEY, params);
       
   121         }
       
   122         c.doFinal(pt2, 0, PT.length, pt2, offset);
       
   123         if (!isTwoArraysEqual(pt2, offset, answer, 0, answer.length)) {
       
   124             throw new Exception("Enc#2 diff check failed");
       
   125         } else if (DEBUG) {
       
   126             System.out.println("Enc#2 diff check passed");
       
   127         }
       
   128 
       
   129         // #3: inOfs = offset, outOfs = 0
       
   130         System.arraycopy(PT, 0, pt2, offset, PT.length);
       
   131         if (isGCM) {
       
   132             c.init(Cipher.ENCRYPT_MODE, KEY);
       
   133             c.init(Cipher.ENCRYPT_MODE, KEY, params);
       
   134         }
       
   135         c.doFinal(pt2, offset, PT.length, pt2, 0);
       
   136         if (!isTwoArraysEqual(pt2, 0, answer, 0, answer.length)) {
       
   137             throw new Exception("Enc#3 diff check failed");
       
   138         } else if (DEBUG) {
       
   139             System.out.println("Enc#3 diff check passed");
       
   140         }
       
   141 
       
   142        // Test decryption now, we should get back PT as a result
       
   143         c.init(Cipher.DECRYPT_MODE, KEY, params);
       
   144         pt2 = Arrays.copyOf(answer, answer.length + offset);
       
   145 
       
   146         // #1: outOfs = inOfs = 0
       
   147         c.doFinal(pt2, 0, answer.length, pt2, 0);
       
   148         if (!isTwoArraysEqual(pt2, 0, PT, 0, PT.length)) {
       
   149             throw new Exception("Dec#1 diff check failed!");
       
   150         } else if (DEBUG) {
       
   151             System.out.println("Dec#1 diff check passed");
       
   152         }
       
   153 
       
   154         // #2: inOfs = 0, outOfs = offset
       
   155         System.arraycopy(answer, 0, pt2, 0, answer.length);
       
   156         c.doFinal(pt2, 0, answer.length, pt2, offset);
       
   157         if (!isTwoArraysEqual(pt2, offset, PT, 0, PT.length)) {
       
   158             throw new Exception("Dec#2 diff check failed");
       
   159         } else if (DEBUG) {
       
   160             System.out.println("Dec#2 diff check passed");
       
   161         }
       
   162 
       
   163         // #3: inOfs = offset, outOfs = 0
       
   164         System.arraycopy(answer, 0, pt2, offset, answer.length);
       
   165         c.doFinal(pt2, offset, answer.length, pt2, 0);
       
   166         if (!isTwoArraysEqual(pt2, 0, PT, 0, PT.length)) {
       
   167             throw new Exception("Dec#3 diff check failed");
       
   168         } else if (DEBUG) {
       
   169             System.out.println("Dec#3 diff check passed");
       
   170         }
       
   171     }
       
   172 
       
   173     private static boolean isTwoArraysEqual(byte[] a, int aOff, byte[] b, int bOff,
       
   174         int len) {
       
   175         for (int i = 0; i < len; i++) {
       
   176             if (a[aOff + i] != b[bOff + i]) {
       
   177                 return false;
       
   178             }
       
   179         }
       
   180         return true;
       
   181     }
       
   182 }
       
   183