jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
author jjg
Mon, 15 Aug 2011 11:48:20 -0700
changeset 10336 0bb1999251f8
parent 8542 62c7b10ce177
child 11521 d7698e6c5f51
permissions -rw-r--r--
7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror Reviewed-by: xuelei, mullan Contributed-by: alexandre.boulgakov@oracle.com
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
8542
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
     2
 * Copyright (c) 2003, 2011, 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: 5291
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: 5291
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: 5291
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 5291
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 5291
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
package sun.security.pkcs11;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
import java.nio.ByteBuffer;
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    28
import java.util.Arrays;
6122
16fa7ed7ff1b 6867345: Turkish regional options cause NPE in sun.security.x509.AlgorithmId.algOID
xuelei
parents: 5506
diff changeset
    29
import java.util.Locale;
2
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
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import javax.crypto.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import javax.crypto.spec.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import sun.nio.ch.DirectBuffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import sun.security.pkcs11.wrapper.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
 * Cipher implementation class. This class currently supports
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
 * DES, DESede, AES, ARCFOUR, and Blowfish.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
 *
8542
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
    45
 * This class is designed to support ECB, CBC, CTR with NoPadding
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
    46
 * and ECB, CBC with PKCS5Padding. It will use its own padding impl
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
    47
 * if the native mechanism does not support padding.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 *
8542
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
    49
 * Note that PKCS#11 currently only supports ECB, CBC, and CTR.
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
    50
 * There are no provisions for other modes such as CFB, OFB, and PCBC.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * @author  Andreas Sterbenz
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * @since   1.5
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
final class P11Cipher extends CipherSpi {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
    // mode constant for ECB mode
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
    private final static int MODE_ECB = 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
    // mode constant for CBC mode
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
    private final static int MODE_CBC = 4;
8542
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
    61
    // mode constant for CTR mode
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
    62
    private final static int MODE_CTR = 5;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    // padding constant for NoPadding
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    65
    private final static int PAD_NONE = 5;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    // padding constant for PKCS5Padding
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
    private final static int PAD_PKCS5 = 6;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    69
    private static interface Padding {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    70
        // ENC: format the specified buffer with padding bytes and return the
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    71
        // actual padding length
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    72
        int setPaddingBytes(byte[] paddingBuffer, int padLen);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    73
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    74
        // DEC: return the length of trailing padding bytes given the specified
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    75
        // padded data
296
a26e4ea2ca63 6682411: JCK test failed w/ ArrayIndexOutOfBoundException (-1) when decrypting with no data
valeriep
parents: 289
diff changeset
    76
        int unpad(byte[] paddedData, int len)
7269
b7fe0ebc290c 6687725: Internal PKCS5Padding impl should throw IllegalBlockSizeException and not BadPaddingException
valeriep
parents: 6122
diff changeset
    77
                throws BadPaddingException, IllegalBlockSizeException;
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    78
    }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    79
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    80
    private static class PKCS5Padding implements Padding {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    81
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    82
        private final int blockSize;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    83
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    84
        PKCS5Padding(int blockSize)
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    85
                throws NoSuchPaddingException {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    86
            if (blockSize == 0) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    87
                throw new NoSuchPaddingException
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    88
                        ("PKCS#5 padding not supported with stream ciphers");
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    89
            }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    90
            this.blockSize = blockSize;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    91
        }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    92
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    93
        public int setPaddingBytes(byte[] paddingBuffer, int padLen) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    94
            Arrays.fill(paddingBuffer, 0, padLen, (byte) (padLen & 0x007f));
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    95
            return padLen;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    96
        }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
    97
296
a26e4ea2ca63 6682411: JCK test failed w/ ArrayIndexOutOfBoundException (-1) when decrypting with no data
valeriep
parents: 289
diff changeset
    98
        public int unpad(byte[] paddedData, int len)
