gt:         if (params != null) {
context: /* Copyright (c) 2019, 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.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * 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.
   */
  package sun.security.pkcs11;
  
  import java.io.ByteArrayOutputStream;
  import java.nio.ByteBuffer;
  import java.util.Arrays;
  import java.util.Locale;
  
  import java.security.*;
  import java.security.spec.*;
  
  import javax.crypto.*;
  import javax.crypto.spec.*;
  
  import sun.nio.ch.DirectBuffer;
  import sun.security.jca.JCAUtil;
  import sun.security.pkcs11.wrapper.*;
  import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
  
  /**
   * P11 AEAD Cipher implementation class. This class currently supports
   * AES with GCM mode.
   *
   * Note that AEAD modes do not use padding, so this class does not have
   * its own padding impl. In addition, NSS CKM_AES_GCM only supports single-part
   * encryption/decryption, thus the current impl uses PKCS#11 C_Encrypt/C_Decrypt
   * calls and buffers data until doFinal is called.
   *
   * Note that PKCS#11 standard currently only supports GCM and CCM AEAD modes.
   * There are no provisions for other AEAD modes yet.
   *
   * @since   13
   */
  final class P11AEADCipher extends CipherSpi {
  
      // mode constant for GCM mode
      private static final int MODE_GCM = 10;
  
      // default constants for GCM
      private static final int GCM_DEFAULT_TAG_LEN = 16;
      private static final int GCM_DEFAULT_IV_LEN = 16;
  
      private static final String ALGO = "AES";
  
      // token instance
      private final Token token;
  
      // mechanism id
      private final long mechanism;
  
      // mode, one of MODE_* above
      private final int blockMode;
  
      // acceptable key size, -1 if more than 1 key sizes are accepted
      private final int fixedKeySize;
  
      // associated session, if any
      private Session session = null;
  
      // key, if init() was called
      private P11Key p11Key = null;
  
      // flag indicating whether an operation is initialized
      private boolean initialized = false;
  
      // falg indicating encrypt or decrypt mode
      private boolean encrypt = true;
  
      // parameters
      private byte[] iv = null;
      private int tagLen = -1;
      private SecureRandom random = JCAUtil.getSecureRandom();
  
      // dataBuffer is cleared upon doFinal calls
      private ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream();
      // aadBuffer is cleared upon successful init calls
      private ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream();
      private boolean updateCalled = false;
  
      private boolean requireReinit = false;
      private P11Key lastEncKey = null;
      private byte[] lastEncIv = null;
  
      P11AEADCipher(Token token, String algorithm, long mechanism)
              throws PKCS11Exception, NoSuchAlgorithmException {
          super();
          this.token = token;
          this.mechanism = mechanism;
  
          String[] algoParts = algorithm.split("/");
          if (algoParts.length != 3) {
              throw new ProviderException("Unsupported Transformation format: " +
                      algorithm);
          }
          if (!algoParts[0].startsWith("AES")) {
              throw new ProviderException("Only support AES for AEAD cipher mode");
          }
          int index = algoParts[0].indexOf('_');
          if (index != -1) {
              // should be well-formed since we specify what we support
              fixedKeySize = Integer.parseInt(algoParts[0].substring(index+1)) >> 3;
          } else {
              fixedKeySize = -1;
          }
          this.blockMode = parseMode(algoParts[1]);
          if (!algoParts[2].equals("NoPadding")) {
              throw new ProviderException("Only NoPadding is supported for AEAD cipher mode");
          }
      }
  
      protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
          // Disallow change of mode for now since currently it's explicitly
          // defined in transformation strings
          throw new NoSuchAlgorithmException("Unsupported mode " + mode);
      }
  
      private int parseMode(String mode) throws NoSuchAlgorithmException {
          mode = mode.toUpperCase(Locale.ENGLISH);
          int result;
          if (mode.equals("GCM")) {
              result = MODE_GCM;
          } else {
              throw new NoSuchAlgorithmException("Unsupported mode " + mode);
          }
          return result;
      }
  
      // see JCE spec
      protected void engineSetPadding(String padding)
              throws NoSuchPaddingException {
          // Disallow change of padding for now since currently it's explicitly
          // defined in transformation strings
          throw new NoSuchPaddingException("Unsupported padding " + padding);
      }
  
      // see JCE spec
      protected int engineGetBlockSize() {
          return 16; // constant; only AES is supported
      }
  
      // see JCE spec
      protected int engineGetOutputSize(int inputLen) {
          return doFinalLength(inputLen);
      }
  
      // see JCE spec
      protected byte[] engineGetIV() {
          return (iv == null) ? null : iv.clone();
      }
  
      // see JCE spec
      protected AlgorithmParameters engineGetParameters() {
          if (encrypt && iv == null && tagLen == -1) {
              switch (blockMode) {
                  case MODE_GCM:
                      iv = new byte[GCM_DEFAULT_IV_LEN];
                      tagLen = GCM_DEFAULT_TAG_LEN;
                      break;
                  default:
                      throw new ProviderException("Unsupported mode");
              }
              random.nextBytes(iv);
          }
          try {
              AlgorithmParameterSpec spec;
              String apAlgo;
              switch (blockMode) {
                  case MODE_GCM:
                      apAlgo = "GCM";
                      spec = new GCMParameterSpec(tagLen << 3, iv);
                      break;
                  default:
                      throw new ProviderException("Unsupported mode");
              }
              AlgorithmParameters params =
                  AlgorithmParameters.getInstance(apAlgo);
              params.init(spec);
              return params;
          } catch (GeneralSecurityException e) {
              // NoSuchAlgorithmException, NoSuchProviderException
              // InvalidParameterSpecException
              throw new ProviderException("Could not encode parameters", e);
          }
      }
  
      // see JCE spec
      protected void engineInit(int opmode, Key key, SecureRandom sr)
              throws InvalidKeyException {
          if (opmode == Cipher.DECRYPT_MODE) {
              throw new InvalidKeyException("Parameters required for decryption");
          }
          updateCalled = false;
          try {
              implInit(opmode, key, null, -1, sr);
          } catch (InvalidAlgorithmParameterException e) {
              throw new InvalidKeyException("init() failed", e);
          }
      }
  
      // see JCE spec
      protected void engineInit(int opmode, Key key,
              AlgorithmParameterSpec params, SecureRandom sr)
              throws InvalidKeyException, InvalidAlgorithmParameterException {
          if (opmode == Cipher.DECRYPT_MODE && params == null) {
              throw new InvalidAlgorithmParameterException
                      ("Parameters required for decryption");
          }
          updateCalled = false;
          byte[] ivValue = null;
          int tagLen = -1;
  