Wed, 30 Apr 2014 14:14:01 -0700
8035936: SIGBUS in StubRoutines::aesencryptBlock, solaris-sparc
Summary: Fix the arbitrary alignment issue in SPARC AES crypto stub routines.
Reviewed-by: kvn, iveresov
Contributed-by: shrinivas.joshi@oracle.com
kvn@4205 | 1 | /* |
kvn@6653 | 2 | * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. |
kvn@4205 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
kvn@4205 | 4 | * |
kvn@4205 | 5 | * This code is free software; you can redistribute it and/or modify it |
kvn@4205 | 6 | * under the terms of the GNU General Public License version 2 only, as |
kvn@4205 | 7 | * published by the Free Software Foundation. |
kvn@4205 | 8 | * |
kvn@4205 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
kvn@4205 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
kvn@4205 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
kvn@4205 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
kvn@4205 | 13 | * accompanied this code). |
kvn@4205 | 14 | * |
kvn@4205 | 15 | * You should have received a copy of the GNU General Public License version |
kvn@4205 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
kvn@4205 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
kvn@4205 | 18 | * |
kvn@4205 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
kvn@4205 | 20 | * or visit www.oracle.com if you need additional information or have any |
kvn@4205 | 21 | * questions. |
kvn@4205 | 22 | * |
kvn@4205 | 23 | */ |
kvn@4205 | 24 | |
kvn@4205 | 25 | /** |
kvn@4205 | 26 | * @author Tom Deneau |
kvn@4205 | 27 | */ |
kvn@4205 | 28 | |
kvn@4205 | 29 | import javax.crypto.Cipher; |
kvn@4205 | 30 | import javax.crypto.KeyGenerator; |
kvn@4205 | 31 | import javax.crypto.SecretKey; |
kvn@4205 | 32 | import javax.crypto.spec.IvParameterSpec; |
kvn@4205 | 33 | import javax.crypto.spec.SecretKeySpec; |
kvn@4205 | 34 | import java.security.AlgorithmParameters; |
kvn@4205 | 35 | |
kvn@4205 | 36 | import java.util.Random; |
kvn@4205 | 37 | import java.util.Arrays; |
kvn@4205 | 38 | |
kvn@4205 | 39 | abstract public class TestAESBase { |
kvn@4205 | 40 | int msgSize = Integer.getInteger("msgSize", 646); |
kvn@4205 | 41 | boolean checkOutput = Boolean.getBoolean("checkOutput"); |
kvn@4205 | 42 | boolean noReinit = Boolean.getBoolean("noReinit"); |
kvn@6653 | 43 | boolean testingMisalignment; |
kvn@6653 | 44 | private static final int ALIGN = 8; |
kvn@6653 | 45 | int encInputOffset = Integer.getInteger("encInputOffset", 0) % ALIGN; |
kvn@6653 | 46 | int encOutputOffset = Integer.getInteger("encOutputOffset", 0) % ALIGN; |
kvn@6653 | 47 | int decOutputOffset = Integer.getInteger("decOutputOffset", 0) % ALIGN; |
kvn@6653 | 48 | int lastChunkSize = Integer.getInteger("lastChunkSize", 32); |
kvn@4205 | 49 | int keySize = Integer.getInteger("keySize", 128); |
kvn@6653 | 50 | int inputLength; |
kvn@6653 | 51 | int encodeLength; |
kvn@6653 | 52 | int decodeLength; |
kvn@6653 | 53 | int decodeMsgSize; |
kvn@4205 | 54 | String algorithm = System.getProperty("algorithm", "AES"); |
kvn@4205 | 55 | String mode = System.getProperty("mode", "CBC"); |
kvn@6653 | 56 | String paddingStr = System.getProperty("paddingStr", "PKCS5Padding"); |
kvn@4205 | 57 | byte[] input; |
kvn@4205 | 58 | byte[] encode; |
kvn@4205 | 59 | byte[] expectedEncode; |
kvn@4205 | 60 | byte[] decode; |
kvn@4205 | 61 | byte[] expectedDecode; |
kvn@4205 | 62 | Random random = new Random(0); |
kvn@4205 | 63 | Cipher cipher; |
kvn@4205 | 64 | Cipher dCipher; |
kvn@4205 | 65 | AlgorithmParameters algParams; |
kvn@4205 | 66 | SecretKey key; |
kvn@4205 | 67 | |
kvn@4205 | 68 | static int numThreads = 0; |
kvn@4205 | 69 | int threadId; |
kvn@4205 | 70 | static synchronized int getThreadId() { |
kvn@4205 | 71 | int id = numThreads; |
kvn@4205 | 72 | numThreads++; |
kvn@4205 | 73 | return id; |
kvn@4205 | 74 | } |
kvn@4205 | 75 | |
kvn@4205 | 76 | abstract public void run(); |
kvn@4205 | 77 | |
kvn@4205 | 78 | public void prepare() { |
kvn@4205 | 79 | try { |
kvn@6653 | 80 | System.out.println("\nalgorithm=" + algorithm + ", mode=" + mode + ", paddingStr=" + paddingStr + ", msgSize=" + msgSize + ", keySize=" + keySize + ", noReinit=" + noReinit + ", checkOutput=" + checkOutput + ", encInputOffset=" + encInputOffset + ", encOutputOffset=" + encOutputOffset + ", decOutputOffset=" + decOutputOffset + ", lastChunkSize=" +lastChunkSize ); |
kvn@6653 | 81 | |
kvn@6653 | 82 | if (encInputOffset % ALIGN != 0 || encOutputOffset % ALIGN != 0 || decOutputOffset % ALIGN !=0 ) |
kvn@6653 | 83 | testingMisalignment = true; |
kvn@4205 | 84 | |
kvn@4205 | 85 | int keyLenBytes = (keySize == 0 ? 16 : keySize/8); |
kvn@4205 | 86 | byte keyBytes[] = new byte[keyLenBytes]; |
kvn@4205 | 87 | if (keySize == 128) |
kvn@4205 | 88 | keyBytes = new byte[] {-8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7}; |
kvn@4205 | 89 | else |
kvn@4205 | 90 | random.nextBytes(keyBytes); |
kvn@4205 | 91 | |
kvn@4205 | 92 | key = new SecretKeySpec(keyBytes, algorithm); |
kvn@4205 | 93 | if (threadId == 0) { |
kvn@4205 | 94 | System.out.println("Algorithm: " + key.getAlgorithm() + "(" |
kvn@4205 | 95 | + key.getEncoded().length * 8 + "bit)"); |
kvn@4205 | 96 | } |
kvn@4205 | 97 | |
kvn@4205 | 98 | cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE"); |
kvn@4205 | 99 | dCipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE"); |
kvn@4205 | 100 | |
kvn@4363 | 101 | if (mode.equals("CBC")) { |
kvn@4363 | 102 | int ivLen = (algorithm.equals("AES") ? 16 : algorithm.equals("DES") ? 8 : 0); |
kvn@4363 | 103 | IvParameterSpec initVector = new IvParameterSpec(new byte[ivLen]); |
kvn@4363 | 104 | cipher.init(Cipher.ENCRYPT_MODE, key, initVector); |
kvn@4363 | 105 | } else { |
kvn@4363 | 106 | algParams = cipher.getParameters(); |
kvn@4363 | 107 | cipher.init(Cipher.ENCRYPT_MODE, key, algParams); |
kvn@4363 | 108 | } |
kvn@4205 | 109 | algParams = cipher.getParameters(); |
kvn@4205 | 110 | dCipher.init(Cipher.DECRYPT_MODE, key, algParams); |
kvn@4205 | 111 | if (threadId == 0) { |
kvn@4205 | 112 | childShowCipher(); |
kvn@4205 | 113 | } |
kvn@4205 | 114 | |
kvn@6653 | 115 | inputLength = msgSize + encInputOffset; |
kvn@6653 | 116 | if (testingMisalignment) { |
kvn@6653 | 117 | encodeLength = cipher.getOutputSize(msgSize - lastChunkSize) + encOutputOffset; |
kvn@6653 | 118 | encodeLength += cipher.getOutputSize(lastChunkSize); |
kvn@6653 | 119 | decodeLength = dCipher.getOutputSize(encodeLength - lastChunkSize) + decOutputOffset; |
kvn@6653 | 120 | decodeLength += dCipher.getOutputSize(lastChunkSize); |
kvn@6653 | 121 | } else { |
kvn@6653 | 122 | encodeLength = cipher.getOutputSize(msgSize) + encOutputOffset; |
kvn@6653 | 123 | decodeLength = dCipher.getOutputSize(encodeLength) + decOutputOffset; |
kvn@6653 | 124 | } |
kvn@6653 | 125 | |
kvn@6653 | 126 | input = new byte[inputLength]; |
kvn@6653 | 127 | for (int i=encInputOffset, j=0; i<inputLength; i++, j++) { |
kvn@6653 | 128 | input[i] = (byte) (j & 0xff); |
kvn@6653 | 129 | } |
kvn@6653 | 130 | |
kvn@4205 | 131 | // do one encode and decode in preparation |
kvn@6653 | 132 | encode = new byte[encodeLength]; |
kvn@6653 | 133 | decode = new byte[decodeLength]; |
kvn@6653 | 134 | if (testingMisalignment) { |
kvn@6653 | 135 | decodeMsgSize = cipher.update(input, encInputOffset, (msgSize - lastChunkSize), encode, encOutputOffset); |
kvn@6653 | 136 | decodeMsgSize += cipher.doFinal(input, (encInputOffset + msgSize - lastChunkSize), lastChunkSize, encode, (encOutputOffset + decodeMsgSize)); |
kvn@6653 | 137 | |
kvn@6653 | 138 | int tempSize = dCipher.update(encode, encOutputOffset, (decodeMsgSize - lastChunkSize), decode, decOutputOffset); |
kvn@6653 | 139 | dCipher.doFinal(encode, (encOutputOffset + decodeMsgSize - lastChunkSize), lastChunkSize, decode, (decOutputOffset + tempSize)); |
kvn@6653 | 140 | } else { |
kvn@6653 | 141 | decodeMsgSize = cipher.doFinal(input, encInputOffset, msgSize, encode, encOutputOffset); |
kvn@6653 | 142 | dCipher.doFinal(encode, encOutputOffset, decodeMsgSize, decode, decOutputOffset); |
kvn@6653 | 143 | } |
kvn@4205 | 144 | if (checkOutput) { |
kvn@4205 | 145 | expectedEncode = (byte[]) encode.clone(); |
kvn@4205 | 146 | expectedDecode = (byte[]) decode.clone(); |
kvn@4205 | 147 | showArray(key.getEncoded() , "key: "); |
kvn@4205 | 148 | showArray(input, "input: "); |
kvn@4205 | 149 | showArray(encode, "encode: "); |
kvn@4205 | 150 | showArray(decode, "decode: "); |
kvn@4205 | 151 | } |
kvn@4205 | 152 | } |
kvn@4205 | 153 | catch (Exception e) { |
kvn@4205 | 154 | e.printStackTrace(); |
kvn@4205 | 155 | System.exit(1); |
kvn@4205 | 156 | } |
kvn@4205 | 157 | } |
kvn@4205 | 158 | |
kvn@4205 | 159 | void showArray(byte b[], String name) { |
kvn@4205 | 160 | System.out.format("%s [%d]: ", name, b.length); |
kvn@4205 | 161 | for (int i=0; i<Math.min(b.length, 32); i++) { |
kvn@4205 | 162 | System.out.format("%02x ", b[i] & 0xff); |
kvn@4205 | 163 | } |
kvn@4205 | 164 | System.out.println(); |
kvn@4205 | 165 | } |
kvn@4205 | 166 | |
kvn@4205 | 167 | void compareArrays(byte b[], byte exp[]) { |
kvn@4205 | 168 | if (b.length != exp.length) { |
kvn@4205 | 169 | System.out.format("different lengths for actual and expected output arrays\n"); |
kvn@4205 | 170 | showArray(b, "test: "); |
kvn@4205 | 171 | showArray(exp, "exp : "); |
kvn@4205 | 172 | System.exit(1); |
kvn@4205 | 173 | } |
kvn@4205 | 174 | for (int i=0; i< exp.length; i++) { |
kvn@4205 | 175 | if (b[i] != exp[i]) { |
kvn@4205 | 176 | System.out.format("output error at index %d: got %02x, expected %02x\n", i, b[i] & 0xff, exp[i] & 0xff); |
kvn@4205 | 177 | showArray(b, "test: "); |
kvn@4205 | 178 | showArray(exp, "exp : "); |
kvn@4205 | 179 | System.exit(1); |
kvn@4205 | 180 | } |
kvn@4205 | 181 | } |
kvn@4205 | 182 | } |
kvn@4205 | 183 | |
kvn@4205 | 184 | |
kvn@4205 | 185 | void showCipher(Cipher c, String kind) { |
kvn@4205 | 186 | System.out.println(kind + " cipher provider: " + cipher.getProvider()); |
kvn@4205 | 187 | System.out.println(kind + " cipher algorithm: " + cipher.getAlgorithm()); |
kvn@4205 | 188 | } |
kvn@4205 | 189 | |
kvn@4205 | 190 | abstract void childShowCipher(); |
kvn@4205 | 191 | } |