7269
b7fe0ebc290c 6687725: Internal PKCS5Padding impl should throw IllegalBlockSizeException and not BadPaddingException
valeriep
parents: 6122
diff changeset
    99
                throws BadPaddingException, IllegalBlockSizeException {
b7fe0ebc290c 6687725: Internal PKCS5Padding impl should throw IllegalBlockSizeException and not BadPaddingException
valeriep
parents: 6122
diff changeset
   100
            if ((len < 1) || (len % blockSize != 0)) {
b7fe0ebc290c 6687725: Internal PKCS5Padding impl should throw IllegalBlockSizeException and not BadPaddingException
valeriep
parents: 6122
diff changeset
   101
                throw new IllegalBlockSizeException
b7fe0ebc290c 6687725: Internal PKCS5Padding impl should throw IllegalBlockSizeException and not BadPaddingException
valeriep
parents: 6122
diff changeset
   102
                    ("Input length must be multiples of " + blockSize);
296
a26e4ea2ca63 6682411: JCK test failed w/ ArrayIndexOutOfBoundException (-1) when decrypting with no data
valeriep
parents: 289
diff changeset
   103
            }
a26e4ea2ca63 6682411: JCK test failed w/ ArrayIndexOutOfBoundException (-1) when decrypting with no data
valeriep
parents: 289
diff changeset
   104
            byte padValue = paddedData[len - 1];
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   105
            if (padValue < 1 || padValue > blockSize) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   106
                throw new BadPaddingException("Invalid pad value!");
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   107
            }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   108
            // sanity check padding bytes
296
a26e4ea2ca63 6682411: JCK test failed w/ ArrayIndexOutOfBoundException (-1) when decrypting with no data
valeriep
parents: 289
diff changeset
   109
            int padStartIndex = len - padValue;
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   110
            for (int i = padStartIndex; i < len; i++) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   111
                if (paddedData[i] != padValue) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   112
                    throw new BadPaddingException("Invalid pad bytes!");
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   113
                }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   114
            }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   115
            return padValue;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   116
        }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   117
    }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   118
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
    // token instance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
    private final Token token;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    // algorithm name
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
    private final String algorithm;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
    // name of the key algorithm, e.g. DES instead of algorithm DES/CBC/...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    private final String keyAlgorithm;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    // mechanism id
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    private final long mechanism;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
    // associated session, if any
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
    private Session session;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
    // key, if init() was called
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
    private P11Key p11Key;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
    // flag indicating whether an operation is initialized
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
    private boolean initialized;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
    // falg indicating encrypt or decrypt mode
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
    private boolean encrypt;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
    // mode, one of MODE_* above (MODE_ECB for stream ciphers)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
    private int blockMode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
    // block size, 0 for stream ciphers
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
    private final int blockSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
    // padding type, on of PAD_* above (PAD_NONE for stream ciphers)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
    private int paddingType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   152
    // when the padding is requested but unsupported by the native mechanism,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   153
    // we use the following to do padding and necessary data buffering.
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   154
    // padding object which generate padding and unpad the decrypted data
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   155
    private Padding paddingObj;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   156
    // buffer for holding back the block which contains padding bytes
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   157
    private byte[] padBuffer;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   158
    private int padBufferLen;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   159
