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