Path: blob/master/test/jdk/com/sun/crypto/provider/Cipher/AEAD/GCMParameterSpecTest.java
41161 views
/*1* Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.security.NoSuchAlgorithmException;24import java.security.NoSuchProviderException;25import java.util.Arrays;26import javax.crypto.SecretKey;27import javax.crypto.Cipher;28import javax.crypto.KeyGenerator;29import javax.crypto.spec.GCMParameterSpec;3031/*32* @test33* @bug 804859634* @summary Check if GCMParameterSpec works as expected35*/36public class GCMParameterSpecTest {3738private static final int[] IV_LENGTHS = { 96, 8, 1024 };39private static final int[] KEY_LENGTHS = { 128, 192, 256 };40private static final int[] DATA_LENGTHS = { 0, 128, 1024 };41private static final int[] AAD_LENGTHS = { 0, 128, 1024 };42private static final int[] TAG_LENGTHS = { 128, 120, 112, 104, 96 };43private static final int[] OFFSETS = { 0, 2, 5, 99 };44private static final String TRANSFORMATION = "AES/GCM/NoPadding";45private static final String TEMPLATE = "Test:\n tag = %d\n"46+ " IV length = %d\n data length = %d\n"47+ " AAD length = %d\n offset = %d\n keylength = %d\n";4849private final byte[] IV;50private final byte[] IVO;51private final byte[] data;52private final byte[] AAD;53private final SecretKey key;54private final int tagLength;55private final int IVlength;56private final int offset;5758/**59* Initialize IV, IV with offset, plain text, AAD and SecretKey60*61* @param keyLength length of a secret key62* @param tagLength tag length63* @param IVlength IV length64* @param offset offset in a buffer for IV65* @param textLength plain text length66* @param AADLength AAD length67*/68public GCMParameterSpecTest(int keyLength, int tagLength, int IVlength,69int offset, int textLength, int AADLength)70throws NoSuchAlgorithmException, NoSuchProviderException {71this.tagLength = tagLength; // save tag length72this.IVlength = IVlength; // save IV length73this.offset = offset; // save IV offset7475// prepare IV76IV = Helper.generateBytes(IVlength);7778// prepare IV with offset79IVO = new byte[this.IVlength + this.offset];80System.arraycopy(IV, 0, IVO, offset, this.IVlength);8182// prepare data83data = Helper.generateBytes(textLength);8485// prepare AAD86AAD = Helper.generateBytes(AADLength);8788// init a secret key89KeyGenerator kg = KeyGenerator.getInstance("AES", "SunJCE");90kg.init(keyLength);91key = kg.generateKey();92}9394/*95* Run the test for each key length, tag length, IV length, plain text96* length, AAD length and offset.97*/98public static void main(String[] args) throws Exception {99boolean success = true;100for (int k : KEY_LENGTHS) {101if (k > Cipher.getMaxAllowedKeyLength(TRANSFORMATION)) {102// skip this if this key length is larger than what's103// allowed in the jce jurisdiction policy files104continue;105}106for (int t : TAG_LENGTHS) {107for (int n : IV_LENGTHS) {108for (int p : DATA_LENGTHS) {109for (int a : AAD_LENGTHS) {110for (int o : OFFSETS) {111System.out.printf(TEMPLATE, t, n, p, a, o, k);112success &= new GCMParameterSpecTest(113k, t, n, o, p, a).doTest();114}115}116}117}118}119}120121if (!success) {122throw new RuntimeException("At least one test case failed");123}124}125126/*127* Run the test:128* - check if result of encryption of plain text is the same129* when parameters constructed with different GCMParameterSpec130* constructors are used131* - check if GCMParameterSpec.getTLen() is equal to actual tag length132* - check if ciphertext has the same length as plaintext133*/134private boolean doTest() throws Exception {135GCMParameterSpec spec1 = new GCMParameterSpec(tagLength, IV);136GCMParameterSpec spec2 = new GCMParameterSpec(tagLength, IVO, offset,137IVlength);138byte[] cipherText1 = getCipherTextBySpec(spec1);139if (cipherText1 == null) {140return false;141}142byte[] cipherText2 = getCipherTextBySpec(spec2);143if (cipherText2 == null) {144return false;145}146if (!Arrays.equals(cipherText1, cipherText2)) {147System.out.println("Cipher texts are different");148return false;149}150if (spec1.getTLen() != spec2.getTLen()) {151System.out.println("Tag lengths are not equal");152return false;153}154byte[] recoveredText1 = recoverCipherText(cipherText1, spec2);155if (recoveredText1 == null) {156return false;157}158byte[] recoveredText2 = recoverCipherText(cipherText2, spec1);159if (recoveredText2 == null) {160return false;161}162if (!Arrays.equals(recoveredText1, recoveredText2)) {163System.out.println("Recovered texts are different");164return false;165}166if (!Arrays.equals(recoveredText1, data)) {167System.out.println("Recovered and original texts are not equal");168return false;169}170171return true;172}173174/*175* Encrypt a plain text, and check if GCMParameterSpec.getIV()176* is equal to Cipher.getIV()177*/178private byte[] getCipherTextBySpec(GCMParameterSpec spec) throws Exception {179// init a cipher180Cipher cipher = createCipher(Cipher.ENCRYPT_MODE, spec);181cipher.updateAAD(AAD);182byte[] cipherText = cipher.doFinal(data);183184// check IVs185if (!Arrays.equals(cipher.getIV(), spec.getIV())) {186System.out.println("IV in parameters is incorrect");187return null;188}189if (spec.getTLen() != (cipherText.length - data.length) * 8) {190System.out.println("Tag length is incorrect");191return null;192}193return cipherText;194}195196private byte[] recoverCipherText(byte[] cipherText, GCMParameterSpec spec)197throws Exception {198// init a cipher199Cipher cipher = createCipher(Cipher.DECRYPT_MODE, spec);200201// check IVs202if (!Arrays.equals(cipher.getIV(), spec.getIV())) {203System.out.println("IV in parameters is incorrect");204return null;205}206207cipher.updateAAD(AAD);208return cipher.doFinal(cipherText);209}210211private Cipher createCipher(int mode, GCMParameterSpec spec)212throws Exception {213Cipher cipher = Cipher.getInstance(TRANSFORMATION, "SunJCE");214cipher.init(mode, key, spec);215return cipher;216}217}218219220