jdk/test/com/sun/crypto/provider/Cipher/AES/TestAESCiphers/Dynamic.java
author valeriep
Fri, 06 Mar 2015 00:49:38 +0000
changeset 29366 fe7c66943ba1
child 42362 7b70c5bfe82e
permissions -rw-r--r--
8044193: Need to add known answer tests for AES cipher Summary: Added more tests for AES cipher using known test vectors. Reviewed-by: valeriep Contributed-by: Zaiyao Liu <zaiyao.liu@oracle.com>

/*
 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

import java.io.PrintStream;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;

public class Dynamic {

    static final String ALGORITHM = "AES";
    static final String[] MODE = {
        "ECb", "CbC", "CTR", "PCBC", "OFB", "OFB150", "cFB", "CFB7",
        "cFB8", "cFB16", "cFB24", "cFB32", "Cfb40", "cfB48", "cfB56",
        "cfB64", "cfB72", "cfB80", "cfB88", "cfB96", "cfb104", "cfB112",
        "cfB120", "cfB128", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40",
        "OFB48", "OFB56", "OFB64", "OFB72", "OFB80", "OFB88", "OFB96",
        "OFB104", "OFB112", "OFB120", "OFB128", "GCM"
    };
    static final String[] PADDING = {
        "NoPadding", "PKCS5Padding", "ISO10126Padding"
    };
    static final String SUNJCE = "SunJCE";

    Cipher ci = null;
    byte[] iv = null;
    AlgorithmParameterSpec aps = null;
    SecretKey key = null;
    int keyStrength;
    static int DefaultSize = 128;

    public void run(String[] argv) throws Exception {
        if (!runAllTest(argv, System.out)) {
            throw new Exception("Test Failed");
        }
    }

    protected boolean runAllTest(String argv[], PrintStream out) {
        boolean result = true;
        StringBuilder failedList = new StringBuilder();
        int failedCnt = 0;
        int testCount = 0;
        int padKinds; // how many kinds of padding mode such as PKCS5padding and
        // NoPadding.

        try {
            for (int i = 0; i < 3; i++) {
                keyStrength = DefaultSize + i * 64; // obtain the key size 128,
                // 192, 256

                for (int j = 0; j < MODE.length; j++) {
                    if (MODE[j].equalsIgnoreCase("ECB")
                            || MODE[j].equalsIgnoreCase("PCBC")
                            || MODE[j].equalsIgnoreCase("CBC")) {
                        padKinds = PADDING.length;
                    } else {
                        padKinds = 1;
                    }

                    for (int k = 0; k < padKinds; k++) {
                        testCount++;
                        try {
                            if (!runTest(ALGORITHM, MODE[j], PADDING[k])) {
                                result = false;
                                failedCnt++;
                                failedList.append(ALGORITHM + "/" + MODE[j]
                                        + "/" + PADDING[k] + " ");
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            result = false;
                            failedCnt++;
                            failedList.append(ALGORITHM + "/" + MODE[j] + "/"
                                    + PADDING[k] + " ");
                        }

                    }
                }
            }

            if (result) {
                out.println("STATUS:Passed. Test " + testCount
                        + " cases, All Passed");
                return true;
            }
            out.println("STATUS:Failed. " + failedCnt + " Failed: "
                    + failedList);
            return false;

        } catch (Exception ex) {
            ex.printStackTrace();
            out.println("STATUS:Failed. Unexpected Exception: " + ex);
            return false;
        }
    }

    protected boolean runTest(String algo, String mo, String pad)
            throws Exception {
        boolean result = true;
        try {
            byte[] plainText = new byte[160000];
            new Random().nextBytes(plainText);

            String transformation = algo + "/" + mo + "/" + pad;
            ci = Cipher.getInstance(transformation, SUNJCE);
            KeyGenerator kg = KeyGenerator.getInstance(algo, SUNJCE);
            if (keyStrength > Cipher.getMaxAllowedKeyLength(transformation)) {
                // skip if this key length is larger than what's
                // configured in the jce jurisdiction policy files
                System.out.println(keyStrength
                        + " is larger than what's configured "
                        + "in the jce jurisdiction policy files");
                return result;
            }
            kg.init(keyStrength);
            key = kg.generateKey();

            if (!mo.equalsIgnoreCase("GCM")) {
                ci.init(Cipher.ENCRYPT_MODE, key, aps);
            } else {
                ci.init(Cipher.ENCRYPT_MODE, key);
            }
            byte[] cipherText = new byte[ci.getOutputSize(plainText.length)];
            int offset = ci.update(plainText, 0, plainText.length, cipherText,
                    0);
            ci.doFinal(cipherText, offset);

            if (!mo.equalsIgnoreCase("ECB")) {
                iv = ci.getIV();
                aps = new IvParameterSpec(iv);
            } else {
                aps = null;
            }

            if (!mo.equalsIgnoreCase("GCM")) {
                ci.init(Cipher.DECRYPT_MODE, key, aps);
            } else {
                ci.init(Cipher.DECRYPT_MODE, key, ci.getParameters());
            }
            byte[] recoveredText = new byte[ci.getOutputSize(cipherText.length)];
            int len = ci.doFinal(cipherText, 0, cipherText.length,
                    recoveredText);

            byte[] tmp = new byte[len];
            for (int i = 0; i < len; i++) {
                tmp[i] = recoveredText[i];
            }

            result = Arrays.equals(plainText, tmp);
        } catch (NoSuchAlgorithmException nsaEx) {
            nsaEx.printStackTrace();
            // CFB7 and OFB150 are negative test,SunJCE not support this
            // algorithm
            result = mo.equalsIgnoreCase("CFB7")
                    || mo.equalsIgnoreCase("OFB150");

        }
        return result;
    }
}