Skip to content

Commit d4b472f

Browse files
alexeybakhtingnu-andrew
authored andcommittedJan 11, 2024
8317547: Enhance TLS connection support
Reviewed-by: mbalao, andrew Backport-of: 066482f9686ca81068f9386322afda8e73323f5e
1 parent 7c693ce commit d4b472f

File tree

4 files changed

+119
-76
lines changed

4 files changed

+119
-76
lines changed
 

‎jdk/src/share/classes/com/sun/crypto/provider/RSACipher.java

+10-12
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ public final class RSACipher extends CipherSpi {
9898

9999
// cipher parameter for OAEP padding and TLS RSA premaster secret
100100
private AlgorithmParameterSpec spec = null;
101+
private boolean forTlsPremasterSecret = false;
101102

102103
// buffer for the data
103104
private byte[] buffer;
@@ -290,6 +291,7 @@ private void init(int opmode, Key key, SecureRandom random,
290291
}
291292

292293
spec = params;
294+
forTlsPremasterSecret = true;
293295
this.random = random; // for TLS RSA premaster secret
294296
}
295297
int blockType = (mode <= MODE_DECRYPT) ? RSAPadding.PAD_BLOCKTYPE_2
@@ -381,7 +383,7 @@ private byte[] doFinal() throws BadPaddingException,
381383
byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs);
382384
paddingCopy = RSACore.rsa(decryptBuffer, privateKey, false);
383385
result = padding.unpad(paddingCopy);
384-
if (result == null) {
386+
if (result == null && !forTlsPremasterSecret) {
385387
throw new BadPaddingException
386388
("Padding error in decryption");
387389
}
@@ -469,26 +471,22 @@ protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
469471

470472
boolean isTlsRsaPremasterSecret =
471473
algorithm.equals("TlsRsaPremasterSecret");
472-
Exception failover = null;
473474
byte[] encoded = null;
474475

475476
update(wrappedKey, 0, wrappedKey.length);
476477
try {
477478
encoded = doFinal();
478-
} catch (BadPaddingException e) {
479-
if (isTlsRsaPremasterSecret) {
480-
failover = e;
481-
} else {
482-
throw new InvalidKeyException("Unwrapping failed", e);
483-
}
484-
} catch (IllegalBlockSizeException e) {
485-
// should not occur, handled with length check above
479+
} catch (BadPaddingException | IllegalBlockSizeException e) {
480+
// BadPaddingException cannot happen for TLS RSA unwrap.
481+
// In that case, padding error is indicated by returning null.
482+
// IllegalBlockSizeException cannot happen in any case,
483+
// because of the length check above.
486484
throw new InvalidKeyException("Unwrapping failed", e);
487485
}
488486

489487
try {
490488
if (isTlsRsaPremasterSecret) {
491-
if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
489+
if (!forTlsPremasterSecret) {
492490
throw new IllegalStateException(
493491
"No TlsRsaPremasterSecretParameterSpec specified");
494492
}
@@ -497,7 +495,7 @@ protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
497495
encoded = KeyUtil.checkTlsPreMasterSecretKey(
498496
((TlsRsaPremasterSecretParameterSpec) spec).getClientVersion(),
499497
((TlsRsaPremasterSecretParameterSpec) spec).getServerVersion(),
500-
random, encoded, (failover != null));
498+
random, encoded, encoded == null);
501499
}
502500

503501
return ConstructKeys.constructKey(encoded, algorithm, type);

‎jdk/src/share/classes/sun/security/util/KeyUtil.java

+32-23
Original file line numberDiff line numberDiff line change
@@ -253,44 +253,53 @@ public static final boolean isOracleJCEProvider(String providerName) {
253253
* contains the lower of that suggested by the client in the client
254254
* hello and the highest supported by the server.
255255
* @param encoded the encoded key in its "RAW" encoding format
256-
* @param isFailover whether or not the previous decryption of the
257-
* encrypted PreMasterSecret message run into problem
256+
* @param failure true if encoded is incorrect according to previous checks
258257
* @return the polished PreMasterSecret key in its "RAW" encoding format
259258
*/
260259
public static byte[] checkTlsPreMasterSecretKey(
261260
int clientVersion, int serverVersion, SecureRandom random,
262-
byte[] encoded, boolean isFailOver) {
261+
byte[] encoded, boolean failure) {
262+
263+
byte[] tmp;
263264

264265
if (random == null) {
265266
random = JCAUtil.getSecureRandom();
266267
}
267268
byte[] replacer = new byte[48];
268269
random.nextBytes(replacer);
269270

270-
if (!isFailOver && (encoded != null)) {
271-
// check the length
272-
if (encoded.length != 48) {
273-
// private, don't need to clone the byte array.
274-
return replacer;
275-
}
276-
277-
int encodedVersion =
278-
((encoded[0] & 0xFF) << 8) | (encoded[1] & 0xFF);
279-
if (clientVersion != encodedVersion) {
280-
if (clientVersion > 0x0301 || // 0x0301: TLSv1
281-
serverVersion != encodedVersion) {
282-
encoded = replacer;
283-
} // Otherwise, For compatibility, we maintain the behavior
284-
// that the version in pre_master_secret can be the
285-
// negotiated version for TLS v1.0 and SSL v3.0.
286-
}
271+
if (failure) {
272+
tmp = replacer;
273+
} else {
274+
tmp = encoded;
275+
}
287276

277+
if (tmp == null) {
278+
encoded = replacer;
279+
} else {
280+
encoded = tmp;
281+
}
282+
// check the length
283+
if (encoded.length != 48) {
288284
// private, don't need to clone the byte array.
289-
return encoded;
285+
tmp = replacer;
286+
} else {
287+
tmp = encoded;
290288
}
291289

292-
// private, don't need to clone the byte array.
293-
return replacer;
290+
int encodedVersion =
291+
((tmp[0] & 0xFF) << 8) | (tmp[1] & 0xFF);
292+
int check1 = 0;
293+
int check2 = 0;
294+
int check3 = 0;
295+
if (clientVersion != encodedVersion) check1 = 1;
296+
if (clientVersion > 0x0301) check2 = 1;
297+
if (serverVersion != encodedVersion) check3 = 1;
298+
if ((check1 & (check2 | check3)) == 1) {
299+
return replacer;
300+
} else {
301+
return tmp;
302+
}
294303
}
295304

296305
/**

‎jdk/src/windows/classes/sun/security/mscapi/CRSACipher.java

+51-31
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
3030
import java.security.Key;
3131
import java.security.interfaces.*;
3232
import java.security.spec.*;
33+
import java.util.Arrays;
3334

3435
import javax.crypto.*;
3536
import javax.crypto.spec.*;
@@ -61,6 +62,9 @@
6162
*/
6263
public final class CRSACipher extends CipherSpi {
6364

65+
private static final int ERROR_INVALID_PARAMETER = 0x57;
66+
private static final int NTE_INVALID_PARAMETER = 0x80090027;
67+
6468
// constant for an empty byte array
6569
private final static byte[] B0 = new byte[0];
6670

@@ -101,6 +105,8 @@ public final class CRSACipher extends CipherSpi {
101105
// cipher parameter for TLS RSA premaster secret
102106
private AlgorithmParameterSpec spec = null;
103107

108+
private boolean forTlsPremasterSecret = false;
109+
104110
// the source of randomness
105111
private SecureRandom random;
106112

@@ -171,6 +177,9 @@ protected void engineInit(int opmode, Key key,
171177
}
172178
spec = params;
173179
this.random = random; // for TLS RSA premaster secret
180+
this.forTlsPremasterSecret = true;
181+
} else {
182+
this.forTlsPremasterSecret = false;
174183
}
175184
init(opmode, key);
176185
}
@@ -277,8 +286,7 @@ private void update(byte[] in, int inOfs, int inLen) {
277286
}
278287

279288
// internal doFinal() method. Here we perform the actual RSA operation
280-
private byte[] doFinal() throws BadPaddingException,
281-
IllegalBlockSizeException {
289+
private byte[] doFinal() throws IllegalBlockSizeException {
282290
if (bufOfs > buffer.length) {
283291
throw new IllegalBlockSizeException("Data must not be longer "
284292
+ "than " + (buffer.length - paddingLength) + " bytes");
@@ -307,7 +315,7 @@ private byte[] doFinal() throws BadPaddingException,
307315
throw new AssertionError("Internal error");
308316
}
309317

310-
} catch (KeyException e) {
318+
} catch (KeyException | BadPaddingException e) {
311319
throw new ProviderException(e);
312320

313321
} finally {
@@ -330,14 +338,14 @@ protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
330338

331339
// see JCE spec
332340
protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
333-
throws BadPaddingException, IllegalBlockSizeException {
341+
throws IllegalBlockSizeException {
334342
update(in, inOfs, inLen);
335343
return doFinal();
336344
}
337345

338346
// see JCE spec
339347
protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
340-
int outOfs) throws ShortBufferException, BadPaddingException,
348+
int outOfs) throws ShortBufferException,
341349
IllegalBlockSizeException {
342350
if (outputSize > out.length - outOfs) {
343351
throw new ShortBufferException
@@ -353,6 +361,7 @@ protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
353361
// see JCE spec
354362
protected byte[] engineWrap(Key key) throws InvalidKeyException,
355363
IllegalBlockSizeException {
364+
356365
byte[] encoded = key.getEncoded(); // TODO - unextractable key
357366
if ((encoded == null) || (encoded.length == 0)) {
358367
throw new InvalidKeyException("Could not obtain encoded key");
@@ -361,12 +370,7 @@ protected byte[] engineWrap(Key key) throws InvalidKeyException,
361370
throw new InvalidKeyException("Key is too long for wrapping");
362371
}
363372
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-
}
373+
return doFinal();
370374
}
371375

372376
// see JCE spec
@@ -387,31 +391,31 @@ protected java.security.Key engineUnwrap(byte[] wrappedKey,
387391
update(wrappedKey, 0, wrappedKey.length);
388392
try {
389393
encoded = doFinal();
390-
} catch (BadPaddingException e) {
391-
if (isTlsRsaPremasterSecret) {
392-
failover = e;
393-
} else {
394-
throw new InvalidKeyException("Unwrapping failed", e);
395-
}
396394
} catch (IllegalBlockSizeException e) {
397395
// should not occur, handled with length check above
398396
throw new InvalidKeyException("Unwrapping failed", e);
399397
}
400398

401-
if (isTlsRsaPremasterSecret) {
402-
if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
403-
throw new IllegalStateException(
404-
"No TlsRsaPremasterSecretParameterSpec specified");
399+
try {
400+
if (isTlsRsaPremasterSecret) {
401+
if (!forTlsPremasterSecret) {
402+
throw new IllegalStateException(
403+
"No TlsRsaPremasterSecretParameterSpec specified");
404+
}
405+
406+
// polish the TLS premaster secret
407+
encoded = KeyUtil.checkTlsPreMasterSecretKey(
408+
((TlsRsaPremasterSecretParameterSpec) spec).getClientVersion(),
409+
((TlsRsaPremasterSecretParameterSpec) spec).getServerVersion(),
410+
random, encoded, encoded == null);
405411
}
406412

407-
// polish the TLS premaster secret
408-
encoded = KeyUtil.checkTlsPreMasterSecretKey(
409-
((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(),
410-
((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(),
411-
random, encoded, (failover != null));
413+
return constructKey(encoded, algorithm, type);
414+
} finally {
415+
if (encoded != null) {
416+
Arrays.fill(encoded, (byte) 0);
417+
}
412418
}
413-
414-
return constructKey(encoded, algorithm, type);
415419
}
416420

417421
// see JCE spec
@@ -495,7 +499,23 @@ private static Key constructKey(byte[] encodedKey,
495499
* Encrypt/decrypt a data buffer using Microsoft Crypto API with HCRYPTKEY.
496500
* It expects and returns ciphertext data in big-endian form.
497501
*/
498-
private native static byte[] encryptDecrypt(byte[] data, int dataSize,
499-
long hCryptKey, boolean doEncrypt) throws KeyException;
502+
private byte[] encryptDecrypt(byte[] data, int dataSize,
503+
long hCryptKey, boolean doEncrypt) throws KeyException, BadPaddingException {
504+
int[] returnStatus = new int[1];
505+
byte[] result= encryptDecrypt(returnStatus, data, dataSize, hCryptKey, doEncrypt);
506+
if ((returnStatus[0] == ERROR_INVALID_PARAMETER) || (returnStatus[0] == NTE_INVALID_PARAMETER)) {
507+
if (forTlsPremasterSecret) {
508+
result = null;
509+
} else {
510+
throw new BadPaddingException("Error " + returnStatus[0] + " returned by MSCAPI");
511+
}
512+
} else if (returnStatus[0] != 0) {
513+
throw new KeyException("Error " + returnStatus[0] + " returned by MSCAPI");
514+
}
515+
516+
return result;
517+
}
518+
private static native byte[] encryptDecrypt(int[] returnStatus, byte[] data, int dataSize,
519+
long key, boolean doEncrypt) throws KeyException;
500520

501521
}

‎jdk/src/windows/native/sun/security/mscapi/security.cpp

+26-10
Original file line numberDiff line numberDiff line change
@@ -1832,18 +1832,25 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_destroyKeyContainer
18321832
/*
18331833
* Class: sun_security_mscapi_CRSACipher
18341834
* Method: encryptDecrypt
1835-
* Signature: ([BIJZ)[B
1835+
* Signature: ([I[BIJZ)[B
18361836
*/
18371837
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_encryptDecrypt
1838-
(JNIEnv *env, jclass clazz, jbyteArray jData, jint jDataSize, jlong hKey,
1838+
(JNIEnv *env, jclass clazz, jintArray jResultStatus, jbyteArray jData, jint jDataSize, jlong hKey,
18391839
jboolean doEncrypt)
18401840
{
18411841
jbyteArray result = NULL;
18421842
jbyte* pData = NULL;
1843+
jbyte* resultData = NULL;
18431844
DWORD dwDataLen = jDataSize;
18441845
DWORD dwBufLen = env->GetArrayLength(jData);
18451846
DWORD i;
18461847
BYTE tmp;
1848+
BOOL success;
1849+
DWORD ss = ERROR_SUCCESS;
1850+
DWORD lastError = ERROR_SUCCESS;
1851+
DWORD resultLen = 0;
1852+
DWORD pmsLen = 48;
1853+
jbyte pmsArr[48] = {0};
18471854

18481855
__try
18491856
{
@@ -1870,6 +1877,8 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_encryptDecrypt
18701877
pData[i] = pData[dwBufLen - i -1];
18711878
pData[dwBufLen - i - 1] = tmp;
18721879
}
1880+
resultData = pData;
1881+
resultLen = dwBufLen;
18731882
} else {
18741883
// convert to little-endian
18751884
for (i = 0; i < dwBufLen / 2; i++) {
@@ -1879,21 +1888,28 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_encryptDecrypt
18791888
}
18801889

18811890
// decrypt
1882-
if (! ::CryptDecrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, //deprecated
1883-
&dwBufLen)) {
1884-
1885-
ThrowException(env, KEY_EXCEPTION, GetLastError());
1886-
__leave;
1891+
success = ::CryptDecrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, //deprecated
1892+
&dwBufLen);
1893+
lastError = GetLastError();
1894+
if (success) {
1895+
ss = ERROR_SUCCESS;
1896+
resultData = pData;
1897+
resultLen = dwBufLen;
1898+
} else {
1899+
ss = lastError;
1900+
resultData = pmsArr;
1901+
resultLen = pmsLen;
18871902
}
1903+
env->SetIntArrayRegion(jResultStatus, 0, 1, (jint*) &ss);
18881904
}
18891905

1890-
// Create new byte array
1891-
if ((result = env->NewByteArray(dwBufLen)) == NULL) {
1906+
// Create new byte array
1907+
if ((result = env->NewByteArray(resultLen)) == NULL) {
18921908
__leave;
18931909
}
18941910

18951911
// Copy data from native buffer to Java buffer
1896-
env->SetByteArrayRegion(result, 0, dwBufLen, (jbyte*) pData);
1912+
env->SetByteArrayRegion(result, 0, resultLen, (jbyte*) resultData);
18971913
}
18981914
__finally
18991915
{

0 commit comments

Comments
 (0)
Please sign in to comment.