Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/pkcs11/P11Digest.java
38919 views
1
/*
2
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.security.pkcs11;
27
28
import java.util.*;
29
import java.nio.ByteBuffer;
30
31
import java.security.*;
32
33
import javax.crypto.SecretKey;
34
35
import sun.nio.ch.DirectBuffer;
36
37
import sun.security.util.MessageDigestSpi2;
38
39
import sun.security.pkcs11.wrapper.*;
40
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
41
42
/**
43
* MessageDigest implementation class. This class currently supports
44
* MD2, MD5, SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512.
45
*
46
* Note that many digest operations are on fairly small amounts of data
47
* (less than 100 bytes total). For example, the 2nd hashing in HMAC or
48
* the PRF in TLS. In order to speed those up, we use some buffering to
49
* minimize number of the Java->native transitions.
50
*
51
* @author Andreas Sterbenz
52
* @since 1.5
53
*/
54
final class P11Digest extends MessageDigestSpi implements Cloneable,
55
MessageDigestSpi2 {
56
57
/* fields initialized, no session acquired */
58
private final static int S_BLANK = 1;
59
60
/* data in buffer, session acquired, but digest not initialized */
61
private final static int S_BUFFERED = 2;
62
63
/* session initialized for digesting */
64
private final static int S_INIT = 3;
65
66
private final static int BUFFER_SIZE = 96;
67
68
// token instance
69
private final Token token;
70
71
// algorithm name
72
private final String algorithm;
73
74
// mechanism id object
75
private final CK_MECHANISM mechanism;
76
77
// length of the digest in bytes
78
private final int digestLength;
79
80
// associated session, if any
81
private Session session;
82
83
// current state, one of S_* above
84
private int state;
85
86
// buffer to reduce number of JNI calls
87
private byte[] buffer;
88
89
// offset into the buffer
90
private int bufOfs;
91
92
P11Digest(Token token, String algorithm, long mechanism) {
93
super();
94
this.token = token;
95
this.algorithm = algorithm;
96
this.mechanism = new CK_MECHANISM(mechanism);
97
switch ((int)mechanism) {
98
case (int)CKM_MD2:
99
case (int)CKM_MD5:
100
digestLength = 16;
101
break;
102
case (int)CKM_SHA_1:
103
digestLength = 20;
104
break;
105
case (int)CKM_SHA224:
106
digestLength = 28;
107
break;
108
case (int)CKM_SHA256:
109
digestLength = 32;
110
break;
111
case (int)CKM_SHA384:
112
digestLength = 48;
113
break;
114
case (int)CKM_SHA512:
115
digestLength = 64;
116
break;
117
default:
118
throw new ProviderException("Unknown mechanism: " + mechanism);
119
}
120
buffer = new byte[BUFFER_SIZE];
121
state = S_BLANK;
122
}
123
124
// see JCA spec
125
protected int engineGetDigestLength() {
126
return digestLength;
127
}
128
129
private void fetchSession() {
130
token.ensureValid();
131
if (state == S_BLANK) {
132
try {
133
session = token.getOpSession();
134
state = S_BUFFERED;
135
} catch (PKCS11Exception e) {
136
throw new ProviderException("No more session available", e);
137
}
138
}
139
}
140
141
// see JCA spec
142
protected void engineReset() {
143
token.ensureValid();
144
145
if (session != null) {
146
if (state == S_INIT && token.explicitCancel == true
147
&& session.hasObjects() == false) {
148
session = token.killSession(session);
149
} else {
150
session = token.releaseSession(session);
151
}
152
}
153
state = S_BLANK;
154
bufOfs = 0;
155
}
156
157
// see JCA spec
158
protected byte[] engineDigest() {
159
try {
160
byte[] digest = new byte[digestLength];
161
int n = engineDigest(digest, 0, digestLength);
162
return digest;
163
} catch (DigestException e) {
164
throw new ProviderException("internal error", e);
165
}
166
}
167
168
// see JCA spec
169
protected int engineDigest(byte[] digest, int ofs, int len)
170
throws DigestException {
171
if (len < digestLength) {
172
throw new DigestException("Length must be at least " +
173
digestLength);
174
}
175
176
fetchSession();
177
try {
178
int n;
179
if (state == S_BUFFERED) {
180
n = token.p11.C_DigestSingle(session.id(), mechanism, buffer, 0,
181
bufOfs, digest, ofs, len);
182
bufOfs = 0;
183
} else {
184
if (bufOfs != 0) {
185
token.p11.C_DigestUpdate(session.id(), 0, buffer, 0,
186
bufOfs);
187
bufOfs = 0;
188
}
189
n = token.p11.C_DigestFinal(session.id(), digest, ofs, len);
190
}
191
if (n != digestLength) {
192
throw new ProviderException("internal digest length error");
193
}
194
return n;
195
} catch (PKCS11Exception e) {
196
throw new ProviderException("digest() failed", e);
197
} finally {
198
engineReset();
199
}
200
}
201
202
// see JCA spec
203
protected void engineUpdate(byte in) {
204
byte[] temp = { in };
205
engineUpdate(temp, 0, 1);
206
}
207
208
// see JCA spec
209
protected void engineUpdate(byte[] in, int ofs, int len) {
210
if (len <= 0) {
211
return;
212
}
213
214
fetchSession();
215
try {
216
if (state == S_BUFFERED) {
217
token.p11.C_DigestInit(session.id(), mechanism);
218
state = S_INIT;
219
}
220
if ((bufOfs != 0) && (bufOfs + len > buffer.length)) {
221
// process the buffered data
222
token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
223
bufOfs = 0;
224
}
225
if (bufOfs + len > buffer.length) {
226
// process the new data
227
token.p11.C_DigestUpdate(session.id(), 0, in, ofs, len);
228
} else {
229
// buffer the new data
230
System.arraycopy(in, ofs, buffer, bufOfs, len);
231
bufOfs += len;
232
}
233
} catch (PKCS11Exception e) {
234
engineReset();
235
throw new ProviderException("update() failed", e);
236
}
237
}
238
239
// Called by SunJSSE via reflection during the SSL 3.0 handshake if
240
// the master secret is sensitive.
241
// Note: Change to protected after this method is moved from
242
// sun.security.util.MessageSpi2 interface to
243
// java.security.MessageDigestSpi class
244
public void engineUpdate(SecretKey key) throws InvalidKeyException {
245
// SunJSSE calls this method only if the key does not have a RAW
246
// encoding, i.e. if it is sensitive. Therefore, no point in calling
247
// SecretKeyFactory to try to convert it. Just verify it ourselves.
248
if (key instanceof P11Key == false) {
249
throw new InvalidKeyException("Not a P11Key: " + key);
250
}
251
P11Key p11Key = (P11Key)key;
252
if (p11Key.token != token) {
253
throw new InvalidKeyException("Not a P11Key of this provider: " +
254
key);
255
}
256
257
fetchSession();
258
long p11KeyID = p11Key.getKeyID();
259
try {
260
if (state == S_BUFFERED) {
261
token.p11.C_DigestInit(session.id(), mechanism);
262
state = S_INIT;
263
}
264
265
if (bufOfs != 0) {
266
token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
267
bufOfs = 0;
268
}
269
token.p11.C_DigestKey(session.id(), p11KeyID);
270
} catch (PKCS11Exception e) {
271
engineReset();
272
throw new ProviderException("update(SecretKey) failed", e);
273
} finally {
274
p11Key.releaseKeyID();
275
}
276
}
277
278
// see JCA spec
279
protected void engineUpdate(ByteBuffer byteBuffer) {
280
int len = byteBuffer.remaining();
281
if (len <= 0) {
282
return;
283
}
284
285
if (byteBuffer instanceof DirectBuffer == false) {
286
super.engineUpdate(byteBuffer);
287
return;
288
}
289
290
fetchSession();
291
long addr = ((DirectBuffer)byteBuffer).address();
292
int ofs = byteBuffer.position();
293
try {
294
if (state == S_BUFFERED) {
295
token.p11.C_DigestInit(session.id(), mechanism);
296
state = S_INIT;
297
}
298
if (bufOfs != 0) {
299
token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
300
bufOfs = 0;
301
}
302
token.p11.C_DigestUpdate(session.id(), addr + ofs, null, 0, len);
303
byteBuffer.position(ofs + len);
304
} catch (PKCS11Exception e) {
305
engineReset();
306
throw new ProviderException("update() failed", e);
307
}
308
}
309
310
public Object clone() throws CloneNotSupportedException {
311
P11Digest copy = (P11Digest) super.clone();
312
copy.buffer = buffer.clone();
313
try {
314
if (session != null) {
315
copy.session = copy.token.getOpSession();
316
}
317
if (state == S_INIT) {
318
byte[] stateValues =
319
token.p11.C_GetOperationState(session.id());
320
token.p11.C_SetOperationState(copy.session.id(),
321
stateValues, 0, 0);
322
}
323
} catch (PKCS11Exception e) {
324
throw (CloneNotSupportedException)
325
(new CloneNotSupportedException(algorithm).initCause(e));
326
}
327
return copy;
328
}
329
}
330
331