jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java
changeset 39750 982b75e31495
parent 35302 e4d2275861c3
child 39752 365d487907ac
equal deleted inserted replaced
39749:ea071138bf61 39750:982b75e31495
     1 /*
     1 /*
     2  * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    57 
    57 
    58     private static final int DEFAULT_TAG_LEN = 128; // same as SunJCE provider
    58     private static final int DEFAULT_TAG_LEN = 128; // same as SunJCE provider
    59 
    59 
    60     // buffer for storing AAD data; if null, meaning buffer content has been
    60     // buffer for storing AAD data; if null, meaning buffer content has been
    61     // supplied to native context
    61     // supplied to native context
    62     private ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream();
    62     private ByteArrayOutputStream aadBuffer;
    63 
    63 
    64     // buffer for storing input in decryption, not used for encryption
    64     // buffer for storing input in decryption, not used for encryption
    65     private ByteArrayOutputStream ibuffer = null;
    65     private ByteArrayOutputStream ibuffer;
    66 
    66 
    67     private int tagLen = DEFAULT_TAG_LEN;
    67     private int tagLen = DEFAULT_TAG_LEN;
    68 
    68 
    69     /*
    69     /*
    70      * variables used for performing the GCM (key+iv) uniqueness check.
    70      * variables used for performing the GCM (key+iv) uniqueness check.
    73      * ENCRYPTION operation. However, checking all past key + iv values
    73      * ENCRYPTION operation. However, checking all past key + iv values
    74      * isn't feasible. Thus, we only do a per-instance check of the
    74      * isn't feasible. Thus, we only do a per-instance check of the
    75      * key + iv values used in previous encryption.
    75      * key + iv values used in previous encryption.
    76      * For decryption operations, no checking is necessary.
    76      * For decryption operations, no checking is necessary.
    77      */
    77      */
    78     private boolean requireReinit = false;
    78     private boolean requireReinit;
    79     private byte[] lastEncKey = null;
    79     private byte[] lastEncKey = null;
    80     private byte[] lastEncIv = null;
    80     private byte[] lastEncIv = null;
    81 
    81 
    82     NativeGCMCipher(int fixedKeySize) throws NoSuchAlgorithmException {
    82     NativeGCMCipher(int fixedKeySize) throws NoSuchAlgorithmException {
    83         super(UcryptoMech.CRYPTO_AES_GCM, fixedKeySize);
    83         super(UcryptoMech.CRYPTO_AES_GCM, fixedKeySize);
    84     }
    84     }
    85 
    85 
    86     @Override
    86     @Override
    87     protected void ensureInitialized() {
    87     protected void ensureInitialized() {
    88         if (!initialized) {
    88         if (!initialized) {
    89             if (aadBuffer != null && aadBuffer.size() > 0) {
    89             byte[] aad = null;
    90                 init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
    90             if (aadBuffer != null) {
    91                 aadBuffer = null;
    91                 if (aadBuffer.size() > 0) {
    92             } else {
    92                     aad = aadBuffer.toByteArray();
    93                 init(encrypt, keyValue, iv, tagLen, null);
    93                 }
    94             }
    94             }
       
    95             init(encrypt, keyValue, iv, tagLen, aad);
       
    96             aadBuffer = null;
    95             if (!initialized) {
    97             if (!initialized) {
    96                 throw new UcryptoException("Cannot initialize Cipher");
    98                 throw new UcryptoException("Cannot initialize Cipher");
    97             }
    99             }
    98         }
   100         }
    99     }
   101     }
   183             opmode != Cipher.WRAP_MODE &&
   185             opmode != Cipher.WRAP_MODE &&
   184             opmode != Cipher.UNWRAP_MODE) {
   186             opmode != Cipher.UNWRAP_MODE) {
   185             throw new InvalidAlgorithmParameterException
   187             throw new InvalidAlgorithmParameterException
   186                 ("Unsupported mode: " + opmode);
   188                 ("Unsupported mode: " + opmode);
   187         }
   189         }
       
   190         aadBuffer = new ByteArrayOutputStream();
   188         boolean doEncrypt = (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE);
   191         boolean doEncrypt = (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE);
   189         byte[] keyBytes = key.getEncoded().clone();
   192         byte[] keyBytes = key.getEncoded().clone();
   190         byte[] ivBytes = null;
   193         byte[] ivBytes = null;
   191         if (params != null) {
   194         if (params != null) {
   192             if (!(params instanceof GCMParameterSpec)) {
   195             if (!(params instanceof GCMParameterSpec)) {
   217                 throw new InvalidAlgorithmParameterException
   220                 throw new InvalidAlgorithmParameterException
   218                     ("Cannot reuse iv for GCM encryption");
   221                     ("Cannot reuse iv for GCM encryption");
   219             }
   222             }
   220             lastEncIv = ivBytes;
   223             lastEncIv = ivBytes;
   221             lastEncKey = keyBytes;
   224             lastEncKey = keyBytes;
       
   225             ibuffer = null;
   222         } else {
   226         } else {
   223             requireReinit = false;
   227             requireReinit = false;
   224             ibuffer = new ByteArrayOutputStream();
   228             ibuffer = new ByteArrayOutputStream();
   225         }
   229         }
   226         init(doEncrypt, keyBytes, ivBytes, tagLen, null);
   230         init(doEncrypt, keyBytes, ivBytes, tagLen, null);
   244     }
   248     }
   245 
   249 
   246     // see JCE spec
   250     // see JCE spec
   247     @Override
   251     @Override
   248     protected synchronized byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
   252     protected synchronized byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
   249         if (aadBuffer != null && aadBuffer.size() > 0) {
   253         if (aadBuffer != null) {
   250             // init again with AAD data
   254             if (aadBuffer.size() > 0) {
   251             init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
   255                 // init again with AAD data
       
   256                 init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
       
   257             }
   252             aadBuffer = null;
   258             aadBuffer = null;
   253         }
   259         }
   254         if (requireReinit) {
   260         if (requireReinit) {
   255             throw new IllegalStateException
   261             throw new IllegalStateException
   256                 ("Must use either different key or iv for GCM encryption");
   262                 ("Must use either different key or iv for GCM encryption");
   272         if (out.length - outOfs < len) {
   278         if (out.length - outOfs < len) {
   273             throw new ShortBufferException("Output buffer must be " +
   279             throw new ShortBufferException("Output buffer must be " +
   274                  "(at least) " + len + " bytes long. Got: " +
   280                  "(at least) " + len + " bytes long. Got: " +
   275                  (out.length - outOfs));
   281                  (out.length - outOfs));
   276         }
   282         }
   277         if (aadBuffer != null && aadBuffer.size() > 0) {
   283         if (aadBuffer != null) {
   278             // init again with AAD data
   284             if (aadBuffer.size() > 0) {
   279             init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
   285                 // init again with AAD data
       
   286                 init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
       
   287             }
   280             aadBuffer = null;
   288             aadBuffer = null;
   281         }
   289         }
   282         if (requireReinit) {
   290         if (requireReinit) {
   283             throw new IllegalStateException
   291             throw new IllegalStateException
   284                 ("Must use either different key or iv for GCM encryption");
   292                 ("Must use either different key or iv for GCM encryption");
   372         if (out.length - outOfs < len) {
   380         if (out.length - outOfs < len) {
   373             throw new ShortBufferException("Output buffer must be "
   381             throw new ShortBufferException("Output buffer must be "
   374                 + "(at least) " + len + " bytes long. Got: " +
   382                 + "(at least) " + len + " bytes long. Got: " +
   375                 (out.length - outOfs));
   383                 (out.length - outOfs));
   376         }
   384         }
   377         if (aadBuffer != null && aadBuffer.size() > 0) {
   385         if (aadBuffer != null) {
   378             // init again with AAD data
   386             if (aadBuffer.size() > 0) {
   379             init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
   387                 // init again with AAD data
       
   388                 init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
       
   389             }
   380             aadBuffer = null;
   390             aadBuffer = null;
   381         }
   391         }
   382         if (requireReinit) {
   392         if (requireReinit) {
   383             throw new IllegalStateException
   393             throw new IllegalStateException
   384                 ("Must use either different key or iv for GCM encryption");
   394                 ("Must use either different key or iv for GCM encryption");