jdk/src/share/classes/com/sun/crypto/provider/CipherCore.java
author vinnie
Thu, 11 Apr 2013 17:57:08 +0100
changeset 16909 78a1749a43e2
parent 15010 ec6b49ce42b1
child 20752 f0f0acea9113
permissions -rw-r--r--
7171982: Cipher getParameters() throws RuntimeException: Cannot find SunJCE provider Reviewed-by: vinnie, wetmore Contributed-by: Tony Scarpino <anthony.scarpino@oracle.com>
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) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        int totalLen = buffered + inputLen;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   315
        // GCM: this call may be for either update() or doFinal(), so have to
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   316
        // return the larger value of both
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   317
        // Encryption: based on doFinal value: inputLen + tag
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   318
        // Decryption: based on update value: inputLen
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   319
        if (!decrypting && (cipherMode == GCM_MODE)) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   320
            return (totalLen + ((GaloisCounterMode) cipher).getTagLen());
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   321
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   323
        if (padding == null) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
            return totalLen;
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   325
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   326
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   327
        if (decrypting) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   328
            return totalLen;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   329
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
        if (unitBytes != blockSize) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   332
            if (totalLen < diffBlocksize) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
                return diffBlocksize;
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   334
            } else {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
                return (totalLen + blockSize -
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
                        ((totalLen - diffBlocksize) % blockSize));
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   337
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
            return totalLen + padding.padLength(totalLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   343
    private int getOutputSizeByOperation(int inputLen, boolean isDoFinal) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   344
        int totalLen = 0;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   345
        switch (cipherMode) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   346
        case GCM_MODE:
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   347
            totalLen = buffered + inputLen;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   348
            if (isDoFinal) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   349
                int tagLen = ((GaloisCounterMode) cipher).getTagLen();
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   350
                if (decrypting) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   351
                    // need to get the actual value from cipher??
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   352
                    // deduct tagLen
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   353
                    totalLen -= tagLen;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   354
                } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   355
                    totalLen += tagLen;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   356
                }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   357
            }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   358
            if (totalLen < 0) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   359
                totalLen = 0;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   360
            }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   361
            break;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   362
        default:
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   363
             totalLen  = getOutputSize(inputLen);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   364
             break;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   365
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   366
        return totalLen;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   367
    }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   368
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
     * Returns the initialization vector (IV) in a new buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
     * <p>This is useful in the case where a random IV has been created
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
     * (see <a href = "#init">init</a>),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
     * or in the context of password-based encryption or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
     * decryption, where the IV is derived from a user-provided password.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
     * @return the initialization vector in a new buffer, or null if the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
     * underlying algorithm does not use an IV, or if the IV has not yet
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
     * been set.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
    byte[] getIV() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
        byte[] iv = cipher.getIV();
10336
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   383
        return (iv == null) ? null : iv.clone();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
     * Returns the parameters used with this cipher.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
     * <p>The returned parameters may be the same that were used to initialize
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
     * this cipher, or may contain the default set of parameters or a set of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
     * randomly generated parameters used by the underlying cipher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
     * implementation (provided that the underlying cipher implementation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
     * uses a default set of parameters or creates new parameters if it needs
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
     * parameters but was not initialized with any).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
     * @return the parameters used with this cipher, or null if this cipher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
     * does not use any parameters.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
    AlgorithmParameters getParameters(String algName) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   400
        if (cipherMode == ECB_MODE) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   401
            return null;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   402
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
        AlgorithmParameters params = null;
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   404
        AlgorithmParameterSpec spec;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
        byte[] iv = getIV();
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   406
        if (iv == null) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   407
            // generate spec using default value
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   408
            if (cipherMode == GCM_MODE) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   409
                iv = new byte[GaloisCounterMode.DEFAULT_IV_LEN];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
            } else {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   411
                iv = new byte[blockSize];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
            }
