TestGCMWithSBE.java revision 10854:558e97e47abe
1/*
2 * Copyright (c) 2014, 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 8036970
27 * @summary Ensure that Cipher object is still usable after SBE.
28 * @author Valerie Peng
29 */
30
31import java.security.*;
32import javax.crypto.*;
33import javax.crypto.spec.*;
34import java.math.*;
35import com.sun.crypto.provider.*;
36
37import java.util.*;
38
39public class TestGCMWithSBE extends UcryptoTest {
40
41    private static final byte[] PT = new byte[32];
42    private static final byte[] ONE_BYTE = new byte[1];
43
44    public static void main(String[] args) throws Exception {
45        main(new TestGCMWithSBE(), null);
46    }
47
48    public void doTest(Provider p) throws Exception {
49        Cipher c;
50        try {
51            c = Cipher.getInstance("AES/GCM/NoPadding", p);
52        } catch (NoSuchAlgorithmException nsae) {
53            System.out.println("Skipping Test due to No GCM support");
54            return;
55        }
56
57        SecretKey key = new SecretKeySpec(new byte[16], "AES");
58        c.init(Cipher.ENCRYPT_MODE, key);
59
60        // test SBE with update calls
61        byte[] ct1 = null;
62        try {
63            c.update(PT, 0, PT.length, ONE_BYTE);
64        } catch (ShortBufferException sbe) {
65            // retry should work
66            ct1 = c.update(PT, 0, PT.length);
67        }
68
69        byte[] ct2PlusTag = null;
70        // test SBE with doFinal calls
71        try {
72            c.doFinal(ONE_BYTE, 0);
73        } catch (ShortBufferException sbe) {
74            // retry should work
75            ct2PlusTag = c.doFinal();
76        }
77
78        // Validate the retrieved parameters against the IV and tag length.
79        AlgorithmParameters params = c.getParameters();
80        if (params == null) {
81            throw new Exception("getParameters() should not return null");
82        }
83        GCMParameterSpec spec = params.getParameterSpec(GCMParameterSpec.class);
84        if (spec.getTLen() != (ct1.length + ct2PlusTag.length - PT.length)*8) {
85            throw new Exception("Parameters contains incorrect TLen value");
86        }
87        if (!Arrays.equals(spec.getIV(), c.getIV())) {
88            throw new Exception("Parameters contains incorrect IV value");
89        }
90
91        // Should be ok to use the same key+iv for decryption
92        c.init(Cipher.DECRYPT_MODE, key, params);
93        byte[] pt1 = c.update(ct1);
94        if (pt1 != null && pt1.length != 0) {
95            throw new Exception("Recovered text should not be returned "
96                + "to caller before tag verification");
97        }
98
99        byte[] pt2 = null;
100        try {
101            c.doFinal(ct2PlusTag, 0, ct2PlusTag.length, ONE_BYTE);
102        } catch (ShortBufferException sbe) {
103            // retry should work
104            pt2 = c.doFinal(ct2PlusTag);
105        }
106        if (!Arrays.equals(pt2, PT)) {
107            throw new Exception("decryption result mismatch");
108        }
109
110        System.out.println("Test Passed!");
111    }
112}
113
114