blob: 341390623fa9f68e899bb533eb99466b4794ebfd [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.security.provider;
27
28import java.security.MessageDigestSpi;
29import java.security.DigestException;
30import java.security.ProviderException;
31
32/**
33 * Common base message digest implementation for the Sun provider.
34 * It implements all the JCA methods as suitable for a Java message digest
35 * implementation of an algorithm based on a compression function (as all
36 * commonly used algorithms are). The individual digest subclasses only need to
37 * implement the following methods:
38 *
39 * . abstract void implCompress(byte[] b, int ofs);
40 * . abstract void implDigest(byte[] out, int ofs);
41 * . abstract void implReset();
42 * . public abstract Object clone();
43 *
44 * See the inline documentation for details.
45 *
46 * @since 1.5
47 * @author Andreas Sterbenz
48 */
49abstract class DigestBase extends MessageDigestSpi implements Cloneable {
50
51 // one element byte array, temporary storage for update(byte)
52 private byte[] oneByte;
53
54 // algorithm name to use in the exception message
55 private final String algorithm;
56 // length of the message digest in bytes
57 private final int digestLength;
58
59 // size of the input to the compression function in bytes
60 private final int blockSize;
61 // buffer to store partial blocks, blockSize bytes large
62 // Subclasses should not access this array directly except possibly in their
63 // implDigest() method. See MD5.java as an example.
64 final byte[] buffer;
65 // offset into buffer
66 private int bufOfs;
67
68 // number of bytes processed so far. subclasses should not modify
69 // this value.
70 // also used as a flag to indicate reset status
71 // -1: need to call engineReset() before next call to update()
72 // 0: is already reset
73 long bytesProcessed;
74
75 /**
76 * Main constructor.
77 */
78 DigestBase(String algorithm, int digestLength, int blockSize) {
79 super();
80 this.algorithm = algorithm;
81 this.digestLength = digestLength;
82 this.blockSize = blockSize;
83 buffer = new byte[blockSize];
84 }
85
86 /**
87 * Constructor for cloning. Replicates common data.
88 */
89 DigestBase(DigestBase base) {
90 this.algorithm = base.algorithm;
91 this.digestLength = base.digestLength;
92 this.blockSize = base.blockSize;
93 this.buffer = base.buffer.clone();
94 this.bufOfs = base.bufOfs;
95 this.bytesProcessed = base.bytesProcessed;
96 }
97
98 // return digest length. See JCA doc.
99 protected final int engineGetDigestLength() {
100 return digestLength;
101 }
102
103 // single byte update. See JCA doc.
104 protected final void engineUpdate(byte b) {
105 if (oneByte == null) {
106 oneByte = new byte[1];
107 }
108 oneByte[0] = b;
109 engineUpdate(oneByte, 0, 1);
110 }
111
112 // array update. See JCA doc.
113 protected final void engineUpdate(byte[] b, int ofs, int len) {
114 if (len == 0) {
115 return;
116 }
117 if ((ofs < 0) || (len < 0) || (ofs > b.length - len)) {
118 throw new ArrayIndexOutOfBoundsException();
119 }
120 if (bytesProcessed < 0) {
121 engineReset();
122 }
123 bytesProcessed += len;
124 // if buffer is not empty, we need to fill it before proceeding
125 if (bufOfs != 0) {
126 int n = Math.min(len, blockSize - bufOfs);
127 System.arraycopy(b, ofs, buffer, bufOfs, n);
128 bufOfs += n;
129 ofs += n;
130 len -= n;
131 if (bufOfs >= blockSize) {
132 // compress completed block now
133 implCompress(buffer, 0);
134 bufOfs = 0;
135 }
136 }
137 // compress complete blocks
138 while (len >= blockSize) {
139 implCompress(b, ofs);
140 len -= blockSize;
141 ofs += blockSize;
142 }
143 // copy remainder to buffer
144 if (len > 0) {
145 System.arraycopy(b, ofs, buffer, 0, len);
146 bufOfs = len;
147 }
148 }
149
150 // reset this object. See JCA doc.
151 protected final void engineReset() {
152 if (bytesProcessed == 0) {
153 // already reset, ignore
154 return;
155 }
156 implReset();
157 bufOfs = 0;
158 bytesProcessed = 0;
159 }
160
161 // return the digest. See JCA doc.
162 protected final byte[] engineDigest() {
163 byte[] b = new byte[digestLength];
164 try {
165 engineDigest(b, 0, b.length);
166 } catch (DigestException e) {
167 throw (ProviderException)
168 new ProviderException("Internal error").initCause(e);
169 }
170 return b;
171 }
172
173 // return the digest in the specified array. See JCA doc.
174 protected final int engineDigest(byte[] out, int ofs, int len)
175 throws DigestException {
176 if (len < digestLength) {
177 throw new DigestException("Length must be at least "
178 + digestLength + " for " + algorithm + "digests");
179 }
180 if ((ofs < 0) || (len < 0) || (ofs > out.length - len)) {
181 throw new DigestException("Buffer too short to store digest");
182 }
183 if (bytesProcessed < 0) {
184 engineReset();
185 }
186 implDigest(out, ofs);
187 bytesProcessed = -1;
188 return digestLength;
189 }
190
191 /**
192 * Core compression function. Processes blockSize bytes at a time
193 * and updates the state of this object.
194 */
195 abstract void implCompress(byte[] b, int ofs);
196
197 /**
198 * Return the digest. Subclasses do not need to reset() themselves,
199 * DigestBase calls implReset() when necessary.
200 */
201 abstract void implDigest(byte[] out, int ofs);
202
203 /**
204 * Reset subclass specific state to their initial values. DigestBase
205 * calls this method when necessary.
206 */
207 abstract void implReset();
208
209 /**
210 * Clone this digest. Should be implemented as "return new MyDigest(this)".
211 * That constructor should first call "super(baseDigest)" and then copy
212 * subclass specific data.
213 */
214 public abstract Object clone();
215
216 // padding used for the MD5, and SHA-* message digests
217 static final byte[] padding;
218
219 static {
220 // we need 128 byte padding for SHA-384/512
221 // and an additional 8 bytes for the high 8 bytes of the 16
222 // byte bit counter in SHA-384/512
223 padding = new byte[136];
224 padding[0] = (byte)0x80;
225 }
226
227}