jdk/src/share/classes/com/sun/crypto/provider/CipherCore.java
author valeriep
Tue, 19 Nov 2013 15:29:56 -0800
changeset 21837 0c41fa97176a
parent 20752 f0f0acea9113
child 25214 78a0f67da1d4
permissions -rw-r--r--
8026943: SQE test jce/Global/Cipher/SameBuffer failed Summary: Always use different input/output buffers when calling FeedbackCipher objects Reviewed-by: mullan
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
     2
 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package com.sun.crypto.provider;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
    28
import java.util.Arrays;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.util.Locale;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.security.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.security.spec.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import javax.crypto.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import javax.crypto.spec.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import javax.crypto.BadPaddingException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
 * This class represents the symmetric algorithms in its various modes
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
 * (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>, <code>CBC</code>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 * <code>PCBC</code>, <code>CTR</code>, and <code>CTS</code>) and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
 * padding schemes (<code>PKCS5Padding</code>, <code>NoPadding</code>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
 * <code>ISO10126Padding</code>).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
 * @author Gigi Ankeny
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 * @author Jan Luehe
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 * @see ElectronicCodeBook
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * @see CipherFeedback
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 * @see OutputFeedback
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * @see CipherBlockChaining
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * @see PCBC
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * @see CounterMode
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * @see CipherTextStealing
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
final class CipherCore {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
     * internal buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
    private byte[] buffer = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    /*
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
    63
     * block size of cipher in bytes
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    private int blockSize = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
     * unit size (number of input bytes that can be processed at a time)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    private int unitBytes = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
     * index of the content size left in the buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
    private int buffered = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
     * minimum number of bytes in the buffer required for
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
     * FeedbackCipher.encryptFinal()/decryptFinal() call.
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
    80
     * update() must buffer this many bytes before starting
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
     * to encrypt/decrypt data.
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
    82
     * currently, only the following cases have non-zero values:
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
    83
     * 1) CTS mode - due to its special handling on the last two blocks
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
    84
     * (the last one may be incomplete).
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
    85
     * 2) GCM mode + decryption - due to its trailing tag bytes
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    private int minBytes = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
     * number of bytes needed to make the total input length a multiple
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
     * of the blocksize (this is used in feedback mode, when the number of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
     * input bytes that are processed at a time is different from the block
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
     * size)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
    private int diffBlocksize = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
     * padding class
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
    private Padding padding = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
     * internal cipher engine
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
    private FeedbackCipher cipher = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
     * the cipher mode
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    private int cipherMode = ECB_MODE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
     * are we encrypting or decrypting?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
    private boolean decrypting = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
     * Block Mode constants
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
    private static final int ECB_MODE = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
    private static final int CBC_MODE = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    private static final int CFB_MODE = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
    private static final int OFB_MODE = 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
    private static final int PCBC_MODE = 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
    private static final int CTR_MODE = 5;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    private static final int CTS_MODE = 6;
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   127
    private static final int GCM_MODE = 7;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   128
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   129
    /*
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   130
     * variables used for performing the GCM (key+iv) uniqueness check.
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   131
     * To use GCM mode safely, the cipher object must be re-initialized
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   132
     * with a different combination of key + iv values for each
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   133
     * encryption operation. However, checking all past key + iv values
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   134
     * isn't feasible. Thus, we only do a per-instance check of the
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   135
     * key + iv values used in previous encryption.
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   136
     * For decryption operations, no checking is necessary.
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   137
     * NOTE: this key+iv check have to be done inside CipherCore class
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   138
     * since CipherCore class buffers potential tag bytes in GCM mode
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   139
     * and may not call GaloisCounterMode when there isn't sufficient
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   140
     * input to process.
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   141
     */
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   142
    private boolean requireReinit = false;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   143
    private byte[] lastEncKey = null;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   144
    private byte[] lastEncIv = null;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
     * Creates an instance of CipherCore with default ECB mode and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
     * PKCS5Padding.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
    CipherCore(SymmetricCipher impl, int blkSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
        blockSize = blkSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
        unitBytes = blkSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
        diffBlocksize = blkSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
         * The buffer should be usable for all cipher mode and padding
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
         * schemes. Thus, it has to be at least (blockSize+1) for CTS.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
         * In decryption mode, it also hold the possible padding block.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
        buffer = new byte[blockSize*2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
        // set mode and padding
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
        cipher = new ElectronicCodeBook(impl);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
        padding = new PKCS5Padding(blockSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
     * Sets the mode of this cipher.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
     * @param mode the cipher mode
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
     * @exception NoSuchAlgorithmException if the requested cipher mode does
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   173
     * not exist for this cipher
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
    void setMode(String mode) throws NoSuchAlgorithmException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        if (mode == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
            throw new NoSuchAlgorithmException("null mode");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
        String modeUpperCase = mode.toUpperCase(Locale.ENGLISH);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
        if (modeUpperCase.equals("ECB")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
        SymmetricCipher rawImpl = cipher.getEmbeddedCipher();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
        if (modeUpperCase.equals("CBC")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
            cipherMode = CBC_MODE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
            cipher = new CipherBlockChaining(rawImpl);
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   189
        } else if (modeUpperCase.equals("CTS")) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
            cipherMode = CTS_MODE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
            cipher = new CipherTextStealing(rawImpl);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
            minBytes = blockSize+1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
            padding = null;
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   194
        } else if (modeUpperCase.equals("CTR")) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
            cipherMode = CTR_MODE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
            cipher = new CounterMode(rawImpl);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
            unitBytes = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
            padding = null;
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   199
        }  else if (modeUpperCase.startsWith("GCM")) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   200
            // can only be used for block ciphers w/ 128-bit block size
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   201
            if (blockSize != 16) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   202
                throw new NoSuchAlgorithmException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   203
                    ("GCM mode can only be used for AES cipher");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   204
            }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   205
            cipherMode = GCM_MODE;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   206
            cipher = new GaloisCounterMode(rawImpl);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   207
            padding = null;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   208
        } else if (modeUpperCase.startsWith("CFB")) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
            cipherMode = CFB_MODE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
            unitBytes = getNumOfUnit(mode, "CFB".length(), blockSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
            cipher = new CipherFeedback(rawImpl, unitBytes);
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   212
        } else if (modeUpperCase.startsWith("OFB")) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
            cipherMode = OFB_MODE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
            unitBytes = getNumOfUnit(mode, "OFB".length(), blockSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
            cipher = new OutputFeedback(rawImpl, unitBytes);
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   216
        } else if (modeUpperCase.equals("PCBC")) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
            cipherMode = PCBC_MODE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
            cipher = new PCBC(rawImpl);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
        else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
            throw new NoSuchAlgorithmException("Cipher mode: " + mode
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
                                               + " not found");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
    private static int getNumOfUnit(String mode, int offset, int blockSize)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
        throws NoSuchAlgorithmException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        int result = blockSize; // use blockSize as default value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
        if (mode.length() > offset) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
            int numInt;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
                Integer num = Integer.valueOf(mode.substring(offset));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
                numInt = num.intValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
                result = numInt >> 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
            } catch (NumberFormatException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
                throw new NoSuchAlgorithmException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
                    ("Algorithm mode: " + mode + " not implemented");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
            if ((numInt % 8 != 0) || (result > blockSize)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
                throw new NoSuchAlgorithmException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
                    ("Invalid algorithm mode: " + mode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
        return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   247
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
     * Sets the padding mechanism of this cipher.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
     * @param padding the padding mechanism
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
     * @exception NoSuchPaddingException if the requested padding mechanism
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
     * does not exist
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
    void setPadding(String paddingScheme)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
        throws NoSuchPaddingException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
        if (paddingScheme == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
            throw new NoSuchPaddingException("null padding");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
        if (paddingScheme.equalsIgnoreCase("NoPadding")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
            padding = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        } else if (paddingScheme.equalsIgnoreCase("ISO10126Padding")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
            padding = new ISO10126Padding(blockSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
        } else if (!paddingScheme.equalsIgnoreCase("PKCS5Padding")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
            throw new NoSuchPaddingException("Padding: " + paddingScheme
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
                                             + " not implemented");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
        if ((padding != null) &&
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   271
            ((cipherMode == CTR_MODE) || (cipherMode == CTS_MODE)
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   272
             || (cipherMode == GCM_MODE))) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
            padding = null;
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   274
            String modeStr = null;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   275
            switch (cipherMode) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   276
            case CTR_MODE:
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   277
                modeStr = "CTR";
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   278
                break;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   279
            case GCM_MODE:
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   280
                modeStr = "GCM";
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   281
                break;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   282
            case CTS_MODE:
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   283
                modeStr = "CTS";
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   284
                break;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   285
            default:
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   286
                // should never happen
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   287
            }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   288
            if (modeStr != null) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   289
                throw new NoSuchPaddingException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   290
                    (modeStr + " mode must be used with NoPadding");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   291
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
     * Returns the length in bytes that an output buffer would need to be in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
     * order to hold the result of the next <code>update</code> or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
     * <code>doFinal</code> operation, given the input length
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
     * <code>inputLen</code> (in bytes).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
     * <p>This call takes into account any unprocessed (buffered) data from a
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   302
     * previous <code>update</code> call, padding, and AEAD tagging.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
     * <p>The actual output length of the next <code>update</code> or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
     * <code>doFinal</code> call may be smaller than the length returned by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
     * this method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
     * @param inputLen the input length (in bytes)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
     * @return the required output buffer size (in bytes)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
    int getOutputSize(int inputLen) {
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   313
        // estimate based on the maximum
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   314
        return getOutputSizeByOperation(inputLen, true);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   317
    private int getOutputSizeByOperation(int inputLen, boolean isDoFinal) {
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   318
        int totalLen = buffered + inputLen + cipher.getBufferedLength();
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   319
        switch (cipherMode) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   320
        case GCM_MODE:
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   321
            if (isDoFinal) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   322
                int tagLen = ((GaloisCounterMode) cipher).getTagLen();
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   323
                if (!decrypting) {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   324
                    totalLen += tagLen;
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   325
                } else {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   326
                    totalLen -= tagLen;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   327
                }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   328
            }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   329
            if (totalLen < 0) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   330
                totalLen = 0;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   331
            }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   332
            break;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   333
        default:
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   334
            if (padding != null && !decrypting) {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   335
                if (unitBytes != blockSize) {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   336
                    if (totalLen < diffBlocksize) {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   337
                        totalLen = diffBlocksize;
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   338
                    } else {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   339
                        int residue = (totalLen - diffBlocksize) % blockSize;
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   340
                        totalLen += (blockSize - residue);
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   341
                    }
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   342
                } else {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   343
                    totalLen += padding.padLength(totalLen);
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   344
                }
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   345
            }
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   346
            break;
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   347
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   348
        return totalLen;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   349
    }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   350
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
     * Returns the initialization vector (IV) in a new buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
     * <p>This is useful in the case where a random IV has been created
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
     * (see <a href = "#init">init</a>),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
     * or in the context of password-based encryption or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
     * decryption, where the IV is derived from a user-provided password.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
     * @return the initialization vector in a new buffer, or null if the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
     * underlying algorithm does not use an IV, or if the IV has not yet
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
     * been set.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
    byte[] getIV() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
        byte[] iv = cipher.getIV();
10336
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   365
        return (iv == null) ? null : iv.clone();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
     * Returns the parameters used with this cipher.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
     * <p>The returned parameters may be the same that were used to initialize
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
     * this cipher, or may contain the default set of parameters or a set of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
     * randomly generated parameters used by the underlying cipher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
     * implementation (provided that the underlying cipher implementation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
     * uses a default set of parameters or creates new parameters if it needs
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
     * parameters but was not initialized with any).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
     * @return the parameters used with this cipher, or null if this cipher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
     * does not use any parameters.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
    AlgorithmParameters getParameters(String algName) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   382
        if (cipherMode == ECB_MODE) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   383
            return null;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   384
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
        AlgorithmParameters params = null;
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   386
        AlgorithmParameterSpec spec;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
        byte[] iv = getIV();
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   388
        if (iv == null) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   389
            // generate spec using default value
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   390
            if (cipherMode == GCM_MODE) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   391
                iv = new byte[GaloisCounterMode.DEFAULT_IV_LEN];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
            } else {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   393
                iv = new byte[blockSize];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
            }
15010
ec6b49ce42b1 8004044: Lazily instantiate SunJCE.RANDOM
valeriep
parents: 15008
diff changeset
   395
            SunJCE.getRandom().nextBytes(iv);
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   396
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   397
        if (cipherMode == GCM_MODE) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   398
            algName = "GCM";
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   399
            spec = new GCMParameterSpec
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   400
                (((GaloisCounterMode) cipher).getTagLen()*8, iv);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   401
        } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   402
           if (algName.equals("RC2")) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   403
               RC2Crypt rawImpl = (RC2Crypt) cipher.getEmbeddedCipher();
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   404
               spec = new RC2ParameterSpec
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   405
                   (rawImpl.getEffectiveKeyBits(), iv);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   406
           } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   407
               spec = new IvParameterSpec(iv);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   408
           }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   409
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   410
        try {
16909
78a1749a43e2 7171982: Cipher getParameters() throws RuntimeException: Cannot find SunJCE provider
vinnie
parents: 15010
diff changeset
   411
            params = AlgorithmParameters.getInstance(algName,
78a1749a43e2 7171982: Cipher getParameters() throws RuntimeException: Cannot find SunJCE provider
vinnie
parents: 15010
diff changeset
   412
                    SunJCE.getInstance());
78a1749a43e2 7171982: Cipher getParameters() throws RuntimeException: Cannot find SunJCE provider
vinnie
parents: 15010
diff changeset
   413
            params.init(spec);
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   414
        } catch (NoSuchAlgorithmException nsae) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   415
            // should never happen
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   416
            throw new RuntimeException("Cannot find " + algName +
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   417
                " AlgorithmParameters implementation in SunJCE provider");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   418
        } catch (InvalidParameterSpecException ipse) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   419
            // should never happen
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   420
            throw new RuntimeException(spec.getClass() + " not supported");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
        return params;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
     * Initializes this cipher with a key and a source of randomness.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
     * <p>The cipher is initialized for one of the following four operations:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
     * encryption, decryption, key wrapping or key unwrapping, depending on
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
     * the value of <code>opmode</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
     * <p>If this cipher requires an initialization vector (IV), it will get
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
     * it from <code>random</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
     * This behaviour should only be used in encryption or key wrapping
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
     * mode, however.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
     * When initializing a cipher that requires an IV for decryption or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
     * key unwrapping, the IV
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
     * (same IV that was used for encryption or key wrapping) must be provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
     * explicitly as a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
     * parameter, in order to get the correct result.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
     * <p>This method also cleans existing buffer and other related state
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
     * information.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
     * @param opmode the operation mode of this cipher (this is one of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
     * the following:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
     * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
     * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
     * @param key the secret key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
     * @param random the source of randomness
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
     * @exception InvalidKeyException if the given key is inappropriate for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
     * initializing this cipher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
    void init(int opmode, Key key, SecureRandom random)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
            throws InvalidKeyException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
            init(opmode, key, (AlgorithmParameterSpec)null, random);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
        } catch (InvalidAlgorithmParameterException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
            throw new InvalidKeyException(e.getMessage());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
     * Initializes this cipher with a key, a set of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
     * algorithm parameters, and a source of randomness.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
     * <p>The cipher is initialized for one of the following four operations:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
     * encryption, decryption, key wrapping or key unwrapping, depending on
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
     * the value of <code>opmode</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
     * <p>If this cipher (including its underlying feedback or padding scheme)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
     * requires any random bytes, it will get them from <code>random</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
     * @param opmode the operation mode of this cipher (this is one of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
     * the following:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
     * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
     * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
     * @param key the encryption key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
     * @param params the algorithm parameters
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
     * @param random the source of randomness
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
     * @exception InvalidKeyException if the given key is inappropriate for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
     * initializing this cipher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
     * @exception InvalidAlgorithmParameterException if the given algorithm
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
     * parameters are inappropriate for this cipher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
    void init(int opmode, Key key, AlgorithmParameterSpec params,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
            SecureRandom random)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
            throws InvalidKeyException, InvalidAlgorithmParameterException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
        decrypting = (opmode == Cipher.DECRYPT_MODE)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
                  || (opmode == Cipher.UNWRAP_MODE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
        byte[] keyBytes = getKeyBytes(key);
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   495
        int tagLen = -1;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   496
        byte[] ivBytes = null;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   497
        if (params != null) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   498
            if (cipherMode == GCM_MODE) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   499
                if (params instanceof GCMParameterSpec) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   500
                    tagLen = ((GCMParameterSpec)params).getTLen();
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   501
                    if (tagLen < 96 || tagLen > 128 || ((tagLen & 0x07) != 0)) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   502
                        throw new InvalidAlgorithmParameterException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   503
                            ("Unsupported TLen value; must be one of " +
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   504
                             "{128, 120, 112, 104, 96}");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   505
                    }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   506
                    tagLen = tagLen >> 3;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   507
                    ivBytes = ((GCMParameterSpec)params).getIV();
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   508
                } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   509
                    throw new InvalidAlgorithmParameterException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   510
                        ("Unsupported parameter: " + params);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   511
               }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   512
            } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   513
                if (params instanceof IvParameterSpec) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   514
                    ivBytes = ((IvParameterSpec)params).getIV();
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   515
                    if ((ivBytes == null) || (ivBytes.length != blockSize)) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   516
                        throw new InvalidAlgorithmParameterException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   517
                            ("Wrong IV length: must be " + blockSize +
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   518
                             " bytes long");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   519
                    }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   520
                } else if (params instanceof RC2ParameterSpec) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   521
                    ivBytes = ((RC2ParameterSpec)params).getIV();
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   522
                    if ((ivBytes != null) && (ivBytes.length != blockSize)) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   523
                        throw new InvalidAlgorithmParameterException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   524
                            ("Wrong IV length: must be " + blockSize +
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   525
                             " bytes long");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   526
                    }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   527
                } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   528
                    throw new InvalidAlgorithmParameterException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   529
                        ("Unsupported parameter: " + params);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   530
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
        if (cipherMode == ECB_MODE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
            if (ivBytes != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
                throw new InvalidAlgorithmParameterException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
                                                ("ECB mode cannot use IV");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
            }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   538
        } else if (ivBytes == null)  {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
            if (decrypting) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
                throw new InvalidAlgorithmParameterException("Parameters "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
                                                             + "missing");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
            }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   543
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
            if (random == null) {
15010
ec6b49ce42b1 8004044: Lazily instantiate SunJCE.RANDOM
valeriep
parents: 15008
diff changeset
   545
                random = SunJCE.getRandom();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
            }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   547
            if (cipherMode == GCM_MODE) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   548
                ivBytes = new byte[GaloisCounterMode.DEFAULT_IV_LEN];
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   549
            } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   550
                ivBytes = new byte[blockSize];
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   551
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
            random.nextBytes(ivBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
        buffered = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
        diffBlocksize = blockSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
        String algorithm = key.getAlgorithm();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   560
        // GCM mode needs additional handling
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   561
        if (cipherMode == GCM_MODE) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   562
            if(tagLen == -1) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   563
                tagLen = GaloisCounterMode.DEFAULT_TAG_LEN;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   564
            }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   565
            if (decrypting) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   566
                minBytes = tagLen;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   567
            } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   568
                // check key+iv for encryption in GCM mode
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   569
                requireReinit =
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   570
                    Arrays.equals(ivBytes, lastEncIv) &&
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   571
                    Arrays.equals(keyBytes, lastEncKey);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   572
                if (requireReinit) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   573
                    throw new InvalidAlgorithmParameterException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   574
                        ("Cannot reuse iv for GCM encryption");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   575
                }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   576
                lastEncIv = ivBytes;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   577
                lastEncKey = keyBytes;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   578
            }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   579
            ((GaloisCounterMode) cipher).init
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   580
                (decrypting, algorithm, keyBytes, ivBytes, tagLen);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   581
        } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   582
            cipher.init(decrypting, algorithm, keyBytes, ivBytes);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   583
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   584
        // skip checking key+iv from now on until after doFinal()
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   585
        requireReinit = false;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
    void init(int opmode, Key key, AlgorithmParameters params,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
              SecureRandom random)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
        throws InvalidKeyException, InvalidAlgorithmParameterException {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   591
        AlgorithmParameterSpec spec = null;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   592
        String paramType = null;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
        if (params != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
            try {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   595
                if (cipherMode == GCM_MODE) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   596
                    paramType = "GCM";
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   597
                    spec = params.getParameterSpec(GCMParameterSpec.class);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   598
                } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   599
                    // NOTE: RC2 parameters are always handled through
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   600
                    // init(..., AlgorithmParameterSpec,...) method, so
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   601
                    // we can assume IvParameterSpec type here.
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   602
                    paramType = "IV";
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   603
                    spec = params.getParameterSpec(IvParameterSpec.class);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   604
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
            } catch (InvalidParameterSpecException ipse) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   606
                throw new InvalidAlgorithmParameterException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   607
                    ("Wrong parameter type: " + paramType + " expected");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
        }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   610
        init(opmode, key, spec, random);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
     * Return the key bytes of the specified key. Throw an InvalidKeyException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
     * if the key is not usable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
    static byte[] getKeyBytes(Key key) throws InvalidKeyException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
        if (key == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
            throw new InvalidKeyException("No key given");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
        // note: key.getFormat() may return null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
        if (!"RAW".equalsIgnoreCase(key.getFormat())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
            throw new InvalidKeyException("Wrong format: RAW bytes needed");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
        byte[] keyBytes = key.getEncoded();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
        if (keyBytes == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
            throw new InvalidKeyException("RAW key bytes missing");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
        return keyBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   632
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
     * Continues a multiple-part encryption or decryption operation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
     * (depending on how this cipher was initialized), processing another data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
     * part.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
     * buffer, starting at <code>inputOffset</code>, are processed, and the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
     * result is stored in a new buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
     * @param input the input buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
     * @param inputOffset the offset in <code>input</code> where the input
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
     * starts
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
     * @param inputLen the input length
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
     * @return the new buffer with the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
     * @exception IllegalStateException if this cipher is in a wrong state
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
     * (e.g., has not been initialized)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
    byte[] update(byte[] input, int inputOffset, int inputLen) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   653
        if (requireReinit) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   654
            throw new IllegalStateException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   655
                ("Must use either different key or iv for GCM encryption");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   656
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   657
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
        byte[] output = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
        try {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   660
            output = new byte[getOutputSizeByOperation(inputLen, false)];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
            int len = update(input, inputOffset, inputLen, output,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
                             0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
            if (len == output.length) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   664
                return output;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
            } else {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   666
                return Arrays.copyOf(output, len);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
        } catch (ShortBufferException e) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   669
            // should never happen
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   670
            throw new ProviderException("Unexpected exception", e);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
     * Continues a multiple-part encryption or decryption operation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
     * (depending on how this cipher was initialized), processing another data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
     * part.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
     * buffer, starting at <code>inputOffset</code>, are processed, and the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
     * result is stored in the <code>output</code> buffer, starting at
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
     * <code>outputOffset</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
     * @param input the input buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
     * @param inputOffset the offset in <code>input</code> where the input
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
     * starts
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
     * @param inputLen the input length
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
     * @param output the buffer for the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
     * @param outputOffset the offset in <code>output</code> where the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
     * is stored
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
     * @return the number of bytes stored in <code>output</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
     * @exception ShortBufferException if the given output buffer is too small
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
     * to hold the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
    int update(byte[] input, int inputOffset, int inputLen, byte[] output,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
               int outputOffset) throws ShortBufferException {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   699
        if (requireReinit) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   700
            throw new IllegalStateException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   701
                ("Must use either different key or iv for GCM encryption");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   702
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   703
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
        // figure out how much can be sent to crypto function
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
        int len = buffered + inputLen - minBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
        if (padding != null && decrypting) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
            // do not include the padding bytes when decrypting
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
            len -= blockSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
        // do not count the trailing bytes which do not make up a unit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
        len = (len > 0 ? (len - (len%unitBytes)) : 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
        // check output buffer capacity
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   714
        if ((output == null) ||
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   715
            ((output.length - outputOffset) < len)) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
            throw new ShortBufferException("Output buffer must be "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
                                           + "(at least) " + len
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
                                           + " bytes long");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
        }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   720
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   721
        int outLen = 0;
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   722
        if (len != 0) { // there is some work to do
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   723
            if (len <= buffered) {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   724
                // all to-be-processed data are from 'buffer'
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   725
                if (decrypting) {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   726
                    outLen = cipher.decrypt(buffer, 0, len, output, outputOffset);
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   727
                } else {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   728
                    outLen = cipher.encrypt(buffer, 0, len, output, outputOffset);
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   729
                }
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   730
                buffered -= len;
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   731
                if (buffered != 0) {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   732
                    System.arraycopy(buffer, len, buffer, 0, buffered);
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   733
                }
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   734
            } else { // len > buffered
21837
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   735
                if ((input != output) && (buffered == 0)) {
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   736
                    // all to-be-processed data are from 'input'
21837
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   737
                    // however, note that if 'input' and 'output' are the same,
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   738
                    // then they can't be passed directly to the underlying cipher
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   739
                    // engine operations as data may be overwritten before they
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   740
                    // are read.
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   741
                    if (decrypting) {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   742
                        outLen = cipher.decrypt(input, inputOffset, len, output, outputOffset);
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   743
                    } else {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   744
                        outLen = cipher.encrypt(input, inputOffset, len, output, outputOffset);
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   745
                    }
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   746
                    inputOffset += len;
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   747
                    inputLen -= len;
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   748
                } else {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   749
                    // assemble the data using both 'buffer' and 'input'
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   750
                    byte[] in = new byte[len];
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   751
                    int inConsumed = len - buffered;
21837
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   752
                    if (buffered != 0) {
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   753
                        System.arraycopy(buffer, 0, in, 0, buffered);
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   754
                        buffered = 0;
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   755
                    }
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   756
                    if (inConsumed != 0) {
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   757
                        System.arraycopy(input, inputOffset, in, len - inConsumed, inConsumed);
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   758
                        inputOffset += inConsumed;
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   759
                        inputLen -= inConsumed;
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   760
                    }
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   761
                    if (decrypting) {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   762
                        outLen = cipher.decrypt(in, 0, len, output, outputOffset);
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   763
                    } else {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   764
                        outLen = cipher.encrypt(in, 0, len, output, outputOffset);
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   765
                    }
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   766
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
            // Let's keep track of how many bytes are needed to make
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
            // the total input length a multiple of blocksize when
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
            // padding is applied
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
            if (unitBytes != blockSize) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   772
                if (len < diffBlocksize) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
                    diffBlocksize -= len;
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   774
                } else {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
                    diffBlocksize = blockSize -
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
                        ((len - diffBlocksize) % blockSize);
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   777
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
        }
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   780
        // Store remaining input into 'buffer' again
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
        if (inputLen > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
            System.arraycopy(input, inputOffset, buffer, buffered,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
                             inputLen);
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   784
            buffered += inputLen;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
        }
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   786
        return outLen;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
     * Encrypts or decrypts data in a single-part operation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
     * or finishes a multiple-part operation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
     * The data is encrypted or decrypted, depending on how this cipher was
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
     * initialized.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
     * buffer, starting at <code>inputOffset</code>, and any input bytes that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
     * may have been buffered during a previous <code>update</code> operation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
     * are processed, with padding (if requested) being applied.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
     * The result is stored in a new buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
     * <p>The cipher is reset to its initial state (uninitialized) after this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
     * call.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
     * @param input the input buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
     * @param inputOffset the offset in <code>input</code> where the input
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
     * starts
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
     * @param inputLen the input length
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
     * @return the new buffer with the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
     * @exception IllegalBlockSizeException if this cipher is a block cipher,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
     * no padding has been requested (only in encryption mode), and the total
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
     * input length of the data processed by this cipher is not a multiple of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
     * block size
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
     * @exception BadPaddingException if this cipher is in decryption mode,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
     * and (un)padding has been requested, but the decrypted data is not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
     * bounded by the appropriate padding bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
    byte[] doFinal(byte[] input, int inputOffset, int inputLen)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
        throws IllegalBlockSizeException, BadPaddingException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
        byte[] output = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
        try {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   823
            output = new byte[getOutputSizeByOperation(inputLen, true)];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
            int len = doFinal(input, inputOffset, inputLen, output, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
            if (len < output.length) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   826
                return Arrays.copyOf(output, len);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
            } else {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   828
                return output;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
        } catch (ShortBufferException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
            // never thrown
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   832
            throw new ProviderException("Unexpected exception", e);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
     * Encrypts or decrypts data in a single-part operation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
     * or finishes a multiple-part operation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
     * The data is encrypted or decrypted, depending on how this cipher was
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
     * initialized.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
     * buffer, starting at <code>inputOffset</code>, and any input bytes that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
     * may have been buffered during a previous <code>update</code> operation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
     * are processed, with padding (if requested) being applied.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
     * The result is stored in the <code>output</code> buffer, starting at
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
     * <code>outputOffset</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
     * <p>The cipher is reset to its initial state (uninitialized) after this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
     * call.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
     * @param input the input buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
     * @param inputOffset the offset in <code>input</code> where the input
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
     * starts
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
     * @param inputLen the input length
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
     * @param output the buffer for the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
     * @param outputOffset the offset in <code>output</code> where the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
     * is stored
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
     * @return the number of bytes stored in <code>output</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
     * @exception IllegalBlockSizeException if this cipher is a block cipher,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
     * no padding has been requested (only in encryption mode), and the total
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
     * input length of the data processed by this cipher is not a multiple of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
     * block size
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
     * @exception ShortBufferException if the given output buffer is too small
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
     * to hold the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
     * @exception BadPaddingException if this cipher is in decryption mode,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
     * and (un)padding has been requested, but the decrypted data is not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
     * bounded by the appropriate padding bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
    int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
                int outputOffset)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
        throws IllegalBlockSizeException, ShortBufferException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
               BadPaddingException {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   876
        if (requireReinit) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   877
            throw new IllegalStateException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   878
                ("Must use either different key or iv for GCM encryption");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   879
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   881
        int estOutSize = getOutputSizeByOperation(inputLen, true);
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   882
        // check output buffer capacity.
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   883
        // if we are decrypting with padding applied, we can perform this
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   884
        // check only after we have determined how many padding bytes there
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   885
        // are.
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   886
        int outputCapacity = output.length - outputOffset;
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   887
        int minOutSize = (decrypting? (estOutSize - blockSize):estOutSize);
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   888
        if ((output == null) || (outputCapacity < minOutSize)) {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   889
            throw new ShortBufferException("Output buffer must be "
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   890
                + "(at least) " + minOutSize + " bytes long");
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   891
        }
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   892
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   893
        // calculate total input length
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   894
        int len = buffered + inputLen;
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   895
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   896
        // calculate padding length
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   897
        int totalLen = len + cipher.getBufferedLength();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
        int paddingLen = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
        // will the total input length be a multiple of blockSize?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
        if (unitBytes != blockSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
            if (totalLen < diffBlocksize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
                paddingLen = diffBlocksize - totalLen;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
                paddingLen = blockSize -
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
                    ((totalLen - diffBlocksize) % blockSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
        } else if (padding != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
            paddingLen = padding.padLength(totalLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   911
        if (decrypting && (padding != null) &&
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   912
            (paddingLen > 0) && (paddingLen != blockSize)) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
            throw new IllegalBlockSizeException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
                ("Input length must be multiple of " + blockSize +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
                 " when decrypting with padded cipher");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
21837
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   918
        /*
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   919
         * prepare the final input, assemble a new buffer if any
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   920
         * of the following is true:
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   921
         *  - 'input' and 'output' are the same buffer
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   922
         *  - there are internally buffered bytes
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   923
         *  - doing encryption and padding is needed
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   924
         */
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
        byte[] finalBuf = input;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
        int finalOffset = inputOffset;
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   927
        int finalBufLen = inputLen;
21837
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   928
        if ((input == output) || (buffered != 0) ||
0c41fa97176a 8026943: SQE test jce/Global/Cipher/SameBuffer failed
valeriep
parents: 20752
diff changeset
   929
            (!decrypting && padding != null)) {
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   930
            if (decrypting || padding == null) {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   931
                paddingLen = 0;
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   932
            }
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   933
            finalBuf = new byte[len + paddingLen];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
            finalOffset = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
            if (buffered != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
                System.arraycopy(buffer, 0, finalBuf, 0, buffered);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
            if (inputLen != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
                System.arraycopy(input, inputOffset, finalBuf,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
                                 buffered, inputLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
            }
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   942
            if (paddingLen != 0) {
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   943
                padding.padWithLen(finalBuf, (buffered+inputLen), paddingLen);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
            }
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   945
            finalBufLen = finalBuf.length;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
        }
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   947
        int outLen = 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
        if (decrypting) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
            // if the size of specified output buffer is less than
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
            // the length of the cipher text, then the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
            // content of cipher has to be preserved in order for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
            // users to retry the call with a larger buffer in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
            // case of ShortBufferException.
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   954
            if (outputCapacity < estOutSize) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
                cipher.save();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
            // create temporary output buffer so that only "real"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
            // data bytes are passed to user's output buffer.
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   959
            byte[] outWithPadding = new byte[estOutSize];
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   960
            outLen = finalNoPadding(finalBuf, finalOffset, outWithPadding,
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   961
                                    0, finalBufLen);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
            if (padding != null) {
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   964
                int padStart = padding.unpad(outWithPadding, 0, outLen);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
                if (padStart < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
                    throw new BadPaddingException("Given final block not "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
                                                  + "properly padded");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
                }
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   969
                outLen = padStart;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
            }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   971
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   972
            if (outputCapacity < outLen) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
                // restore so users can retry with a larger buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
                cipher.restore();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
                throw new ShortBufferException("Output buffer too short: "
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   976
                                               + (outputCapacity)
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   977
                                               + " bytes given, " + outLen
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
                                               + " bytes needed");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
            }
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   980
            // copy the result into user-supplied output buffer
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   981
            System.arraycopy(outWithPadding, 0, output, outputOffset, outLen);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
        } else { // encrypting
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   983
            try {
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   984
                outLen = finalNoPadding(finalBuf, finalOffset, output,
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   985
                                        outputOffset, finalBufLen);
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   986
            } finally {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   987
                // reset after doFinal() for GCM encryption
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   988
                requireReinit = (cipherMode == GCM_MODE);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   989
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
        buffered = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
        diffBlocksize = blockSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
        if (cipherMode != ECB_MODE) {
10336
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   995
            cipher.reset();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
        }
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
   997
        return outLen;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1000
    private int finalNoPadding(byte[] in, int inOfs, byte[] out, int outOfs,
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
                               int len)
20752
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
  1002
        throws IllegalBlockSizeException, AEADBadTagException,
f0f0acea9113 8012900: CICO ignores AAD in GCM mode
valeriep
parents: 16909
diff changeset
  1003
        ShortBufferException {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1005
        if ((cipherMode != GCM_MODE) && (in == null || len == 0)) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1006
            return 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
        }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1008
        if ((cipherMode != CFB_MODE) && (cipherMode != OFB_MODE) &&
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1009
            (cipherMode != GCM_MODE) &&
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1010
            ((len % unitBytes) != 0) && (cipherMode != CTS_MODE)) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1011
                if (padding != null) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1012
                    throw new IllegalBlockSizeException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1013
                        ("Input length (with padding) not multiple of " +
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1014
                         unitBytes + " bytes");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1015
                } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1016
                    throw new IllegalBlockSizeException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1017
                        ("Input length not multiple of " + unitBytes
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1018
                         + " bytes");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1019
                }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1020
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1021
        int outLen = 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
        if (decrypting) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1023
            outLen = cipher.decryptFinal(in, inOfs, len, out, outOfs);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
        } else {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1025
            outLen = cipher.encryptFinal(in, inOfs, len, out, outOfs);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
        }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1027
        return outLen;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
    // Note: Wrap() and Unwrap() are the same in
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
    // each of SunJCE CipherSpi implementation classes.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
    // They are duplicated due to export control requirements:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
    // All CipherSpi implementation must be final.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1035
     * Wrap a key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
     * @param key the key to be wrapped.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
     * @return the wrapped key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
     * @exception IllegalBlockSizeException if this cipher is a block
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
     * cipher, no padding has been requested, and the length of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
     * encoding of the key to be wrapped is not a
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
     * multiple of the block size.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1045
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1046
     * @exception InvalidKeyException if it is impossible or unsafe to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
     * wrap the key with this cipher (e.g., a hardware protected key is
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
     * being passed to a software only cipher).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
    byte[] wrap(Key key)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
        throws IllegalBlockSizeException, InvalidKeyException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
        byte[] result = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1054
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
            byte[] encodedKey = key.getEncoded();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1056
            if ((encodedKey == null) || (encodedKey.length == 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1057
                throw new InvalidKeyException("Cannot get an encoding of " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
                                              "the key to be wrapped");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1059
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
            result = doFinal(encodedKey, 0, encodedKey.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
        } catch (BadPaddingException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1062
            // Should never happen
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1063
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1064
        return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1065
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1066
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1067
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1068
     * Unwrap a previously wrapped key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1069
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1070
     * @param wrappedKey the key to be unwrapped.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1071
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1072
     * @param wrappedKeyAlgorithm the algorithm the wrapped key is for.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1073
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1074
     * @param wrappedKeyType the type of the wrapped key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1075
     * This is one of <code>Cipher.SECRET_KEY</code>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1076
     * <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1077
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1078
     * @return the unwrapped key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1079
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1080
     * @exception NoSuchAlgorithmException if no installed providers
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1081
     * can create keys of type <code>wrappedKeyType</code> for the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1082
     * <code>wrappedKeyAlgorithm</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1083
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
     * @exception InvalidKeyException if <code>wrappedKey</code> does not
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1085
     * represent a wrapped key of type <code>wrappedKeyType</code> for
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1086
     * the <code>wrappedKeyAlgorithm</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1087
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1088
    Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1089
               int wrappedKeyType)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1090
        throws InvalidKeyException, NoSuchAlgorithmException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1091
        byte[] encodedKey;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1092
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1093
            encodedKey = doFinal(wrappedKey, 0, wrappedKey.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1094
        } catch (BadPaddingException ePadding) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1095
            throw new InvalidKeyException("The wrapped key is not padded " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1096
                                          "correctly");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1097
        } catch (IllegalBlockSizeException eBlockSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1098
            throw new InvalidKeyException("The wrapped key does not have " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1099
                                          "the correct length");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1100
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1101
        return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1102
                                          wrappedKeyType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1103
    }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1104
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1105
    /**
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1106
     * Continues a multi-part update of the Additional Authentication
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1107
     * Data (AAD), using a subset of the provided buffer.
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1108
     * <p>
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1109
     * Calls to this method provide AAD to the cipher when operating in
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1110
     * modes such as AEAD (GCM/CCM).  If this cipher is operating in
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1111
     * either GCM or CCM mode, all AAD must be supplied before beginning
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1112
     * operations on the ciphertext (via the {@code update} and {@code
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1113
     * doFinal} methods).
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1114
     *
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1115
     * @param src the buffer containing the AAD
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1116
     * @param offset the offset in {@code src} where the AAD input starts
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1117
     * @param len the number of AAD bytes
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1118
     *
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1119
     * @throws IllegalStateException if this cipher is in a wrong state
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1120
     * (e.g., has not been initialized), does not accept AAD, or if
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1121
     * operating in either GCM or CCM mode and one of the {@code update}
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1122
     * methods has already been called for the active
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1123
     * encryption/decryption operation
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1124
     * @throws UnsupportedOperationException if this method
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1125
     * has not been overridden by an implementation
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1126
     *
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1127
     * @since 1.8
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1128
     */
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1129
    void updateAAD(byte[] src, int offset, int len) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1130
        if (requireReinit) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1131
            throw new IllegalStateException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1132
                ("Must use either different key or iv for GCM encryption");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1133
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1134
        cipher.updateAAD(src, offset, len);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1135
    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1136
}