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