Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/pkcs11/P11Digest.java
38919 views
/*1* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.pkcs11;2627import java.util.*;28import java.nio.ByteBuffer;2930import java.security.*;3132import javax.crypto.SecretKey;3334import sun.nio.ch.DirectBuffer;3536import sun.security.util.MessageDigestSpi2;3738import sun.security.pkcs11.wrapper.*;39import static sun.security.pkcs11.wrapper.PKCS11Constants.*;4041/**42* MessageDigest implementation class. This class currently supports43* MD2, MD5, SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512.44*45* Note that many digest operations are on fairly small amounts of data46* (less than 100 bytes total). For example, the 2nd hashing in HMAC or47* the PRF in TLS. In order to speed those up, we use some buffering to48* minimize number of the Java->native transitions.49*50* @author Andreas Sterbenz51* @since 1.552*/53final class P11Digest extends MessageDigestSpi implements Cloneable,54MessageDigestSpi2 {5556/* fields initialized, no session acquired */57private final static int S_BLANK = 1;5859/* data in buffer, session acquired, but digest not initialized */60private final static int S_BUFFERED = 2;6162/* session initialized for digesting */63private final static int S_INIT = 3;6465private final static int BUFFER_SIZE = 96;6667// token instance68private final Token token;6970// algorithm name71private final String algorithm;7273// mechanism id object74private final CK_MECHANISM mechanism;7576// length of the digest in bytes77private final int digestLength;7879// associated session, if any80private Session session;8182// current state, one of S_* above83private int state;8485// buffer to reduce number of JNI calls86private byte[] buffer;8788// offset into the buffer89private int bufOfs;9091P11Digest(Token token, String algorithm, long mechanism) {92super();93this.token = token;94this.algorithm = algorithm;95this.mechanism = new CK_MECHANISM(mechanism);96switch ((int)mechanism) {97case (int)CKM_MD2:98case (int)CKM_MD5:99digestLength = 16;100break;101case (int)CKM_SHA_1:102digestLength = 20;103break;104case (int)CKM_SHA224:105digestLength = 28;106break;107case (int)CKM_SHA256:108digestLength = 32;109break;110case (int)CKM_SHA384:111digestLength = 48;112break;113case (int)CKM_SHA512:114digestLength = 64;115break;116default:117throw new ProviderException("Unknown mechanism: " + mechanism);118}119buffer = new byte[BUFFER_SIZE];120state = S_BLANK;121}122123// see JCA spec124protected int engineGetDigestLength() {125return digestLength;126}127128private void fetchSession() {129token.ensureValid();130if (state == S_BLANK) {131try {132session = token.getOpSession();133state = S_BUFFERED;134} catch (PKCS11Exception e) {135throw new ProviderException("No more session available", e);136}137}138}139140// see JCA spec141protected void engineReset() {142token.ensureValid();143144if (session != null) {145if (state == S_INIT && token.explicitCancel == true146&& session.hasObjects() == false) {147session = token.killSession(session);148} else {149session = token.releaseSession(session);150}151}152state = S_BLANK;153bufOfs = 0;154}155156// see JCA spec157protected byte[] engineDigest() {158try {159byte[] digest = new byte[digestLength];160int n = engineDigest(digest, 0, digestLength);161return digest;162} catch (DigestException e) {163throw new ProviderException("internal error", e);164}165}166167// see JCA spec168protected int engineDigest(byte[] digest, int ofs, int len)169throws DigestException {170if (len < digestLength) {171throw new DigestException("Length must be at least " +172digestLength);173}174175fetchSession();176try {177int n;178if (state == S_BUFFERED) {179n = token.p11.C_DigestSingle(session.id(), mechanism, buffer, 0,180bufOfs, digest, ofs, len);181bufOfs = 0;182} else {183if (bufOfs != 0) {184token.p11.C_DigestUpdate(session.id(), 0, buffer, 0,185bufOfs);186bufOfs = 0;187}188n = token.p11.C_DigestFinal(session.id(), digest, ofs, len);189}190if (n != digestLength) {191throw new ProviderException("internal digest length error");192}193return n;194} catch (PKCS11Exception e) {195throw new ProviderException("digest() failed", e);196} finally {197engineReset();198}199}200201// see JCA spec202protected void engineUpdate(byte in) {203byte[] temp = { in };204engineUpdate(temp, 0, 1);205}206207// see JCA spec208protected void engineUpdate(byte[] in, int ofs, int len) {209if (len <= 0) {210return;211}212213fetchSession();214try {215if (state == S_BUFFERED) {216token.p11.C_DigestInit(session.id(), mechanism);217state = S_INIT;218}219if ((bufOfs != 0) && (bufOfs + len > buffer.length)) {220// process the buffered data221token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);222bufOfs = 0;223}224if (bufOfs + len > buffer.length) {225// process the new data226token.p11.C_DigestUpdate(session.id(), 0, in, ofs, len);227} else {228// buffer the new data229System.arraycopy(in, ofs, buffer, bufOfs, len);230bufOfs += len;231}232} catch (PKCS11Exception e) {233engineReset();234throw new ProviderException("update() failed", e);235}236}237238// Called by SunJSSE via reflection during the SSL 3.0 handshake if239// the master secret is sensitive.240// Note: Change to protected after this method is moved from241// sun.security.util.MessageSpi2 interface to242// java.security.MessageDigestSpi class243public void engineUpdate(SecretKey key) throws InvalidKeyException {244// SunJSSE calls this method only if the key does not have a RAW245// encoding, i.e. if it is sensitive. Therefore, no point in calling246// SecretKeyFactory to try to convert it. Just verify it ourselves.247if (key instanceof P11Key == false) {248throw new InvalidKeyException("Not a P11Key: " + key);249}250P11Key p11Key = (P11Key)key;251if (p11Key.token != token) {252throw new InvalidKeyException("Not a P11Key of this provider: " +253key);254}255256fetchSession();257long p11KeyID = p11Key.getKeyID();258try {259if (state == S_BUFFERED) {260token.p11.C_DigestInit(session.id(), mechanism);261state = S_INIT;262}263264if (bufOfs != 0) {265token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);266bufOfs = 0;267}268token.p11.C_DigestKey(session.id(), p11KeyID);269} catch (PKCS11Exception e) {270engineReset();271throw new ProviderException("update(SecretKey) failed", e);272} finally {273p11Key.releaseKeyID();274}275}276277// see JCA spec278protected void engineUpdate(ByteBuffer byteBuffer) {279int len = byteBuffer.remaining();280if (len <= 0) {281return;282}283284if (byteBuffer instanceof DirectBuffer == false) {285super.engineUpdate(byteBuffer);286return;287}288289fetchSession();290long addr = ((DirectBuffer)byteBuffer).address();291int ofs = byteBuffer.position();292try {293if (state == S_BUFFERED) {294token.p11.C_DigestInit(session.id(), mechanism);295state = S_INIT;296}297if (bufOfs != 0) {298token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);299bufOfs = 0;300}301token.p11.C_DigestUpdate(session.id(), addr + ofs, null, 0, len);302byteBuffer.position(ofs + len);303} catch (PKCS11Exception e) {304engineReset();305throw new ProviderException("update() failed", e);306}307}308309public Object clone() throws CloneNotSupportedException {310P11Digest copy = (P11Digest) super.clone();311copy.buffer = buffer.clone();312try {313if (session != null) {314copy.session = copy.token.getOpSession();315}316if (state == S_INIT) {317byte[] stateValues =318token.p11.C_GetOperationState(session.id());319token.p11.C_SetOperationState(copy.session.id(),320stateValues, 0, 0);321}322} catch (PKCS11Exception e) {323throw (CloneNotSupportedException)324(new CloneNotSupportedException(algorithm).initCause(e));325}326return copy;327}328}329330331