8542
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   160
    // original IV, if in MODE_CBC or MODE_CTR
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
    private byte[] iv;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   163
    // number of bytes buffered internally by the native mechanism and padBuffer
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   164
    // if we do the padding
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   165
    private int bytesBuffered;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
    P11Cipher(Token token, String algorithm, long mechanism)
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   168
            throws PKCS11Exception, NoSuchAlgorithmException {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
        super();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        this.token = token;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
        this.algorithm = algorithm;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        this.mechanism = mechanism;
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   173
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   174
        String algoParts[] = algorithm.split("/");
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   175
        keyAlgorithm = algoParts[0];
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   176
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
        if (keyAlgorithm.equals("AES")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
            blockSize = 16;
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   179
        } else if (keyAlgorithm.equals("RC4") ||
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   180
                keyAlgorithm.equals("ARCFOUR")) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
            blockSize = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
        } else { // DES, DESede, Blowfish
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
            blockSize = 8;
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   184
        }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   185
        this.blockMode =
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   186
                (algoParts.length > 1 ? parseMode(algoParts[1]) : MODE_ECB);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   187
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   188
        String defPadding = (blockSize == 0 ? "NoPadding" : "PKCS5Padding");
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   189
        String paddingStr =
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   190
                (algoParts.length > 2 ? algoParts[2] : defPadding);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   191
        try {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   192
            engineSetPadding(paddingStr);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   193
        } catch (NoSuchPaddingException nspe) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   194
            // should not happen
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   195
            throw new ProviderException(nspe);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
    protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   200
        // Disallow change of mode for now since currently it's explicitly
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   201
        // defined in transformation strings
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   202
        throw new NoSuchAlgorithmException("Unsupported mode " + mode);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   203
    }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   204
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   205
    private int parseMode(String mode) throws NoSuchAlgorithmException {
6122
16fa7ed7ff1b 6867345: Turkish regional options cause NPE in sun.security.x509.AlgorithmId.algOID
xuelei
parents: 5506
diff changeset
   206
        mode = mode.toUpperCase(Locale.ENGLISH);
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   207
        int result;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        if (mode.equals("ECB")) {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   209
            result = MODE_ECB;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
        } else if (mode.equals("CBC")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
            if (blockSize == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
                throw new NoSuchAlgorithmException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
                        ("CBC mode not supported with stream ciphers");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
            }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   215
            result = MODE_CBC;
8542
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   216
        } else if (mode.equals("CTR")) {
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   217
            result = MODE_CTR;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
            throw new NoSuchAlgorithmException("Unsupported mode " + mode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
        }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   221
        return result;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
    // see JCE spec
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
    protected void engineSetPadding(String padding)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
            throws NoSuchPaddingException {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   227
        paddingObj = null;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   228
        padBuffer = null;
6122
16fa7ed7ff1b 6867345: Turkish regional options cause NPE in sun.security.x509.AlgorithmId.algOID
xuelei
parents: 5506
diff changeset
   229
        padding = padding.toUpperCase(Locale.ENGLISH);
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   230
        if (padding.equals("NOPADDING")) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
            paddingType = PAD_NONE;
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   232
        } else if (padding.equals("PKCS5PADDING")) {
8542
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   233
            if (this.blockMode == MODE_CTR) {
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   234
                throw new NoSuchPaddingException
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   235
                    ("PKCS#5 padding not supported with CTR mode");
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   236
            }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   237
            paddingType = PAD_PKCS5;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   238
            if (mechanism != CKM_DES_CBC_PAD && mechanism != CKM_DES3_CBC_PAD &&
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   239
                    mechanism != CKM_AES_CBC_PAD) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   240
                // no native padding support; use our own padding impl
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   241
                paddingObj = new PKCS5Padding(blockSize);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   242
                padBuffer = new byte[blockSize];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
            throw new NoSuchPaddingException("Unsupported padding " + padding);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
    // see JCE spec
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
    protected int engineGetBlockSize() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
        return blockSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
    // see JCE spec
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
    protected int engineGetOutputSize(int inputLen) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
        return doFinalLength(inputLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
    // see JCE spec
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
    protected byte[] engineGetIV() {
10336
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 8542
diff changeset
   261
        return (iv == null) ? null : iv.clone();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
    // see JCE spec
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
    protected AlgorithmParameters engineGetParameters() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
        if (iv == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
        try {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   271
            AlgorithmParameters params =
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   272
                    AlgorithmParameters.getInstance(keyAlgorithm,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   273
                    P11Util.getSunJceProvider());
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
            params.init(ivSpec);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
            return params;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
        } catch (GeneralSecurityException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
            // NoSuchAlgorithmException, NoSuchProviderException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
            // InvalidParameterSpecException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
            throw new ProviderException("Could not encode parameters", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
    // see JCE spec
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
    protected void engineInit(int opmode, Key key, SecureRandom random)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
            throws InvalidKeyException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
            implInit(opmode, key, null, random);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
        } catch (InvalidAlgorithmParameterException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
            throw new InvalidKeyException("init() failed", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
    // see JCE spec
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
    protected void engineInit(int opmode, Key key,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
            AlgorithmParameterSpec params, SecureRandom random)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
            throws InvalidKeyException, InvalidAlgorithmParameterException {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   297
        byte[] ivValue;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
        if (params != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
            if (params instanceof IvParameterSpec == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
                throw new InvalidAlgorithmParameterException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
                        ("Only IvParameterSpec supported");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
            }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   303
            IvParameterSpec ivSpec = (IvParameterSpec) params;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   304
            ivValue = ivSpec.getIV();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
        } else {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   306
            ivValue = null;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
        }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   308
        implInit(opmode, key, ivValue, random);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
    // see JCE spec
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
    protected void engineInit(int opmode, Key key, AlgorithmParameters params,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
            SecureRandom random)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
            throws InvalidKeyException, InvalidAlgorithmParameterException {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   315
        byte[] ivValue;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
        if (params != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
            try {
10336
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 8542
diff changeset
   318
                IvParameterSpec ivSpec =
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
                        params.getParameterSpec(IvParameterSpec.class);
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   320
                ivValue = ivSpec.getIV();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
            } catch (InvalidParameterSpecException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
                throw new InvalidAlgorithmParameterException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
                        ("Could not decode IV", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
        } else {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   326
            ivValue = null;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
        }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   328
        implInit(opmode, key, ivValue, random);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
    // actual init() implementation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
    private void implInit(int opmode, Key key, byte[] iv,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
            SecureRandom random)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
            throws InvalidKeyException, InvalidAlgorithmParameterException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
        cancelOperation();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
        switch (opmode) {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   337
            case Cipher.ENCRYPT_MODE:
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   338
                encrypt = true;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   339
                break;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   340
            case Cipher.DECRYPT_MODE:
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   341
                encrypt = false;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   342
                break;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   343
            default:
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   344
                throw new InvalidAlgorithmParameterException
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   345
                        ("Unsupported mode: " + opmode);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
        if (blockMode == MODE_ECB) { // ECB or stream cipher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
            if (iv != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
                if (blockSize == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
                    throw new InvalidAlgorithmParameterException
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   351
                            ("IV not used with stream ciphers");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
                    throw new InvalidAlgorithmParameterException
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   354
                            ("IV not used in ECB mode");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
            }
8542
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   357
        } else { // MODE_CBC or MODE_CTR
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
            if (iv == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
                if (encrypt == false) {
8542
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   360
                    String exMsg =
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   361
                        (blockMode == MODE_CBC ?
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   362
                         "IV must be specified for decryption in CBC mode" :
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   363
                         "IV must be specified for decryption in CTR mode");
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   364
                    throw new InvalidAlgorithmParameterException(exMsg);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
                // generate random IV
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
                if (random == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
                    random = new SecureRandom();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
                iv = new byte[blockSize];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
                random.nextBytes(iv);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
                if (iv.length != blockSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
                    throw new InvalidAlgorithmParameterException
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   375
                            ("IV length must match block size");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        this.iv = iv;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        p11Key = P11SecretKeyFactory.convertKey(token, key, keyAlgorithm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
            initialize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
        } catch (PKCS11Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
            throw new InvalidKeyException("Could not initialize cipher", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
    private void cancelOperation() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
        if (initialized == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        initialized = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
        if ((session == null) || (token.explicitCancel == false)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
        // cancel operation by finishing it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
        int bufLen = doFinalLength(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
        byte[] buffer = new byte[bufLen];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
            if (encrypt) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
                token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
                token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
        } catch (PKCS11Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
            throw new ProviderException("Cancel failed", e);
7812
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   407
        } finally {
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   408
            reset();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
    private void ensureInitialized() throws PKCS11Exception {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
        if (initialized == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
            initialize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
    private void initialize() throws PKCS11Exception {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
        if (session == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
            session = token.getOpSession();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
        }
8542
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   422
        CK_MECHANISM mechParams = (blockMode == MODE_CTR?
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   423
            new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) :
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   424
            new CK_MECHANISM(mechanism, iv));
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   425
7812
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   426
        try {
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   427
            if (encrypt) {
8542
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   428
                token.p11.C_EncryptInit(session.id(), mechParams, p11Key.keyID);
7812
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   429
            } else {
8542
62c7b10ce177 6604496: Support for CKM_AES_CTR (counter mode)
valeriep
parents: 7812
diff changeset
   430
                token.p11.C_DecryptInit(session.id(), mechParams, p11Key.keyID);
7812
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   431
            }
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   432
        } catch (PKCS11Exception ex) {
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   433
            // release session when initialization failed
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   434
            session = token.releaseSession(session);
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   435
            throw ex;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
        }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   437
        bytesBuffered = 0;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   438
        padBufferLen = 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        initialized = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
    // if update(inLen) is called, how big does the output buffer have to be?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
    private int updateLength(int inLen) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
        if (inLen <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
        }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   447
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   448
        int result = inLen + bytesBuffered;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   449
        if (blockSize != 0) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   450
            // minus the number of bytes in the last incomplete block.
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   451
            result -= (result & (blockSize - 1));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
        }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   453
        return result;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
    // if doFinal(inLen) is called, how big does the output buffer have to be?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
    private int doFinalLength(int inLen) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
        if (inLen < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
        }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   461
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   462
        int result = inLen + bytesBuffered;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   463
        if (blockSize != 0 && encrypt && paddingType != PAD_NONE) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   464
            // add the number of bytes to make the last block complete.
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   465
            result += (blockSize - (result & (blockSize - 1)));
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   466
        }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   467
        return result;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
7812
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   470
    // reset the states to the pre-initialized values
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   471
    private void reset() {
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   472
        initialized = false;
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   473
        bytesBuffered = 0;
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   474
        padBufferLen = 0;
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   475
        if (session != null) {
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   476
            session = token.releaseSession(session);
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   477
        }
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   478
    }
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   479
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
    // see JCE spec
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
    protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
            byte[] out = new byte[updateLength(inLen)];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
            int n = engineUpdate(in, inOfs, inLen, out, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
            return P11Util.convert(out, 0, n);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
        } catch (ShortBufferException e) {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   487
            // convert since the output length is calculated by updateLength()
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
            throw new ProviderException(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
    // see JCE spec
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
    protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
            int outOfs) throws ShortBufferException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
        int outLen = out.length - outOfs;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
        return implUpdate(in, inOfs, inLen, out, outOfs, outLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
    // see JCE spec
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   500
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
    protected int engineUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
            throws ShortBufferException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
        return implUpdate(inBuffer, outBuffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
    // see JCE spec
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
    protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
            throws IllegalBlockSizeException, BadPaddingException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
            byte[] out = new byte[doFinalLength(inLen)];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
            int n = engineDoFinal(in, inOfs, inLen, out, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
            return P11Util.convert(out, 0, n);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
        } catch (ShortBufferException e) {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   514
            // convert since the output length is calculated by doFinalLength()
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
            throw new ProviderException(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
    // see JCE spec
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
    protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   521
            int outOfs) throws ShortBufferException, IllegalBlockSizeException,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   522
            BadPaddingException {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
        int n = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
        if ((inLen != 0) && (in != null)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
            n = engineUpdate(in, inOfs, inLen, out, outOfs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
            outOfs += n;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
        n += implDoFinal(out, outOfs, out.length - outOfs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
        return n;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
    // see JCE spec
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   533
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
    protected int engineDoFinal(ByteBuffer inBuffer, ByteBuffer outBuffer)
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   535
            throws ShortBufferException, IllegalBlockSizeException,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   536
            BadPaddingException {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
        int n = engineUpdate(inBuffer, outBuffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
        n += implDoFinal(outBuffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
        return n;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
    private int implUpdate(byte[] in, int inOfs, int inLen,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
            byte[] out, int outOfs, int outLen) throws ShortBufferException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
        if (outLen < updateLength(inLen)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
            throw new ShortBufferException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
            ensureInitialized();
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   549
            int k = 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
            if (encrypt) {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   551
                k = token.p11.C_EncryptUpdate(session.id(), 0, in, inOfs, inLen,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   552
                        0, out, outOfs, outLen);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
            } else {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   554
                int newPadBufferLen = 0;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   555
                if (paddingObj != null) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   556
                    if (padBufferLen != 0) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   557
                        // NSS throws up when called with data not in multiple
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   558
                        // of blocks. Try to work around this by holding the
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   559
                        // extra data in padBuffer.
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   560
                        if (padBufferLen != padBuffer.length) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   561
                            int bufCapacity = padBuffer.length - padBufferLen;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   562
                            if (inLen > bufCapacity) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   563
                                bufferInputBytes(in, inOfs, bufCapacity);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   564
                                inOfs += bufCapacity;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   565
                                inLen -= bufCapacity;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   566
                            } else {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   567
                                bufferInputBytes(in, inOfs, inLen);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   568
                                return 0;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   569
                            }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   570
                        }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   571
                        k = token.p11.C_DecryptUpdate(session.id(),
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   572
                                0, padBuffer, 0, padBufferLen,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   573
                                0, out, outOfs, outLen);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   574
                        padBufferLen = 0;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   575
                    }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   576
                    newPadBufferLen = inLen & (blockSize - 1);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   577
                    if (newPadBufferLen == 0) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   578
                        newPadBufferLen = padBuffer.length;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   579
                    }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   580
                    inLen -= newPadBufferLen;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   581
                }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   582
                if (inLen > 0) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   583
                    k += token.p11.C_DecryptUpdate(session.id(), 0, in, inOfs,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   584
                            inLen, 0, out, (outOfs + k), (outLen - k));
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   585
                }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   586
                // update 'padBuffer' if using our own padding impl.
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   587
                if (paddingObj != null) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   588
                    bufferInputBytes(in, inOfs + inLen, newPadBufferLen);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   589
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
            }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   591
            bytesBuffered += (inLen - k);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
            return k;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
        } catch (PKCS11Exception e) {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   594
            if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   595
                throw (ShortBufferException)
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   596
                        (new ShortBufferException().initCause(e));
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   597
            }
7812
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   598
            reset();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
            throw new ProviderException("update() failed", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
    private int implUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
            throws ShortBufferException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
        int inLen = inBuffer.remaining();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
        if (inLen <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
        int outLen = outBuffer.remaining();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
        if (outLen < updateLength(inLen)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
            throw new ShortBufferException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
        }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   614
        int origPos = inBuffer.position();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
            ensureInitialized();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
            long inAddr = 0;
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   619
            int inOfs = 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
            byte[] inArray = null;
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   621
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
            if (inBuffer instanceof DirectBuffer) {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   623
                inAddr = ((DirectBuffer) inBuffer).address();
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   624
                inOfs = origPos;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   625
            } else if (inBuffer.hasArray()) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   626
                inArray = inBuffer.array();
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   627
                inOfs = (origPos + inBuffer.arrayOffset());
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
            long outAddr = 0;
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   631
            int outOfs = 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
            byte[] outArray = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
            if (outBuffer instanceof DirectBuffer) {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   634
                outAddr = ((DirectBuffer) outBuffer).address();
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   635
                outOfs = outBuffer.position();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
                if (outBuffer.hasArray()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
                    outArray = outBuffer.array();
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   639
                    outOfs = (outBuffer.position() + outBuffer.arrayOffset());
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
                    outArray = new byte[outLen];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   645
            int k = 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
            if (encrypt) {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   647
                if (inAddr == 0 && inArray == null) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   648
                    inArray = new byte[inLen];
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   649
                    inBuffer.get(inArray);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   650
                } else {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   651
                    inBuffer.position(origPos + inLen);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   652
                }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   653
                k = token.p11.C_EncryptUpdate(session.id(),
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   654
                        inAddr, inArray, inOfs, inLen,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   655
                        outAddr, outArray, outOfs, outLen);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
            } else {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   657
                int newPadBufferLen = 0;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   658
                if (paddingObj != null) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   659
                    if (padBufferLen != 0) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   660
                        // NSS throws up when called with data not in multiple
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   661
                        // of blocks. Try to work around this by holding the
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   662
                        // extra data in padBuffer.
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   663
                        if (padBufferLen != padBuffer.length) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   664
                            int bufCapacity = padBuffer.length - padBufferLen;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   665
                            if (inLen > bufCapacity) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   666
                                bufferInputBytes(inBuffer, bufCapacity);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   667
                                inOfs += bufCapacity;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   668
                                inLen -= bufCapacity;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   669
                            } else {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   670
                                bufferInputBytes(inBuffer, inLen);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   671
                                return 0;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   672
                            }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   673
                        }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   674
                        k = token.p11.C_DecryptUpdate(session.id(), 0,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   675
                                padBuffer, 0, padBufferLen, outAddr, outArray,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   676
                                outOfs, outLen);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   677
                        padBufferLen = 0;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   678
                    }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   679
                    newPadBufferLen = inLen & (blockSize - 1);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   680
                    if (newPadBufferLen == 0) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   681
                        newPadBufferLen = padBuffer.length;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   682
                    }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   683
                    inLen -= newPadBufferLen;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   684
                }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   685
                if (inLen > 0) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   686
                    if (inAddr == 0 && inArray == null) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   687
                        inArray = new byte[inLen];
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   688
                        inBuffer.get(inArray);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   689
                    } else {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   690
                        inBuffer.position(inBuffer.position() + inLen);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   691
                    }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   692
                    k += token.p11.C_DecryptUpdate(session.id(), inAddr,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   693
                            inArray, inOfs, inLen, outAddr, outArray,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   694
                            (outOfs + k), (outLen - k));
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   695
                }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   696
                // update 'padBuffer' if using our own padding impl.
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   697
                if (paddingObj != null && newPadBufferLen != 0) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   698
                    bufferInputBytes(inBuffer, newPadBufferLen);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   699
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
            }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   701
            bytesBuffered += (inLen - k);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
            if (!(outBuffer instanceof DirectBuffer) &&
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   703
                    !outBuffer.hasArray()) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
                outBuffer.put(outArray, outOfs, k);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
                outBuffer.position(outBuffer.position() + k);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
            return k;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
        } catch (PKCS11Exception e) {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   710
            // Reset input buffer to its original position for
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   711
            inBuffer.position(origPos);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   712
            if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   713
                throw (ShortBufferException)
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   714
                        (new ShortBufferException().initCause(e));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
            }
7812
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   716
            reset();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
            throw new ProviderException("update() failed", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
    private int implDoFinal(byte[] out, int outOfs, int outLen)
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   722
            throws ShortBufferException, IllegalBlockSizeException,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   723
            BadPaddingException {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   724
        int requiredOutLen = doFinalLength(0);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   725
        if (outLen < requiredOutLen) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
            throw new ShortBufferException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
            ensureInitialized();
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   730
            int k = 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
            if (encrypt) {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   732
                if (paddingObj != null) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   733
                    int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   734
                            requiredOutLen - bytesBuffered);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   735
                    k = token.p11.C_EncryptUpdate(session.id(),
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   736
                            0, padBuffer, 0, actualPadLen,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   737
                            0, out, outOfs, outLen);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   738
                }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   739
                k += token.p11.C_EncryptFinal(session.id(),
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   740
                        0, out, (outOfs + k), (outLen - k));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
            } else {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   742
                if (paddingObj != null) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   743
                    if (padBufferLen != 0) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   744
                        k = token.p11.C_DecryptUpdate(session.id(), 0,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   745
                                padBuffer, 0, padBufferLen, 0, padBuffer, 0,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   746
                                padBuffer.length);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   747
                    }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   748
                    k += token.p11.C_DecryptFinal(session.id(), 0, padBuffer, k,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   749
                            padBuffer.length - k);
296
a26e4ea2ca63 6682411: JCK test failed w/ ArrayIndexOutOfBoundException (-1) when decrypting with no data
valeriep
parents: 289
diff changeset
   750
                    int actualPadLen = paddingObj.unpad(padBuffer, k);
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   751
                    k -= actualPadLen;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   752
                    System.arraycopy(padBuffer, 0, out, outOfs, k);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   753
                } else {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   754
                    k = token.p11.C_DecryptFinal(session.id(), 0, out, outOfs,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   755
                            outLen);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   756
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
            }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   758
            return k;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
        } catch (PKCS11Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
            handleException(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
            throw new ProviderException("doFinal() failed", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
        } finally {
7812
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   763
            reset();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
    private int implDoFinal(ByteBuffer outBuffer)
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   768
            throws ShortBufferException, IllegalBlockSizeException,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   769
            BadPaddingException {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
        int outLen = outBuffer.remaining();
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   771
        int requiredOutLen = doFinalLength(0);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   772
        if (outLen < requiredOutLen) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
            throw new ShortBufferException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
            ensureInitialized();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
            long outAddr = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
            byte[] outArray = null;
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   781
            int outOfs = 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
            if (outBuffer instanceof DirectBuffer) {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   783
                outAddr = ((DirectBuffer) outBuffer).address();
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   784
                outOfs = outBuffer.position();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
                if (outBuffer.hasArray()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
                    outArray = outBuffer.array();
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   788
                    outOfs = outBuffer.position() + outBuffer.arrayOffset();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
                    outArray = new byte[outLen];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   794
            int k = 0;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   795
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
            if (encrypt) {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   797
                if (paddingObj != null) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   798
                    int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   799
                            requiredOutLen - bytesBuffered);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   800
                    k = token.p11.C_EncryptUpdate(session.id(),
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   801
                            0, padBuffer, 0, actualPadLen,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   802
                            outAddr, outArray, outOfs, outLen);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   803
                }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   804
                k += token.p11.C_EncryptFinal(session.id(),
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   805
                        outAddr, outArray, (outOfs + k), (outLen - k));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
            } else {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   807
                if (paddingObj != null) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   808
                    if (padBufferLen != 0) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   809
                        k = token.p11.C_DecryptUpdate(session.id(),
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   810
                                0, padBuffer, 0, padBufferLen,
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   811
                                0, padBuffer, 0, padBuffer.length);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   812
                        padBufferLen = 0;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   813
                    }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   814
                    k += token.p11.C_DecryptFinal(session.id(),
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   815
                            0, padBuffer, k, padBuffer.length - k);
296
a26e4ea2ca63 6682411: JCK test failed w/ ArrayIndexOutOfBoundException (-1) when decrypting with no data
valeriep
parents: 289
diff changeset
   816
                    int actualPadLen = paddingObj.unpad(padBuffer, k);
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   817
                    k -= actualPadLen;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   818
                    outArray = padBuffer;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   819
                    outOfs = 0;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   820
                } else {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   821
                    k = token.p11.C_DecryptFinal(session.id(),
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   822
                            outAddr, outArray, outOfs, outLen);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   823
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
            }
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   825
            if ((!encrypt && paddingObj != null) ||
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   826
                    (!(outBuffer instanceof DirectBuffer) &&
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   827
                    !outBuffer.hasArray())) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
                outBuffer.put(outArray, outOfs, k);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
                outBuffer.position(outBuffer.position() + k);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
            return k;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
        } catch (PKCS11Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
            handleException(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
            throw new ProviderException("doFinal() failed", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
        } finally {
7812
ed539cb9eb27 6924489: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OPERATION_NOT_INITIALIZED
valeriep
parents: 7269
diff changeset
   837
            reset();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
    private void handleException(PKCS11Exception e)
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   842
            throws ShortBufferException, IllegalBlockSizeException {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
        long errorCode = e.getErrorCode();
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   844
        if (errorCode == CKR_BUFFER_TOO_SMALL) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   845
            throw (ShortBufferException)
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   846
                    (new ShortBufferException().initCause(e));
297
bec12c857972 6682417: JCK test failed w/ ProviderException when decrypted data is not multiple of blocks
valeriep
parents: 296
diff changeset
   847
        } else if (errorCode == CKR_DATA_LEN_RANGE ||
bec12c857972 6682417: JCK test failed w/ ProviderException when decrypted data is not multiple of blocks
valeriep
parents: 296
diff changeset
   848
                   errorCode == CKR_ENCRYPTED_DATA_LEN_RANGE) {
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   849
            throw (IllegalBlockSizeException)
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   850
                    (new IllegalBlockSizeException(e.toString()).initCause(e));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
    // see JCE spec
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
    protected byte[] engineWrap(Key key) throws IllegalBlockSizeException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
            InvalidKeyException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
        // XXX key wrapping
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
        throw new UnsupportedOperationException("engineWrap()");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
    // see JCE spec
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
    protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
            int wrappedKeyType)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
            throws InvalidKeyException, NoSuchAlgorithmException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
        // XXX key unwrapping
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
        throw new UnsupportedOperationException("engineUnwrap()");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
    // see JCE spec
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   870
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
    protected int engineGetKeySize(Key key) throws InvalidKeyException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
        int n = P11SecretKeyFactory.convertKey
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   873
                (token, key, keyAlgorithm).keyLength();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
        return n;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
289
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   877
    private final void bufferInputBytes(byte[] in, int inOfs, int len) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   878
        System.arraycopy(in, inOfs, padBuffer, padBufferLen, len);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   879
        padBufferLen += len;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   880
        bytesBuffered += len;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   881
    }
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   882
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   883
    private final void bufferInputBytes(ByteBuffer inBuffer, int len) {
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   884
        inBuffer.get(padBuffer, padBufferLen, len);
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   885
        padBufferLen += len;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   886
        bytesBuffered += len;
b1c8ad73578f 4898461: Support for ECB and CBC/PKCS5Padding
valeriep
parents: 2
diff changeset
   887
    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
}