Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/provider/DigestBase.java
38830 views
/*1* Copyright (c) 2003, 2014, 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.provider;2627import java.security.MessageDigestSpi;28import java.security.DigestException;29import java.security.ProviderException;30import java.util.Arrays;31import java.util.Objects;3233/**34* Common base message digest implementation for the Sun provider.35* It implements all the JCA methods as suitable for a Java message digest36* implementation of an algorithm based on a compression function (as all37* commonly used algorithms are). The individual digest subclasses only need to38* implement the following methods:39*40* . abstract void implCompress(byte[] b, int ofs);41* . abstract void implDigest(byte[] out, int ofs);42* . abstract void implReset();43*44* See the inline documentation for details.45*46* @since 1.547* @author Andreas Sterbenz48*/49abstract class DigestBase extends MessageDigestSpi implements Cloneable {5051// one element byte array, temporary storage for update(byte)52private byte[] oneByte;5354// algorithm name to use in the exception message55private final String algorithm;56// length of the message digest in bytes57private final int digestLength;5859// size of the input to the compression function in bytes60private final int blockSize;61// buffer to store partial blocks, blockSize bytes large62// Subclasses should not access this array directly except possibly in their63// implDigest() method. See MD5.java as an example.64byte[] buffer;65// offset into buffer66private int bufOfs;6768// number of bytes processed so far. subclasses should not modify69// this value.70// also used as a flag to indicate reset status71// -1: need to call engineReset() before next call to update()72// 0: is already reset73long bytesProcessed;7475/**76* Main constructor.77*/78DigestBase(String algorithm, int digestLength, int blockSize) {79super();80this.algorithm = algorithm;81this.digestLength = digestLength;82this.blockSize = blockSize;83buffer = new byte[blockSize];84}8586// return digest length. See JCA doc.87protected final int engineGetDigestLength() {88return digestLength;89}9091// single byte update. See JCA doc.92protected final void engineUpdate(byte b) {93if (oneByte == null) {94oneByte = new byte[1];95}96oneByte[0] = b;97engineUpdate(oneByte, 0, 1);98}99100// array update. See JCA doc.101protected final void engineUpdate(byte[] b, int ofs, int len) {102if (len == 0) {103return;104}105if ((ofs < 0) || (len < 0) || (ofs > b.length - len)) {106throw new ArrayIndexOutOfBoundsException();107}108if (bytesProcessed < 0) {109engineReset();110}111bytesProcessed += len;112// if buffer is not empty, we need to fill it before proceeding113if (bufOfs != 0) {114int n = Math.min(len, blockSize - bufOfs);115System.arraycopy(b, ofs, buffer, bufOfs, n);116bufOfs += n;117ofs += n;118len -= n;119if (bufOfs >= blockSize) {120// compress completed block now121implCompress(buffer, 0);122bufOfs = 0;123}124}125// compress complete blocks126if (len >= blockSize) {127int limit = ofs + len;128ofs = implCompressMultiBlock(b, ofs, limit - blockSize);129len = limit - ofs;130}131// copy remainder to buffer132if (len > 0) {133System.arraycopy(b, ofs, buffer, 0, len);134bufOfs = len;135}136}137138// compress complete blocks139private int implCompressMultiBlock(byte[] b, int ofs, int limit) {140implCompressMultiBlockCheck(b, ofs, limit);141return implCompressMultiBlock0(b, ofs, limit);142}143144private int implCompressMultiBlock0(byte[] b, int ofs, int limit) {145for (; ofs <= limit; ofs += blockSize) {146implCompress(b, ofs);147}148return ofs;149}150151private void implCompressMultiBlockCheck(byte[] b, int ofs, int limit) {152if (limit < 0) {153return; // not an error because implCompressMultiBlockImpl won't execute if limit < 0154// and an exception is thrown if ofs < 0.155}156157Objects.requireNonNull(b);158159if (ofs < 0 || ofs >= b.length) {160throw new ArrayIndexOutOfBoundsException(ofs);161}162163int endIndex = (limit / blockSize) * blockSize + blockSize - 1;164if (endIndex >= b.length) {165throw new ArrayIndexOutOfBoundsException(endIndex);166}167}168169// reset this object. See JCA doc.170protected final void engineReset() {171if (bytesProcessed == 0) {172// already reset, ignore173return;174}175implReset();176bufOfs = 0;177bytesProcessed = 0;178Arrays.fill(buffer, (byte) 0x00);179}180181// return the digest. See JCA doc.182protected final byte[] engineDigest() {183byte[] b = new byte[digestLength];184try {185engineDigest(b, 0, b.length);186} catch (DigestException e) {187throw (ProviderException)188new ProviderException("Internal error").initCause(e);189}190return b;191}192193// return the digest in the specified array. See JCA doc.194protected final int engineDigest(byte[] out, int ofs, int len)195throws DigestException {196if (len < digestLength) {197throw new DigestException("Length must be at least "198+ digestLength + " for " + algorithm + "digests");199}200if ((ofs < 0) || (len < 0) || (ofs > out.length - len)) {201throw new DigestException("Buffer too short to store digest");202}203if (bytesProcessed < 0) {204engineReset();205}206implDigest(out, ofs);207bytesProcessed = -1;208return digestLength;209}210211/**212* Core compression function. Processes blockSize bytes at a time213* and updates the state of this object.214*/215abstract void implCompress(byte[] b, int ofs);216217/**218* Return the digest. Subclasses do not need to reset() themselves,219* DigestBase calls implReset() when necessary.220*/221abstract void implDigest(byte[] out, int ofs);222223/**224* Reset subclass specific state to their initial values. DigestBase225* calls this method when necessary.226*/227abstract void implReset();228229public Object clone() throws CloneNotSupportedException {230DigestBase copy = (DigestBase) super.clone();231copy.buffer = copy.buffer.clone();232return copy;233}234235// padding used for the MD5, and SHA-* message digests236static final byte[] padding;237238static {239// we need 128 byte padding for SHA-384/512240// and an additional 8 bytes for the high 8 bytes of the 16241// byte bit counter in SHA-384/512242padding = new byte[136];243padding[0] = (byte)0x80;244}245}246247248