15010
ec6b49ce42b1 8004044: Lazily instantiate SunJCE.RANDOM
valeriep
parents: 15008
diff changeset
   413
            SunJCE.getRandom().nextBytes(iv);
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   414
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   415
        if (cipherMode == GCM_MODE) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   416
            algName = "GCM";
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   417
            spec = new GCMParameterSpec
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   418
                (((GaloisCounterMode) cipher).getTagLen()*8, iv);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   419
        } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   420
           if (algName.equals("RC2")) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   421
               RC2Crypt rawImpl = (RC2Crypt) cipher.getEmbeddedCipher();
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   422
               spec = new RC2ParameterSpec
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   423
                   (rawImpl.getEffectiveKeyBits(), iv);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   424
           } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   425
               spec = new IvParameterSpec(iv);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   426
           }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   427
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   428
        try {
16909
78a1749a43e2 7171982: Cipher getParameters() throws RuntimeException: Cannot find SunJCE provider
vinnie
parents: 15010
diff changeset
   429
            params = AlgorithmParameters.getInstance(algName,
78a1749a43e2 7171982: Cipher getParameters() throws RuntimeException: Cannot find SunJCE provider
vinnie
parents: 15010
diff changeset
   430
                    SunJCE.getInstance());
78a1749a43e2 7171982: Cipher getParameters() throws RuntimeException: Cannot find SunJCE provider
vinnie
parents: 15010
diff changeset
   431
            params.init(spec);
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   432
        } catch (NoSuchAlgorithmException nsae) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   433
            // should never happen
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   434
            throw new RuntimeException("Cannot find " + algName +
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   435
                " AlgorithmParameters implementation in SunJCE provider");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   436
        } catch (InvalidParameterSpecException ipse) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   437
            // should never happen
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   438
            throw new RuntimeException(spec.getClass() + " not supported");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
        return params;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
     * Initializes this cipher with a key and a source of randomness.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
     * <p>The cipher is initialized for one of the following four operations:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
     * encryption, decryption, key wrapping or key unwrapping, depending on
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
     * the value of <code>opmode</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
     * <p>If this cipher requires an initialization vector (IV), it will get
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
     * it from <code>random</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
     * This behaviour should only be used in encryption or key wrapping
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
     * mode, however.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
     * When initializing a cipher that requires an IV for decryption or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
     * key unwrapping, the IV
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
     * (same IV that was used for encryption or key wrapping) must be provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
     * explicitly as a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
     * parameter, in order to get the correct result.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
     * <p>This method also cleans existing buffer and other related state
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
     * information.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
     * @param opmode the operation mode of this cipher (this is one of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
     * the following:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
     * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
     * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
     * @param key the secret key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
     * @param random the source of randomness
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
     * @exception InvalidKeyException if the given key is inappropriate for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
     * initializing this cipher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
    void init(int opmode, Key key, SecureRandom random)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
            throws InvalidKeyException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
            init(opmode, key, (AlgorithmParameterSpec)null, random);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
        } catch (InvalidAlgorithmParameterException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
            throw new InvalidKeyException(e.getMessage());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
     * Initializes this cipher with a key, a set of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
     * algorithm parameters, and a source of randomness.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
     * <p>The cipher is initialized for one of the following four operations:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
     * encryption, decryption, key wrapping or key unwrapping, depending on
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
     * the value of <code>opmode</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
     * <p>If this cipher (including its underlying feedback or padding scheme)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
     * requires any random bytes, it will get them from <code>random</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
     * @param opmode the operation mode of this cipher (this is one of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
     * the following:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
     * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
     * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
     * @param key the encryption key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
     * @param params the algorithm parameters
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
     * @param random the source of randomness
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
     * @exception InvalidKeyException if the given key is inappropriate for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
     * initializing this cipher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
     * @exception InvalidAlgorithmParameterException if the given algorithm
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
     * parameters are inappropriate for this cipher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
    void init(int opmode, Key key, AlgorithmParameterSpec params,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
            SecureRandom random)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
            throws InvalidKeyException, InvalidAlgorithmParameterException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
        decrypting = (opmode == Cipher.DECRYPT_MODE)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
                  || (opmode == Cipher.UNWRAP_MODE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
        byte[] keyBytes = getKeyBytes(key);
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   513
        int tagLen = -1;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   514
        byte[] ivBytes = null;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   515
        if (params != null) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   516
            if (cipherMode == GCM_MODE) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   517
                if (params instanceof GCMParameterSpec) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   518
                    tagLen = ((GCMParameterSpec)params).getTLen();
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   519
                    if (tagLen < 96 || tagLen > 128 || ((tagLen & 0x07) != 0)) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   520
                        throw new InvalidAlgorithmParameterException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   521
                            ("Unsupported TLen value; must be one of " +
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   522
                             "{128, 120, 112, 104, 96}");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   523
                    }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   524
                    tagLen = tagLen >> 3;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   525
                    ivBytes = ((GCMParameterSpec)params).getIV();
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   526
                } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   527
                    throw new InvalidAlgorithmParameterException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   528
                        ("Unsupported parameter: " + params);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   529
               }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   530
            } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   531
                if (params instanceof IvParameterSpec) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   532
                    ivBytes = ((IvParameterSpec)params).getIV();
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   533
                    if ((ivBytes == null) || (ivBytes.length != blockSize)) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   534
                        throw new InvalidAlgorithmParameterException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   535
                            ("Wrong IV length: must be " + blockSize +
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   536
                             " bytes long");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   537
                    }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   538
                } else if (params instanceof RC2ParameterSpec) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   539
                    ivBytes = ((RC2ParameterSpec)params).getIV();
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   540
                    if ((ivBytes != null) && (ivBytes.length != blockSize)) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   541
                        throw new InvalidAlgorithmParameterException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   542
                            ("Wrong IV length: must be " + blockSize +
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   543
                             " bytes long");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   544
                    }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   545
                } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   546
                    throw new InvalidAlgorithmParameterException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   547
                        ("Unsupported parameter: " + params);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   548
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
        if (cipherMode == ECB_MODE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
            if (ivBytes != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
                throw new InvalidAlgorithmParameterException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
                                                ("ECB mode cannot use IV");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
            }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   556
        } else if (ivBytes == null)  {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
            if (decrypting) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
                throw new InvalidAlgorithmParameterException("Parameters "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
                                                             + "missing");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
            }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   561
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
            if (random == null) {
15010
ec6b49ce42b1 8004044: Lazily instantiate SunJCE.RANDOM
valeriep
parents: 15008
diff changeset
   563
                random = SunJCE.getRandom();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
            }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   565
            if (cipherMode == GCM_MODE) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   566
                ivBytes = new byte[GaloisCounterMode.DEFAULT_IV_LEN];
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   567
            } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   568
                ivBytes = new byte[blockSize];
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   569
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
            random.nextBytes(ivBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
        buffered = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
        diffBlocksize = blockSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
        String algorithm = key.getAlgorithm();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   578
        // GCM mode needs additional handling
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   579
        if (cipherMode == GCM_MODE) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   580
            if(tagLen == -1) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   581
                tagLen = GaloisCounterMode.DEFAULT_TAG_LEN;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   582
            }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   583
            if (decrypting) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   584
                minBytes = tagLen;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   585
            } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   586
                // check key+iv for encryption in GCM mode
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   587
                requireReinit =
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   588
                    Arrays.equals(ivBytes, lastEncIv) &&
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   589
                    Arrays.equals(keyBytes, lastEncKey);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   590
                if (requireReinit) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   591
                    throw new InvalidAlgorithmParameterException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   592
                        ("Cannot reuse iv for GCM encryption");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   593
                }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   594
                lastEncIv = ivBytes;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   595
                lastEncKey = keyBytes;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   596
            }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   597
            ((GaloisCounterMode) cipher).init
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   598
                (decrypting, algorithm, keyBytes, ivBytes, tagLen);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   599
        } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   600
            cipher.init(decrypting, algorithm, keyBytes, ivBytes);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   601
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   602
        // skip checking key+iv from now on until after doFinal()
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   603
        requireReinit = false;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
    void init(int opmode, Key key, AlgorithmParameters params,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
              SecureRandom random)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
        throws InvalidKeyException, InvalidAlgorithmParameterException {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   609
        AlgorithmParameterSpec spec = null;
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   610
        String paramType = null;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
        if (params != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
            try {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   613
                if (cipherMode == GCM_MODE) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   614
                    paramType = "GCM";
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   615
                    spec = params.getParameterSpec(GCMParameterSpec.class);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   616
                } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   617
                    // NOTE: RC2 parameters are always handled through
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   618
                    // init(..., AlgorithmParameterSpec,...) method, so
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   619
                    // we can assume IvParameterSpec type here.
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   620
                    paramType = "IV";
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   621
                    spec = params.getParameterSpec(IvParameterSpec.class);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   622
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
            } catch (InvalidParameterSpecException ipse) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   624
                throw new InvalidAlgorithmParameterException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   625
                    ("Wrong parameter type: " + paramType + " expected");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
        }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   628
        init(opmode, key, spec, random);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
     * Return the key bytes of the specified key. Throw an InvalidKeyException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
     * if the key is not usable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
    static byte[] getKeyBytes(Key key) throws InvalidKeyException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
        if (key == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
            throw new InvalidKeyException("No key given");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
        // note: key.getFormat() may return null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
        if (!"RAW".equalsIgnoreCase(key.getFormat())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
            throw new InvalidKeyException("Wrong format: RAW bytes needed");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
        byte[] keyBytes = key.getEncoded();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
        if (keyBytes == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
            throw new InvalidKeyException("RAW key bytes missing");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
        return keyBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   650
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
     * Continues a multiple-part encryption or decryption operation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
     * (depending on how this cipher was initialized), processing another data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
     * part.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
     * buffer, starting at <code>inputOffset</code>, are processed, and the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
     * result is stored in a new buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
     * @param input the input buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
     * @param inputOffset the offset in <code>input</code> where the input
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
     * starts
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
     * @param inputLen the input length
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
     * @return the new buffer with the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
     * @exception IllegalStateException if this cipher is in a wrong state
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
     * (e.g., has not been initialized)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
    byte[] update(byte[] input, int inputOffset, int inputLen) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   671
        if (requireReinit) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   672
            throw new IllegalStateException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   673
                ("Must use either different key or iv for GCM encryption");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   674
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   675
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
        byte[] output = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
        try {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   678
            output = new byte[getOutputSizeByOperation(inputLen, false)];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
            int len = update(input, inputOffset, inputLen, output,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
                             0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
            if (len == output.length) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   682
                return output;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
            } else {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   684
                return Arrays.copyOf(output, len);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
        } catch (ShortBufferException e) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   687
            // should never happen
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   688
            throw new ProviderException("Unexpected exception", e);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
     * Continues a multiple-part encryption or decryption operation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
     * (depending on how this cipher was initialized), processing another data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
     * part.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
     * buffer, starting at <code>inputOffset</code>, are processed, and the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
     * result is stored in the <code>output</code> buffer, starting at
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
     * <code>outputOffset</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
     * @param input the input buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
     * @param inputOffset the offset in <code>input</code> where the input
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
     * starts
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
     * @param inputLen the input length
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
     * @param output the buffer for the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
     * @param outputOffset the offset in <code>output</code> where the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
     * is stored
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
     * @return the number of bytes stored in <code>output</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
     * @exception ShortBufferException if the given output buffer is too small
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
     * to hold the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
    int update(byte[] input, int inputOffset, int inputLen, byte[] output,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
               int outputOffset) throws ShortBufferException {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   717
        if (requireReinit) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   718
            throw new IllegalStateException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   719
                ("Must use either different key or iv for GCM encryption");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   720
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   721
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
        // figure out how much can be sent to crypto function
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
        int len = buffered + inputLen - minBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
        if (padding != null && decrypting) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
            // do not include the padding bytes when decrypting
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
            len -= blockSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
        // do not count the trailing bytes which do not make up a unit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
        len = (len > 0 ? (len - (len%unitBytes)) : 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
        // check output buffer capacity
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
        if ((output == null) || ((output.length - outputOffset) < len)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
            throw new ShortBufferException("Output buffer must be "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
                                           + "(at least) " + len
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
                                           + " bytes long");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
        }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   737
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
        if (len != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
            // there is some work to do
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
            byte[] in = new byte[len];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
            int inputConsumed = len - buffered;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
            int bufferedConsumed = buffered;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
            if (inputConsumed < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
                inputConsumed = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
                bufferedConsumed = len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
            if (buffered != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
                System.arraycopy(buffer, 0, in, 0, bufferedConsumed);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
            if (inputConsumed > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
                System.arraycopy(input, inputOffset, in,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
                                 bufferedConsumed, inputConsumed);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
            if (decrypting) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
                cipher.decrypt(in, 0, len, output, outputOffset);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
                cipher.encrypt(in, 0, len, output, outputOffset);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
            // Let's keep track of how many bytes are needed to make
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
            // the total input length a multiple of blocksize when
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
            // padding is applied
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
            if (unitBytes != blockSize) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   766
                if (len < diffBlocksize) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
                    diffBlocksize -= len;
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   768
                } else {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
                    diffBlocksize = blockSize -
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
                        ((len - diffBlocksize) % blockSize);
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   771
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
            inputLen -= inputConsumed;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
            inputOffset += inputConsumed;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
            outputOffset += len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
            buffered -= bufferedConsumed;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
            if (buffered > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
                System.arraycopy(buffer, bufferedConsumed, buffer, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
                                 buffered);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
        // left over again
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
        if (inputLen > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
            System.arraycopy(input, inputOffset, buffer, buffered,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
                             inputLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
        buffered += inputLen;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
        return len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
     * Encrypts or decrypts data in a single-part operation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
     * or finishes a multiple-part operation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
     * The data is encrypted or decrypted, depending on how this cipher was
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
     * initialized.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
     * buffer, starting at <code>inputOffset</code>, and any input bytes that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
     * may have been buffered during a previous <code>update</code> operation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
     * are processed, with padding (if requested) being applied.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
     * The result is stored in a new buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
     * <p>The cipher is reset to its initial state (uninitialized) after this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
     * call.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
     * @param input the input buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
     * @param inputOffset the offset in <code>input</code> where the input
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
     * starts
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
     * @param inputLen the input length
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
     * @return the new buffer with the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
     * @exception IllegalBlockSizeException if this cipher is a block cipher,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
     * no padding has been requested (only in encryption mode), and the total
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
     * input length of the data processed by this cipher is not a multiple of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
     * block size
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
     * @exception BadPaddingException if this cipher is in decryption mode,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
     * and (un)padding has been requested, but the decrypted data is not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
     * bounded by the appropriate padding bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
    byte[] doFinal(byte[] input, int inputOffset, int inputLen)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
        throws IllegalBlockSizeException, BadPaddingException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
        byte[] output = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
        try {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   826
            output = new byte[getOutputSizeByOperation(inputLen, true)];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
            int len = doFinal(input, inputOffset, inputLen, output, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
            if (len < output.length) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   829
                return Arrays.copyOf(output, len);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
            } else {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   831
                return output;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
        } catch (ShortBufferException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
            // never thrown
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   835
            throw new ProviderException("Unexpected exception", e);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
     * Encrypts or decrypts data in a single-part operation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
     * or finishes a multiple-part operation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
     * The data is encrypted or decrypted, depending on how this cipher was
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
     * initialized.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
     * buffer, starting at <code>inputOffset</code>, and any input bytes that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
     * may have been buffered during a previous <code>update</code> operation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
     * are processed, with padding (if requested) being applied.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
     * The result is stored in the <code>output</code> buffer, starting at
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
     * <code>outputOffset</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
     * <p>The cipher is reset to its initial state (uninitialized) after this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
     * call.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
     * @param input the input buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
     * @param inputOffset the offset in <code>input</code> where the input
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
     * starts
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
     * @param inputLen the input length
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
     * @param output the buffer for the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
     * @param outputOffset the offset in <code>output</code> where the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
     * is stored
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
     * @return the number of bytes stored in <code>output</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
     * @exception IllegalBlockSizeException if this cipher is a block cipher,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
     * no padding has been requested (only in encryption mode), and the total
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
     * input length of the data processed by this cipher is not a multiple of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
     * block size
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
     * @exception ShortBufferException if the given output buffer is too small
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
     * to hold the result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
     * @exception BadPaddingException if this cipher is in decryption mode,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
     * and (un)padding has been requested, but the decrypted data is not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
     * bounded by the appropriate padding bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
    int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
                int outputOffset)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
        throws IllegalBlockSizeException, ShortBufferException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
               BadPaddingException {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   879
        if (requireReinit) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   880
            throw new IllegalStateException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   881
                ("Must use either different key or iv for GCM encryption");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   882
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
        // calculate the total input length
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
        int totalLen = buffered + inputLen;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
        int paddedLen = totalLen;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
        int paddingLen = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
        // will the total input length be a multiple of blockSize?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
        if (unitBytes != blockSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
            if (totalLen < diffBlocksize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
                paddingLen = diffBlocksize - totalLen;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
                paddingLen = blockSize -
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
                    ((totalLen - diffBlocksize) % blockSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
        } else if (padding != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
            paddingLen = padding.padLength(totalLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
        if ((paddingLen > 0) && (paddingLen != blockSize) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
            (padding != null) && decrypting) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
            throw new IllegalBlockSizeException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
                ("Input length must be multiple of " + blockSize +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
                 " when decrypting with padded cipher");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
        // if encrypting and padding not null, add padding
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   909
        if (!decrypting && padding != null) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
            paddedLen += paddingLen;
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   911
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
        // check output buffer capacity.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
        // if we are decrypting with padding applied, we can perform this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
        // check only after we have determined how many padding bytes there
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
        // are.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
        if (output == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
            throw new ShortBufferException("Output buffer is null");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
        int outputCapacity = output.length - outputOffset;
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   921
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   922
        if (((!decrypting) && (outputCapacity < paddedLen)) ||
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
            (decrypting && (outputCapacity < (paddedLen - blockSize)))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
            throw new ShortBufferException("Output buffer too short: "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
                                           + outputCapacity + " bytes given, "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
                                           + paddedLen + " bytes needed");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
        // prepare the final input avoiding copying if possible
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
        byte[] finalBuf = input;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
        int finalOffset = inputOffset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
        if ((buffered != 0) || (!decrypting && padding != null)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
            finalOffset = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
            finalBuf = new byte[paddedLen];
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
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
            if (!decrypting && padding != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
                padding.padWithLen(finalBuf, totalLen, paddingLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
        if (decrypting) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
            // if the size of specified output buffer is less than
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
            // the length of the cipher text, then the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
            // content of cipher has to be preserved in order for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
            // users to retry the call with a larger buffer in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
            // case of ShortBufferException.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
            if (outputCapacity < paddedLen) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
                cipher.save();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
            // create temporary output buffer so that only "real"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
            // data bytes are passed to user's output buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
            byte[] outWithPadding = new byte[totalLen];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
            totalLen = finalNoPadding(finalBuf, finalOffset, outWithPadding,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
                                      0, totalLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
            if (padding != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
                int padStart = padding.unpad(outWithPadding, 0, totalLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
                if (padStart < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
                    throw new BadPaddingException("Given final block not "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
                                                  + "properly padded");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
                totalLen = padStart;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
            }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   970
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
            if ((output.length - outputOffset) < totalLen) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
                // restore so users can retry with a larger buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
                cipher.restore();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
                throw new ShortBufferException("Output buffer too short: "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
                                               + (output.length-outputOffset)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
                                               + " bytes given, " + totalLen
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
                                               + " bytes needed");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
            for (int i = 0; i < totalLen; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
                output[outputOffset + i] = outWithPadding[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
        } else { // encrypting
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   983
            try {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   984
                totalLen = finalNoPadding(finalBuf, finalOffset, output,
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
   985
                                          outputOffset, paddedLen);
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
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
        return totalLen;
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)
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1002
        throws IllegalBlockSizeException, AEADBadTagException {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1004
        if ((cipherMode != GCM_MODE) && (in == null || len == 0)) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1005
            return 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
        }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1007
        if ((cipherMode != CFB_MODE) && (cipherMode != OFB_MODE) &&
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1008
            (cipherMode != GCM_MODE) &&
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1009
            ((len % unitBytes) != 0) && (cipherMode != CTS_MODE)) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1010
                if (padding != null) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1011
                    throw new IllegalBlockSizeException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1012
                        ("Input length (with padding) not multiple of " +
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1013
                         unitBytes + " bytes");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1014
                } else {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1015
                    throw new IllegalBlockSizeException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1016
                        ("Input length not multiple of " + unitBytes
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1017
                         + " bytes");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1018
                }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1019
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1020
        int outLen = 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
        if (decrypting) {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1022
            outLen = cipher.decryptFinal(in, inOfs, len, out, outOfs);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
        } else {
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1024
            outLen = cipher.encryptFinal(in, inOfs, len, out, outOfs);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
        }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1026
        return outLen;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
    // Note: Wrap() and Unwrap() are the same in
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
    // each of SunJCE CipherSpi implementation classes.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
    // They are duplicated due to export control requirements:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
    // All CipherSpi implementation must be final.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
     * Wrap a key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1035
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
     * @param key the key to be wrapped.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
     * @return the wrapped key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
     * @exception IllegalBlockSizeException if this cipher is a block
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
     * cipher, no padding has been requested, and the length of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
     * encoding of the key to be wrapped is not a
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
     * multiple of the block size.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1045
     * @exception InvalidKeyException if it is impossible or unsafe to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1046
     * wrap the key with this cipher (e.g., a hardware protected key is
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
     * being passed to a software only cipher).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
    byte[] wrap(Key key)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
        throws IllegalBlockSizeException, InvalidKeyException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
        byte[] result = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1054
            byte[] encodedKey = key.getEncoded();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
            if ((encodedKey == null) || (encodedKey.length == 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1056
                throw new InvalidKeyException("Cannot get an encoding of " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1057
                                              "the key to be wrapped");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1059
            result = doFinal(encodedKey, 0, encodedKey.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
        } catch (BadPaddingException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
            // Should never happen
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1062
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1063
        return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1064
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1065
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1066
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1067
     * Unwrap a previously wrapped key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1068
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1069
     * @param wrappedKey the key to be unwrapped.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1070
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1071
     * @param wrappedKeyAlgorithm the algorithm the wrapped key is for.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1072
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1073
     * @param wrappedKeyType the type of the wrapped key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1074
     * This is one of <code>Cipher.SECRET_KEY</code>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1075
     * <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1076
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1077
     * @return the unwrapped key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1078
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1079
     * @exception NoSuchAlgorithmException if no installed providers
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1080
     * can create keys of type <code>wrappedKeyType</code> for the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1081
     * <code>wrappedKeyAlgorithm</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1082
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1083
     * @exception InvalidKeyException if <code>wrappedKey</code> does not
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
     * represent a wrapped key of type <code>wrappedKeyType</code> for
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1085
     * the <code>wrappedKeyAlgorithm</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1086
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1087
    Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1088
               int wrappedKeyType)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1089
        throws InvalidKeyException, NoSuchAlgorithmException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1090
        byte[] encodedKey;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1091
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1092
            encodedKey = doFinal(wrappedKey, 0, wrappedKey.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1093
        } catch (BadPaddingException ePadding) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1094
            throw new InvalidKeyException("The wrapped key is not padded " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1095
                                          "correctly");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1096
        } catch (IllegalBlockSizeException eBlockSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1097
            throw new InvalidKeyException("The wrapped key does not have " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1098
                                          "the correct length");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1099
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1100
        return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1101
                                          wrappedKeyType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1102
    }
15008
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1103
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1104
    /**
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1105
     * Continues a multi-part update of the Additional Authentication
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1106
     * Data (AAD), using a subset of the provided buffer.
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1107
     * <p>
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1108
     * Calls to this method provide AAD to the cipher when operating in
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1109
     * modes such as AEAD (GCM/CCM).  If this cipher is operating in
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1110
     * either GCM or CCM mode, all AAD must be supplied before beginning
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1111
     * operations on the ciphertext (via the {@code update} and {@code
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1112
     * doFinal} methods).
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1113
     *
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1114
     * @param src the buffer containing the AAD
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1115
     * @param offset the offset in {@code src} where the AAD input starts
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1116
     * @param len the number of AAD bytes
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1117
     *
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1118
     * @throws IllegalStateException if this cipher is in a wrong state
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1119
     * (e.g., has not been initialized), does not accept AAD, or if
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1120
     * operating in either GCM or CCM mode and one of the {@code update}
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1121
     * methods has already been called for the active
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1122
     * encryption/decryption operation
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1123
     * @throws UnsupportedOperationException if this method
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1124
     * has not been overridden by an implementation
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1125
     *
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1126
     * @since 1.8
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1127
     */
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1128
    void updateAAD(byte[] src, int offset, int len) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1129
        if (requireReinit) {
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1130
            throw new IllegalStateException
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1131
                ("Must use either different key or iv for GCM encryption");
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1132
        }
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1133
        cipher.updateAAD(src, offset, len);
6a494f8ba5b5 6996769: support AEAD cipher
valeriep
parents: 10336
diff changeset
  1134
    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1135
}