Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/classes/sun/security/mscapi/CRSACipher.java
32288 views
1
/*
2
* Copyright (c) 2005, 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.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 final static byte[] B0 = new byte[0];
66
67
// mode constant for public key encryption
68
private final static int MODE_ENCRYPT = 1;
69
// mode constant for private key decryption
70
private final static int MODE_DECRYPT = 2;
71
// mode constant for private key encryption (signing)
72
private final static int MODE_SIGN = 3;
73
// mode constant for public key decryption (verifying)
74
private final static int MODE_VERIFY = 4;
75
76
// constant for PKCS#1 v1.5 RSA
77
private final static String PAD_PKCS1 = "PKCS1Padding";
78
private final static 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
throw new InvalidKeyException("Unknown mode: " + opmode);
208
}
209
210
if (!(key instanceof CKey)) {
211
if (key instanceof java.security.interfaces.RSAPublicKey) {
212
java.security.interfaces.RSAPublicKey rsaKey =
213
(java.security.interfaces.RSAPublicKey) key;
214
215
// Convert key to MSCAPI format
216
217
BigInteger modulus = rsaKey.getModulus();
218
BigInteger exponent = rsaKey.getPublicExponent();
219
220
// Check against the local and global values to make sure
221
// the sizes are ok. Round up to the nearest byte.
222
RSAKeyFactory.checkKeyLengths(((modulus.bitLength() + 7) & ~7),
223
exponent, -1, CKeyPairGenerator.RSA.KEY_SIZE_MAX);
224
225
byte[] modulusBytes = modulus.toByteArray();
226
byte[] exponentBytes = exponent.toByteArray();
227
228
// Adjust key length due to sign bit
229
int keyBitLength = (modulusBytes[0] == 0)
230
? (modulusBytes.length - 1) * 8
231
: modulusBytes.length * 8;
232
233
byte[] keyBlob = CSignature.RSA.generatePublicKeyBlob(
234
keyBitLength, modulusBytes, exponentBytes);
235
236
try {
237
key = CSignature.importPublicKey("RSA", keyBlob, keyBitLength);
238
239
} catch (KeyStoreException e) {
240
throw new InvalidKeyException(e);
241
}
242
243
} else {
244
throw new InvalidKeyException("Unsupported key type: " + key);
245
}
246
}
247
248
if (key instanceof PublicKey) {
249
mode = encrypt ? MODE_ENCRYPT : MODE_VERIFY;
250
publicKey = (CKey)key;
251
privateKey = null;
252
outputSize = publicKey.length() / 8;
253
} else if (key instanceof PrivateKey) {
254
mode = encrypt ? MODE_SIGN : MODE_DECRYPT;
255
privateKey = (CKey)key;
256
publicKey = null;
257
outputSize = privateKey.length() / 8;
258
} else {
259
throw new InvalidKeyException("Unknown key type: " + key);
260
}
261
262
bufOfs = 0;
263
buffer = new byte[outputSize];
264
}
265
266
// internal update method
267
private void update(byte[] in, int inOfs, int inLen) {
268
if ((inLen == 0) || (in == null)) {
269
return;
270
}
271
if (bufOfs + inLen > (buffer.length - paddingLength)) {
272
bufOfs = buffer.length + 1;
273
return;
274
}
275
System.arraycopy(in, inOfs, buffer, bufOfs, inLen);
276
bufOfs += inLen;
277
}
278
279
// internal doFinal() method. Here we perform the actual RSA operation
280
private byte[] doFinal() throws BadPaddingException,
281
IllegalBlockSizeException {
282
if (bufOfs > buffer.length) {
283
throw new IllegalBlockSizeException("Data must not be longer "
284
+ "than " + (buffer.length - paddingLength) + " bytes");
285
}
286
287
try {
288
byte[] data = buffer;
289
switch (mode) {
290
case MODE_SIGN:
291
return encryptDecrypt(data, bufOfs,
292
privateKey.getHCryptKey(), true);
293
294
case MODE_VERIFY:
295
return encryptDecrypt(data, bufOfs,
296
publicKey.getHCryptKey(), false);
297
298
case MODE_ENCRYPT:
299
return encryptDecrypt(data, bufOfs,
300
publicKey.getHCryptKey(), true);
301
302
case MODE_DECRYPT:
303
return encryptDecrypt(data, bufOfs,
304
privateKey.getHCryptKey(), false);
305
306
default:
307
throw new AssertionError("Internal error");
308
}
309
310
} catch (KeyException e) {
311
throw new ProviderException(e);
312
313
} finally {
314
bufOfs = 0;
315
}
316
}
317
318
// see JCE spec
319
protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
320
update(in, inOfs, inLen);
321
return B0;
322
}
323
324
// see JCE spec
325
protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
326
int outOfs) {
327
update(in, inOfs, inLen);
328
return 0;
329
}
330
331
// see JCE spec
332
protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
333
throws BadPaddingException, IllegalBlockSizeException {
334
update(in, inOfs, inLen);
335
return doFinal();
336
}
337
338
// see JCE spec
339
protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
340
int outOfs) throws ShortBufferException, BadPaddingException,
341
IllegalBlockSizeException {
342
if (outputSize > out.length - outOfs) {
343
throw new ShortBufferException
344
("Need " + outputSize + " bytes for output");
345
}
346
update(in, inOfs, inLen);
347
byte[] result = doFinal();
348
int n = result.length;
349
System.arraycopy(result, 0, out, outOfs, n);
350
return n;
351
}
352
353
// see JCE spec
354
protected byte[] engineWrap(Key key) throws InvalidKeyException,
355
IllegalBlockSizeException {
356
byte[] encoded = key.getEncoded(); // TODO - unextractable key
357
if ((encoded == null) || (encoded.length == 0)) {
358
throw new InvalidKeyException("Could not obtain encoded key");
359
}
360
if (encoded.length > buffer.length) {
361
throw new InvalidKeyException("Key is too long for wrapping");
362
}
363
update(encoded, 0, encoded.length);
364
try {
365
return doFinal();
366
} catch (BadPaddingException e) {
367
// should not occur
368
throw new InvalidKeyException("Wrapping failed", e);
369
}
370
}
371
372
// see JCE spec
373
@SuppressWarnings("deprecation")
374
protected java.security.Key engineUnwrap(byte[] wrappedKey,
375
String algorithm,
376
int type) throws InvalidKeyException, NoSuchAlgorithmException {
377
378
if (wrappedKey.length > buffer.length) {
379
throw new InvalidKeyException("Key is too long for unwrapping");
380
}
381
382
boolean isTlsRsaPremasterSecret =
383
algorithm.equals("TlsRsaPremasterSecret");
384
Exception failover = null;
385
byte[] encoded = null;
386
387
update(wrappedKey, 0, wrappedKey.length);
388
try {
389
encoded = doFinal();
390
} catch (BadPaddingException e) {
391
if (isTlsRsaPremasterSecret) {
392
failover = e;
393
} else {
394
throw new InvalidKeyException("Unwrapping failed", e);
395
}
396
} catch (IllegalBlockSizeException e) {
397
// should not occur, handled with length check above
398
throw new InvalidKeyException("Unwrapping failed", e);
399
}
400
401
if (isTlsRsaPremasterSecret) {
402
if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
403
throw new IllegalStateException(
404
"No TlsRsaPremasterSecretParameterSpec specified");
405
}
406
407
// polish the TLS premaster secret
408
encoded = KeyUtil.checkTlsPreMasterSecretKey(
409
((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(),
410
((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(),
411
random, encoded, (failover != null));
412
}
413
414
return constructKey(encoded, algorithm, type);
415
}
416
417
// see JCE spec
418
protected int engineGetKeySize(Key key) throws InvalidKeyException {
419
420
if (key instanceof CKey) {
421
return ((CKey) key).length();
422
423
} else if (key instanceof RSAKey) {
424
return ((RSAKey) key).getModulus().bitLength();
425
426
} else {
427
throw new InvalidKeyException("Unsupported key type: " + key);
428
}
429
}
430
431
// Construct an X.509 encoded public key.
432
private static PublicKey constructPublicKey(byte[] encodedKey,
433
String encodedKeyAlgorithm)
434
throws InvalidKeyException, NoSuchAlgorithmException {
435
436
try {
437
KeyFactory keyFactory = KeyFactory.getInstance(encodedKeyAlgorithm);
438
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
439
440
return keyFactory.generatePublic(keySpec);
441
442
} catch (NoSuchAlgorithmException nsae) {
443
throw new NoSuchAlgorithmException("No installed provider " +
444
"supports the " + encodedKeyAlgorithm + " algorithm", nsae);
445
446
} catch (InvalidKeySpecException ike) {
447
throw new InvalidKeyException("Cannot construct public key", ike);
448
}
449
}
450
451
// Construct a PKCS #8 encoded private key.
452
private static PrivateKey constructPrivateKey(byte[] encodedKey,
453
String encodedKeyAlgorithm)
454
throws InvalidKeyException, NoSuchAlgorithmException {
455
456
try {
457
KeyFactory keyFactory = KeyFactory.getInstance(encodedKeyAlgorithm);
458
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
459
460
return keyFactory.generatePrivate(keySpec);
461
462
} catch (NoSuchAlgorithmException nsae) {
463
throw new NoSuchAlgorithmException("No installed provider " +
464
"supports the " + encodedKeyAlgorithm + " algorithm", nsae);
465
466
} catch (InvalidKeySpecException ike) {
467
throw new InvalidKeyException("Cannot construct private key", ike);
468
}
469
}
470
471
// Construct an encoded secret key.
472
private static SecretKey constructSecretKey(byte[] encodedKey,
473
String encodedKeyAlgorithm) {
474
475
return new SecretKeySpec(encodedKey, encodedKeyAlgorithm);
476
}
477
478
private static Key constructKey(byte[] encodedKey,
479
String encodedKeyAlgorithm,
480
int keyType) throws InvalidKeyException, NoSuchAlgorithmException {
481
482
switch (keyType) {
483
case Cipher.PUBLIC_KEY:
484
return constructPublicKey(encodedKey, encodedKeyAlgorithm);
485
case Cipher.PRIVATE_KEY:
486
return constructPrivateKey(encodedKey, encodedKeyAlgorithm);
487
case Cipher.SECRET_KEY:
488
return constructSecretKey(encodedKey, encodedKeyAlgorithm);
489
default:
490
throw new InvalidKeyException("Unknown key type " + keyType);
491
}
492
}
493
494
/*
495
* Encrypt/decrypt a data buffer using Microsoft Crypto API with HCRYPTKEY.
496
* It expects and returns ciphertext data in big-endian form.
497
*/
498
private native static byte[] encryptDecrypt(byte[] data, int dataSize,
499
long hCryptKey, boolean doEncrypt) throws KeyException;
500
501
}
502
503