Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CRSACipher.java
68250 views
1
/*
2
* Copyright (c) 2005, 2021, 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.mscapi;
27
28
import java.math.BigInteger;
29
import java.security.*;
30
import java.security.Key;
31
import java.security.interfaces.*;
32
import java.security.spec.*;
33
34
import javax.crypto.*;
35
import javax.crypto.spec.*;
36
37
import sun.security.rsa.RSAKeyFactory;
38
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
39
import sun.security.util.KeyUtil;
40
41
/**
42
* Cipher implementation using the Microsoft Crypto API.
43
* Supports RSA en/decryption and signing/verifying using PKCS#1 v1.5 padding.
44
*
45
* Objects should be instantiated by calling Cipher.getInstance() using the
46
* following algorithm name:
47
*
48
* . "RSA/ECB/PKCS1Padding" (or "RSA") for PKCS#1 padding. The mode (blocktype)
49
* is selected based on the en/decryption mode and public/private key used.
50
*
51
* We only do one RSA operation per doFinal() call. If the application passes
52
* more data via calls to update() or doFinal(), we throw an
53
* IllegalBlockSizeException when doFinal() is called (see JCE API spec).
54
* Bulk encryption using RSA does not make sense and is not standardized.
55
*
56
* Note: RSA keys should be at least 512 bits long
57
*
58
* @since 1.6
59
* @author Andreas Sterbenz
60
* @author Vincent Ryan
61
*/
62
public final class CRSACipher extends CipherSpi {
63
64
// constant for an empty byte array
65
private static final byte[] B0 = new byte[0];
66
67
// mode constant for public key encryption
68
private static final int MODE_ENCRYPT = 1;
69
// mode constant for private key decryption
70
private static final int MODE_DECRYPT = 2;
71
// mode constant for private key encryption (signing)
72
private static final int MODE_SIGN = 3;
73
// mode constant for public key decryption (verifying)
74
private static final int MODE_VERIFY = 4;
75
76
// constant for PKCS#1 v1.5 RSA
77
private static final String PAD_PKCS1 = "PKCS1Padding";
78
private static final int PAD_PKCS1_LENGTH = 11;
79
80
// current mode, one of MODE_* above. Set when init() is called
81
private int mode;
82
83
// active padding type, one of PAD_* above. Set by setPadding()
84
private String paddingType;
85
private int paddingLength = 0;
86
87
// buffer for the data
88
private byte[] buffer;
89
// offset into the buffer (number of bytes buffered)
90
private int bufOfs;
91
92
// size of the output (the length of the key).
93
private int outputSize;
94
95
// the public key, if we were initialized using a public key
96
private CKey publicKey;
97
98
// the private key, if we were initialized using a private key
99
private CKey privateKey;
100
101
// cipher parameter for TLS RSA premaster secret
102
private AlgorithmParameterSpec spec = null;
103
104
// the source of randomness
105
private SecureRandom random;
106
107
public CRSACipher() {
108
paddingType = PAD_PKCS1;
109
}
110
111
// modes do not make sense for RSA, but allow ECB
112
// see JCE spec
113
protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
114
if (mode.equalsIgnoreCase("ECB") == false) {
115
throw new NoSuchAlgorithmException("Unsupported mode " + mode);
116
}
117
}
118
119
// set the padding type
120
// see JCE spec
121
protected void engineSetPadding(String paddingName)
122
throws NoSuchPaddingException {
123
if (paddingName.equalsIgnoreCase(PAD_PKCS1)) {
124
paddingType = PAD_PKCS1;
125
} else {
126
throw new NoSuchPaddingException
127
("Padding " + paddingName + " not supported");
128
}
129
}
130
131
// return 0 as block size, we are not a block cipher
132
// see JCE spec
133
protected int engineGetBlockSize() {
134
return 0;
135
}
136
137
// return the output size
138
// see JCE spec
139
protected int engineGetOutputSize(int inputLen) {
140
return outputSize;
141
}
142
143
// no iv, return null
144
// see JCE spec
145
protected byte[] engineGetIV() {
146
return null;
147
}
148
149
// no parameters, return null
150
// see JCE spec
151
protected AlgorithmParameters engineGetParameters() {
152
return null;
153
}
154
155
// see JCE spec
156
protected void engineInit(int opmode, Key key, SecureRandom random)
157
throws InvalidKeyException {
158
init(opmode, key);
159
}
160
161
// see JCE spec
162
@SuppressWarnings("deprecation")
163
protected void engineInit(int opmode, Key key,
164
AlgorithmParameterSpec params, SecureRandom random)
165
throws InvalidKeyException, InvalidAlgorithmParameterException {
166
167
if (params != null) {
168
if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
169
throw new InvalidAlgorithmParameterException(
170
"Parameters not supported");
171
}
172
spec = params;
173
this.random = random; // for TLS RSA premaster secret
174
}
175
init(opmode, key);
176
}
177
178
// see JCE spec
179
protected void engineInit(int opmode, Key key,
180
AlgorithmParameters params, SecureRandom random)
181
throws InvalidKeyException, InvalidAlgorithmParameterException {
182
183
if (params != null) {
184
throw new InvalidAlgorithmParameterException
185
("Parameters not supported");
186
}
187
init(opmode, key);
188
}
189
190
// initialize this cipher
191
private void init(int opmode, Key key) throws InvalidKeyException {
192
193
boolean encrypt;
194
195
switch (opmode) {
196
case Cipher.ENCRYPT_MODE:
197
case Cipher.WRAP_MODE:
198
paddingLength = PAD_PKCS1_LENGTH;
199
encrypt = true;
200
break;
201
case Cipher.DECRYPT_MODE:
202
case Cipher.UNWRAP_MODE:
203
paddingLength = 0; // reset
204
encrypt = false;
205
break;
206
default:
207
// should never happen; checked by Cipher.init()
208
throw new AssertionError("Unknown mode: " + opmode);
209
}
210
211
if (!(key instanceof CKey)) {
212
if (key instanceof java.security.interfaces.RSAPublicKey) {
213
java.security.interfaces.RSAPublicKey rsaKey =
214
(java.security.interfaces.RSAPublicKey) key;
215
216
// Convert key to MSCAPI format
217
218
BigInteger modulus = rsaKey.getModulus();
219
BigInteger exponent = rsaKey.getPublicExponent();
220
221
// Check against the local and global values to make sure
222
// the sizes are ok. Round up to the nearest byte.
223
RSAKeyFactory.checkKeyLengths(((modulus.bitLength() + 7) & ~7),
224
exponent, -1, CKeyPairGenerator.RSA.KEY_SIZE_MAX);
225
226
byte[] modulusBytes = modulus.toByteArray();
227
byte[] exponentBytes = exponent.toByteArray();
228
229
// Adjust key length due to sign bit
230
int keyBitLength = (modulusBytes[0] == 0)
231
? (modulusBytes.length - 1) * 8
232
: modulusBytes.length * 8;
233
234
byte[] keyBlob = CSignature.RSA.generatePublicKeyBlob(
235
keyBitLength, modulusBytes, exponentBytes);
236
237
try {
238
key = CSignature.importPublicKey("RSA", keyBlob, keyBitLength);
239
240
} catch (KeyStoreException e) {
241
throw new InvalidKeyException(e);
242
}
243
244
} else {
245
throw new InvalidKeyException("Unsupported key type: " + key);
246
}
247
}
248
249
if (key instanceof PublicKey) {
250
mode = encrypt ? MODE_ENCRYPT : MODE_VERIFY;
251
publicKey = (CKey)key;
252
privateKey = null;
253
outputSize = publicKey.length() / 8;
254
} else if (key instanceof PrivateKey) {
255
mode = encrypt ? MODE_SIGN : MODE_DECRYPT;
256
privateKey = (CKey)key;
257
publicKey = null;
258
outputSize = privateKey.length() / 8;
259
} else {
260
throw new InvalidKeyException("Unknown key type: " + key);
261
}
262
263
bufOfs = 0;
264
buffer = new byte[outputSize];
265
}
266
267
// internal update method
268
private void update(byte[] in, int inOfs, int inLen) {
269
if ((inLen == 0) || (in == null)) {
270
return;
271
}
272
if (bufOfs + inLen > (buffer.length - paddingLength)) {
273
bufOfs = buffer.length + 1;
274
return;
275
}
276
System.arraycopy(in, inOfs, buffer, bufOfs, inLen);
277
bufOfs += inLen;
278
}
279
280
// internal doFinal() method. Here we perform the actual RSA operation
281
private byte[] doFinal() throws BadPaddingException,
282
IllegalBlockSizeException {
283
if (bufOfs > buffer.length) {
284
throw new IllegalBlockSizeException("Data must not be longer "
285
+ "than " + (buffer.length - paddingLength) + " bytes");
286
}
287
288
try {
289
byte[] data = buffer;
290
switch (mode) {
291
case MODE_SIGN:
292
return encryptDecrypt(data, bufOfs,
293
privateKey.getHCryptKey(), true);
294
295
case MODE_VERIFY:
296
return encryptDecrypt(data, bufOfs,
297
publicKey.getHCryptKey(), false);
298
299
case MODE_ENCRYPT:
300
return encryptDecrypt(data, bufOfs,
301
publicKey.getHCryptKey(), true);
302
303
case MODE_DECRYPT:
304
return encryptDecrypt(data, bufOfs,
305
privateKey.getHCryptKey(), false);
306
307
default:
308
throw new AssertionError("Internal error");
309
}
310
311
} catch (KeyException e) {
312
throw new ProviderException(e);
313
314
} finally {
315
bufOfs = 0;
316
}
317
}
318
319
// see JCE spec
320
protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
321
update(in, inOfs, inLen);
322
return B0;
323
}
324
325
// see JCE spec
326
protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
327
int outOfs) {
328
update(in, inOfs, inLen);
329
return 0;
330
}
331
332
// see JCE spec
333
protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
334
throws BadPaddingException, IllegalBlockSizeException {
335
update(in, inOfs, inLen);
336
return doFinal();
337
}
338
339
// see JCE spec
340
protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
341
int outOfs) throws ShortBufferException, BadPaddingException,
342
IllegalBlockSizeException {
343
if (outputSize > out.length - outOfs) {
344
throw new ShortBufferException
345
("Need " + outputSize + " bytes for output");
346
}
347
update(in, inOfs, inLen);
348
byte[] result = doFinal();
349
int n = result.length;
350
System.arraycopy(result, 0, out, outOfs, n);
351
return n;
352
}
353
354
// see JCE spec
355
protected byte[] engineWrap(Key key) throws InvalidKeyException,
356
IllegalBlockSizeException {
357
byte[] encoded = key.getEncoded(); // TODO - unextractable key
358
if ((encoded == null) || (encoded.length == 0)) {
359
throw new InvalidKeyException("Could not obtain encoded key");
360
}
361
if (encoded.length > buffer.length) {
362
throw new InvalidKeyException("Key is too long for wrapping");
363
}
364
update(encoded, 0, encoded.length);
365
try {
366
return doFinal();
367
} catch (BadPaddingException e) {
368
// should not occur
369
throw new InvalidKeyException("Wrapping failed", e);
370
}
371
}
372
373
// see JCE spec
374
@SuppressWarnings("deprecation")
375
protected java.security.Key engineUnwrap(byte[] wrappedKey,
376
String algorithm,
377
int type) throws InvalidKeyException, NoSuchAlgorithmException {
378
379
if (wrappedKey.length > buffer.length) {
380
throw new InvalidKeyException("Key is too long for unwrapping");
381
}
382
383
boolean isTlsRsaPremasterSecret =
384
algorithm.equals("TlsRsaPremasterSecret");
385
Exception failover = null;
386
byte[] encoded = null;
387
388
update(wrappedKey, 0, wrappedKey.length);
389
try {
390
encoded = doFinal();
391
} catch (BadPaddingException e) {
392
if (isTlsRsaPremasterSecret) {
393
failover = e;
394
} else {
395
throw new InvalidKeyException("Unwrapping failed", e);
396
}
397
} catch (IllegalBlockSizeException e) {
398
// should not occur, handled with length check above
399
throw new InvalidKeyException("Unwrapping failed", e);
400
}
401
402
if (isTlsRsaPremasterSecret) {
403
if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
404
throw new IllegalStateException(
405
"No TlsRsaPremasterSecretParameterSpec specified");
406
}
407
408
// polish the TLS premaster secret
409
encoded = KeyUtil.checkTlsPreMasterSecretKey(
410
((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(),
411
((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(),
412
random, encoded, (failover != null));
413
}
414
415
return constructKey(encoded, algorithm, type);
416
}
417
418
// see JCE spec
419
protected int engineGetKeySize(Key key) throws InvalidKeyException {
420
421
if (key instanceof CKey) {
422
return ((CKey) key).length();
423
424
} else if (key instanceof RSAKey) {
425
return ((RSAKey) key).getModulus().bitLength();
426
427
} else {
428
throw new InvalidKeyException("Unsupported key type: " + key);
429
}
430
}
431
432
// Construct an X.509 encoded public key.
433
private static PublicKey constructPublicKey(byte[] encodedKey,
434
String encodedKeyAlgorithm)
435
throws InvalidKeyException, NoSuchAlgorithmException {
436
437
try {
438
KeyFactory keyFactory = KeyFactory.getInstance(encodedKeyAlgorithm);
439
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
440
441
return keyFactory.generatePublic(keySpec);
442
443
} catch (NoSuchAlgorithmException nsae) {
444
throw new NoSuchAlgorithmException("No installed provider " +
445
"supports the " + encodedKeyAlgorithm + " algorithm", nsae);
446
447
} catch (InvalidKeySpecException ike) {
448
throw new InvalidKeyException("Cannot construct public key", ike);
449
}
450
}
451
452
// Construct a PKCS #8 encoded private key.
453
private static PrivateKey constructPrivateKey(byte[] encodedKey,
454
String encodedKeyAlgorithm)
455
throws InvalidKeyException, NoSuchAlgorithmException {
456
457
try {
458
KeyFactory keyFactory = KeyFactory.getInstance(encodedKeyAlgorithm);
459
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
460
461
return keyFactory.generatePrivate(keySpec);
462
463
} catch (NoSuchAlgorithmException nsae) {
464
throw new NoSuchAlgorithmException("No installed provider " +
465
"supports the " + encodedKeyAlgorithm + " algorithm", nsae);
466
467
} catch (InvalidKeySpecException ike) {
468
throw new InvalidKeyException("Cannot construct private key", ike);
469
}
470
}
471
472
// Construct an encoded secret key.
473
private static SecretKey constructSecretKey(byte[] encodedKey,
474
String encodedKeyAlgorithm) {
475
476
return new SecretKeySpec(encodedKey, encodedKeyAlgorithm);
477
}
478
479
private static Key constructKey(byte[] encodedKey,
480
String encodedKeyAlgorithm,
481
int keyType) throws InvalidKeyException, NoSuchAlgorithmException {
482
483
switch (keyType) {
484
case Cipher.PUBLIC_KEY:
485
return constructPublicKey(encodedKey, encodedKeyAlgorithm);
486
case Cipher.PRIVATE_KEY:
487
return constructPrivateKey(encodedKey, encodedKeyAlgorithm);
488
case Cipher.SECRET_KEY:
489
return constructSecretKey(encodedKey, encodedKeyAlgorithm);
490
default:
491
throw new InvalidKeyException("Unknown key type " + keyType);
492
}
493
}
494
495
/*
496
* Encrypt/decrypt a data buffer using Microsoft Crypto API with HCRYPTKEY.
497
* It expects and returns ciphertext data in big-endian form.
498
*/
499
private native static byte[] encryptDecrypt(byte[] data, int dataSize,
500
long hCryptKey, boolean doEncrypt) throws KeyException;
501
502
}
503
504