8317547: Enhance TLS connection support
Reviewed-by: ahgross, rhalade, weijun, valeriep
This commit is contained in:
parent
c1a568c9c4
commit
bf7bd9a16c
@ -98,6 +98,7 @@ public final class RSACipher extends CipherSpi {
|
|||||||
|
|
||||||
// cipher parameter for OAEP padding and TLS RSA premaster secret
|
// cipher parameter for OAEP padding and TLS RSA premaster secret
|
||||||
private AlgorithmParameterSpec spec = null;
|
private AlgorithmParameterSpec spec = null;
|
||||||
|
private boolean forTlsPremasterSecret = false;
|
||||||
|
|
||||||
// buffer for the data
|
// buffer for the data
|
||||||
private byte[] buffer;
|
private byte[] buffer;
|
||||||
@ -286,6 +287,7 @@ public final class RSACipher extends CipherSpi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
spec = params;
|
spec = params;
|
||||||
|
forTlsPremasterSecret = true;
|
||||||
this.random = random; // for TLS RSA premaster secret
|
this.random = random; // for TLS RSA premaster secret
|
||||||
}
|
}
|
||||||
int blockType = (mode <= MODE_DECRYPT) ? RSAPadding.PAD_BLOCKTYPE_2
|
int blockType = (mode <= MODE_DECRYPT) ? RSAPadding.PAD_BLOCKTYPE_2
|
||||||
@ -377,7 +379,7 @@ public final class RSACipher extends CipherSpi {
|
|||||||
byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs);
|
byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs);
|
||||||
paddingCopy = RSACore.rsa(decryptBuffer, privateKey, false);
|
paddingCopy = RSACore.rsa(decryptBuffer, privateKey, false);
|
||||||
result = padding.unpad(paddingCopy);
|
result = padding.unpad(paddingCopy);
|
||||||
if (result == null) {
|
if (result == null && !forTlsPremasterSecret) {
|
||||||
throw new BadPaddingException
|
throw new BadPaddingException
|
||||||
("Padding error in decryption");
|
("Padding error in decryption");
|
||||||
}
|
}
|
||||||
@ -466,26 +468,22 @@ public final class RSACipher extends CipherSpi {
|
|||||||
|
|
||||||
boolean isTlsRsaPremasterSecret =
|
boolean isTlsRsaPremasterSecret =
|
||||||
algorithm.equals("TlsRsaPremasterSecret");
|
algorithm.equals("TlsRsaPremasterSecret");
|
||||||
Exception failover = null;
|
|
||||||
byte[] encoded = null;
|
byte[] encoded = null;
|
||||||
|
|
||||||
update(wrappedKey, 0, wrappedKey.length);
|
update(wrappedKey, 0, wrappedKey.length);
|
||||||
try {
|
try {
|
||||||
encoded = doFinal();
|
encoded = doFinal();
|
||||||
} catch (BadPaddingException e) {
|
} catch (BadPaddingException | IllegalBlockSizeException e) {
|
||||||
if (isTlsRsaPremasterSecret) {
|
// BadPaddingException cannot happen for TLS RSA unwrap.
|
||||||
failover = e;
|
// In that case, padding error is indicated by returning null.
|
||||||
} else {
|
// IllegalBlockSizeException cannot happen in any case,
|
||||||
throw new InvalidKeyException("Unwrapping failed", e);
|
// because of the length check above.
|
||||||
}
|
|
||||||
} catch (IllegalBlockSizeException e) {
|
|
||||||
// should not occur, handled with length check above
|
|
||||||
throw new InvalidKeyException("Unwrapping failed", e);
|
throw new InvalidKeyException("Unwrapping failed", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isTlsRsaPremasterSecret) {
|
if (isTlsRsaPremasterSecret) {
|
||||||
if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
|
if (!forTlsPremasterSecret) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"No TlsRsaPremasterSecretParameterSpec specified");
|
"No TlsRsaPremasterSecretParameterSpec specified");
|
||||||
}
|
}
|
||||||
@ -494,7 +492,7 @@ public final class RSACipher extends CipherSpi {
|
|||||||
encoded = KeyUtil.checkTlsPreMasterSecretKey(
|
encoded = KeyUtil.checkTlsPreMasterSecretKey(
|
||||||
((TlsRsaPremasterSecretParameterSpec) spec).getClientVersion(),
|
((TlsRsaPremasterSecretParameterSpec) spec).getClientVersion(),
|
||||||
((TlsRsaPremasterSecretParameterSpec) spec).getServerVersion(),
|
((TlsRsaPremasterSecretParameterSpec) spec).getServerVersion(),
|
||||||
random, encoded, (failover != null));
|
random, encoded, encoded == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ConstructKeys.constructKey(encoded, algorithm, type);
|
return ConstructKeys.constructKey(encoded, algorithm, type);
|
||||||
|
@ -291,13 +291,14 @@ public final class KeyUtil {
|
|||||||
* contains the lower of that suggested by the client in the client
|
* contains the lower of that suggested by the client in the client
|
||||||
* hello and the highest supported by the server.
|
* hello and the highest supported by the server.
|
||||||
* @param encoded the encoded key in its "RAW" encoding format
|
* @param encoded the encoded key in its "RAW" encoding format
|
||||||
* @param isFailOver whether the previous decryption of the
|
* @param failure true if encoded is incorrect according to previous checks
|
||||||
* encrypted PreMasterSecret message run into problem
|
|
||||||
* @return the polished PreMasterSecret key in its "RAW" encoding format
|
* @return the polished PreMasterSecret key in its "RAW" encoding format
|
||||||
*/
|
*/
|
||||||
public static byte[] checkTlsPreMasterSecretKey(
|
public static byte[] checkTlsPreMasterSecretKey(
|
||||||
int clientVersion, int serverVersion, SecureRandom random,
|
int clientVersion, int serverVersion, SecureRandom random,
|
||||||
byte[] encoded, boolean isFailOver) {
|
byte[] encoded, boolean failure) {
|
||||||
|
|
||||||
|
byte[] tmp;
|
||||||
|
|
||||||
if (random == null) {
|
if (random == null) {
|
||||||
random = JCAUtil.getSecureRandom();
|
random = JCAUtil.getSecureRandom();
|
||||||
@ -305,30 +306,38 @@ public final class KeyUtil {
|
|||||||
byte[] replacer = new byte[48];
|
byte[] replacer = new byte[48];
|
||||||
random.nextBytes(replacer);
|
random.nextBytes(replacer);
|
||||||
|
|
||||||
if (!isFailOver && (encoded != null)) {
|
if (failure) {
|
||||||
// check the length
|
tmp = replacer;
|
||||||
if (encoded.length != 48) {
|
} else {
|
||||||
// private, don't need to clone the byte array.
|
tmp = encoded;
|
||||||
return replacer;
|
|
||||||
}
|
|
||||||
|
|
||||||
int encodedVersion =
|
|
||||||
((encoded[0] & 0xFF) << 8) | (encoded[1] & 0xFF);
|
|
||||||
if (clientVersion != encodedVersion) {
|
|
||||||
if (clientVersion > 0x0301 || // 0x0301: TLSv1
|
|
||||||
serverVersion != encodedVersion) {
|
|
||||||
encoded = replacer;
|
|
||||||
} // Otherwise, For compatibility, we maintain the behavior
|
|
||||||
// that the version in pre_master_secret can be the
|
|
||||||
// negotiated version for TLS v1.0 and SSL v3.0.
|
|
||||||
}
|
|
||||||
|
|
||||||
// private, don't need to clone the byte array.
|
|
||||||
return encoded;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// private, don't need to clone the byte array.
|
if (tmp == null) {
|
||||||
return replacer;
|
encoded = replacer;
|
||||||
|
} else {
|
||||||
|
encoded = tmp;
|
||||||
|
}
|
||||||
|
// check the length
|
||||||
|
if (encoded.length != 48) {
|
||||||
|
// private, don't need to clone the byte array.
|
||||||
|
tmp = replacer;
|
||||||
|
} else {
|
||||||
|
tmp = encoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
int encodedVersion =
|
||||||
|
((tmp[0] & 0xFF) << 8) | (tmp[1] & 0xFF);
|
||||||
|
int check1 = 0;
|
||||||
|
int check2 = 0;
|
||||||
|
int check3 = 0;
|
||||||
|
if (clientVersion != encodedVersion) check1 = 1;
|
||||||
|
if (clientVersion > 0x0301) check2 = 1;
|
||||||
|
if (serverVersion != encodedVersion) check3 = 1;
|
||||||
|
if ((check1 & (check2 | check3)) == 1) {
|
||||||
|
return replacer;
|
||||||
|
} else {
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -30,6 +30,7 @@ import java.security.*;
|
|||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
import java.security.interfaces.*;
|
import java.security.interfaces.*;
|
||||||
import java.security.spec.*;
|
import java.security.spec.*;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import javax.crypto.*;
|
import javax.crypto.*;
|
||||||
import javax.crypto.spec.*;
|
import javax.crypto.spec.*;
|
||||||
@ -61,6 +62,9 @@ import sun.security.util.KeyUtil;
|
|||||||
*/
|
*/
|
||||||
public final class CRSACipher extends CipherSpi {
|
public final class CRSACipher extends CipherSpi {
|
||||||
|
|
||||||
|
private static final int ERROR_INVALID_PARAMETER = 0x57;
|
||||||
|
private static final int NTE_INVALID_PARAMETER = 0x80090027;
|
||||||
|
|
||||||
// constant for an empty byte array
|
// constant for an empty byte array
|
||||||
private static final byte[] B0 = new byte[0];
|
private static final byte[] B0 = new byte[0];
|
||||||
|
|
||||||
@ -101,6 +105,8 @@ public final class CRSACipher extends CipherSpi {
|
|||||||
// cipher parameter for TLS RSA premaster secret
|
// cipher parameter for TLS RSA premaster secret
|
||||||
private AlgorithmParameterSpec spec = null;
|
private AlgorithmParameterSpec spec = null;
|
||||||
|
|
||||||
|
private boolean forTlsPremasterSecret = false;
|
||||||
|
|
||||||
// the source of randomness
|
// the source of randomness
|
||||||
private SecureRandom random;
|
private SecureRandom random;
|
||||||
|
|
||||||
@ -171,6 +177,9 @@ public final class CRSACipher extends CipherSpi {
|
|||||||
}
|
}
|
||||||
spec = params;
|
spec = params;
|
||||||
this.random = random; // for TLS RSA premaster secret
|
this.random = random; // for TLS RSA premaster secret
|
||||||
|
this.forTlsPremasterSecret = true;
|
||||||
|
} else {
|
||||||
|
this.forTlsPremasterSecret = false;
|
||||||
}
|
}
|
||||||
init(opmode, key);
|
init(opmode, key);
|
||||||
}
|
}
|
||||||
@ -278,8 +287,7 @@ public final class CRSACipher extends CipherSpi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// internal doFinal() method. Here we perform the actual RSA operation
|
// internal doFinal() method. Here we perform the actual RSA operation
|
||||||
private byte[] doFinal() throws BadPaddingException,
|
private byte[] doFinal() throws IllegalBlockSizeException {
|
||||||
IllegalBlockSizeException {
|
|
||||||
if (bufOfs > buffer.length) {
|
if (bufOfs > buffer.length) {
|
||||||
throw new IllegalBlockSizeException("Data must not be longer "
|
throw new IllegalBlockSizeException("Data must not be longer "
|
||||||
+ "than " + (buffer.length - paddingLength) + " bytes");
|
+ "than " + (buffer.length - paddingLength) + " bytes");
|
||||||
@ -308,7 +316,7 @@ public final class CRSACipher extends CipherSpi {
|
|||||||
throw new AssertionError("Internal error");
|
throw new AssertionError("Internal error");
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (KeyException e) {
|
} catch (KeyException | BadPaddingException e) {
|
||||||
throw new ProviderException(e);
|
throw new ProviderException(e);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
@ -331,14 +339,14 @@ public final class CRSACipher extends CipherSpi {
|
|||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
|
protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
|
||||||
throws BadPaddingException, IllegalBlockSizeException {
|
throws IllegalBlockSizeException {
|
||||||
update(in, inOfs, inLen);
|
update(in, inOfs, inLen);
|
||||||
return doFinal();
|
return doFinal();
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
|
protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
|
||||||
int outOfs) throws ShortBufferException, BadPaddingException,
|
int outOfs) throws ShortBufferException,
|
||||||
IllegalBlockSizeException {
|
IllegalBlockSizeException {
|
||||||
if (outputSize > out.length - outOfs) {
|
if (outputSize > out.length - outOfs) {
|
||||||
throw new ShortBufferException
|
throw new ShortBufferException
|
||||||
@ -354,6 +362,7 @@ public final class CRSACipher extends CipherSpi {
|
|||||||
// see JCE spec
|
// see JCE spec
|
||||||
protected byte[] engineWrap(Key key) throws InvalidKeyException,
|
protected byte[] engineWrap(Key key) throws InvalidKeyException,
|
||||||
IllegalBlockSizeException {
|
IllegalBlockSizeException {
|
||||||
|
|
||||||
byte[] encoded = key.getEncoded(); // TODO - unextractable key
|
byte[] encoded = key.getEncoded(); // TODO - unextractable key
|
||||||
if ((encoded == null) || (encoded.length == 0)) {
|
if ((encoded == null) || (encoded.length == 0)) {
|
||||||
throw new InvalidKeyException("Could not obtain encoded key");
|
throw new InvalidKeyException("Could not obtain encoded key");
|
||||||
@ -362,12 +371,7 @@ public final class CRSACipher extends CipherSpi {
|
|||||||
throw new InvalidKeyException("Key is too long for wrapping");
|
throw new InvalidKeyException("Key is too long for wrapping");
|
||||||
}
|
}
|
||||||
update(encoded, 0, encoded.length);
|
update(encoded, 0, encoded.length);
|
||||||
try {
|
return doFinal();
|
||||||
return doFinal();
|
|
||||||
} catch (BadPaddingException e) {
|
|
||||||
// should not occur
|
|
||||||
throw new InvalidKeyException("Wrapping failed", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
@ -388,31 +392,31 @@ public final class CRSACipher extends CipherSpi {
|
|||||||
update(wrappedKey, 0, wrappedKey.length);
|
update(wrappedKey, 0, wrappedKey.length);
|
||||||
try {
|
try {
|
||||||
encoded = doFinal();
|
encoded = doFinal();
|
||||||
} catch (BadPaddingException e) {
|
|
||||||
if (isTlsRsaPremasterSecret) {
|
|
||||||
failover = e;
|
|
||||||
} else {
|
|
||||||
throw new InvalidKeyException("Unwrapping failed", e);
|
|
||||||
}
|
|
||||||
} catch (IllegalBlockSizeException e) {
|
} catch (IllegalBlockSizeException e) {
|
||||||
// should not occur, handled with length check above
|
// should not occur, handled with length check above
|
||||||
throw new InvalidKeyException("Unwrapping failed", e);
|
throw new InvalidKeyException("Unwrapping failed", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTlsRsaPremasterSecret) {
|
try {
|
||||||
if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
|
if (isTlsRsaPremasterSecret) {
|
||||||
throw new IllegalStateException(
|
if (!forTlsPremasterSecret) {
|
||||||
"No TlsRsaPremasterSecretParameterSpec specified");
|
throw new IllegalStateException(
|
||||||
|
"No TlsRsaPremasterSecretParameterSpec specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
// polish the TLS premaster secret
|
||||||
|
encoded = KeyUtil.checkTlsPreMasterSecretKey(
|
||||||
|
((TlsRsaPremasterSecretParameterSpec) spec).getClientVersion(),
|
||||||
|
((TlsRsaPremasterSecretParameterSpec) spec).getServerVersion(),
|
||||||
|
random, encoded, encoded == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// polish the TLS premaster secret
|
return constructKey(encoded, algorithm, type);
|
||||||
encoded = KeyUtil.checkTlsPreMasterSecretKey(
|
} finally {
|
||||||
((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(),
|
if (encoded != null) {
|
||||||
((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(),
|
Arrays.fill(encoded, (byte) 0);
|
||||||
random, encoded, (failover != null));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return constructKey(encoded, algorithm, type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
@ -496,17 +500,30 @@ public final class CRSACipher extends CipherSpi {
|
|||||||
* Encrypt/decrypt a data buffer using Microsoft Crypto API or CNG.
|
* Encrypt/decrypt a data buffer using Microsoft Crypto API or CNG.
|
||||||
* It expects and returns ciphertext data in big-endian form.
|
* It expects and returns ciphertext data in big-endian form.
|
||||||
*/
|
*/
|
||||||
private static byte[] encryptDecrypt(byte[] data, int dataSize,
|
private byte[] encryptDecrypt(byte[] data, int dataSize,
|
||||||
CKey key, boolean doEncrypt) throws KeyException {
|
CKey key, boolean doEncrypt) throws KeyException, BadPaddingException {
|
||||||
|
int[] returnStatus = new int[1];
|
||||||
|
byte[] result;
|
||||||
if (key.getHCryptKey() != 0) {
|
if (key.getHCryptKey() != 0) {
|
||||||
return encryptDecrypt(data, dataSize, key.getHCryptKey(), doEncrypt);
|
result = encryptDecrypt(returnStatus, data, dataSize, key.getHCryptKey(), doEncrypt);
|
||||||
} else {
|
} else {
|
||||||
return cngEncryptDecrypt(data, dataSize, key.getHCryptProvider(), doEncrypt);
|
result = cngEncryptDecrypt(returnStatus, data, dataSize, key.getHCryptProvider(), doEncrypt);
|
||||||
}
|
}
|
||||||
|
if ((returnStatus[0] == ERROR_INVALID_PARAMETER) || (returnStatus[0] == NTE_INVALID_PARAMETER)) {
|
||||||
|
if (forTlsPremasterSecret) {
|
||||||
|
result = null;
|
||||||
|
} else {
|
||||||
|
throw new BadPaddingException("Error " + returnStatus[0] + " returned by MSCAPI");
|
||||||
|
}
|
||||||
|
} else if (returnStatus[0] != 0) {
|
||||||
|
throw new KeyException("Error " + returnStatus[0] + " returned by MSCAPI");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native byte[] encryptDecrypt(byte[] data, int dataSize,
|
private static native byte[] encryptDecrypt(int[] returnStatus, byte[] data, int dataSize,
|
||||||
long key, boolean doEncrypt) throws KeyException;
|
long key, boolean doEncrypt) throws KeyException;
|
||||||
private static native byte[] cngEncryptDecrypt(byte[] data, int dataSize,
|
private static native byte[] cngEncryptDecrypt(int[] returnStatus, byte[] data, int dataSize,
|
||||||
long key, boolean doEncrypt) throws KeyException;
|
long key, boolean doEncrypt) throws KeyException;
|
||||||
}
|
}
|
||||||
|
@ -1905,18 +1905,25 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_destroyKeyContainer
|
|||||||
/*
|
/*
|
||||||
* Class: sun_security_mscapi_CRSACipher
|
* Class: sun_security_mscapi_CRSACipher
|
||||||
* Method: encryptDecrypt
|
* Method: encryptDecrypt
|
||||||
* Signature: ([BIJZ)[B
|
* Signature: ([I[BIJZ)[B
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_encryptDecrypt
|
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_encryptDecrypt
|
||||||
(JNIEnv *env, jclass clazz, jbyteArray jData, jint jDataSize, jlong hKey,
|
(JNIEnv *env, jclass clazz, jintArray jResultStatus, jbyteArray jData, jint jDataSize, jlong hKey,
|
||||||
jboolean doEncrypt)
|
jboolean doEncrypt)
|
||||||
{
|
{
|
||||||
jbyteArray result = NULL;
|
jbyteArray result = NULL;
|
||||||
jbyte* pData = NULL;
|
jbyte* pData = NULL;
|
||||||
|
jbyte* resultData = NULL;
|
||||||
DWORD dwDataLen = jDataSize;
|
DWORD dwDataLen = jDataSize;
|
||||||
DWORD dwBufLen = env->GetArrayLength(jData);
|
DWORD dwBufLen = env->GetArrayLength(jData);
|
||||||
DWORD i;
|
DWORD i;
|
||||||
BYTE tmp;
|
BYTE tmp;
|
||||||
|
BOOL success;
|
||||||
|
DWORD ss = ERROR_SUCCESS;
|
||||||
|
DWORD lastError = ERROR_SUCCESS;
|
||||||
|
DWORD resultLen = 0;
|
||||||
|
DWORD pmsLen = 48;
|
||||||
|
jbyte pmsArr[48] = {0};
|
||||||
|
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
@ -1943,6 +1950,8 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_encryptDecrypt
|
|||||||
pData[i] = pData[dwBufLen - i -1];
|
pData[i] = pData[dwBufLen - i -1];
|
||||||
pData[dwBufLen - i - 1] = tmp;
|
pData[dwBufLen - i - 1] = tmp;
|
||||||
}
|
}
|
||||||
|
resultData = pData;
|
||||||
|
resultLen = dwBufLen;
|
||||||
} else {
|
} else {
|
||||||
// convert to little-endian
|
// convert to little-endian
|
||||||
for (i = 0; i < dwBufLen / 2; i++) {
|
for (i = 0; i < dwBufLen / 2; i++) {
|
||||||
@ -1952,21 +1961,28 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_encryptDecrypt
|
|||||||
}
|
}
|
||||||
|
|
||||||
// decrypt
|
// decrypt
|
||||||
if (! ::CryptDecrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, //deprecated
|
success = ::CryptDecrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, //deprecated
|
||||||
&dwBufLen)) {
|
&dwBufLen);
|
||||||
|
lastError = GetLastError();
|
||||||
ThrowException(env, KEY_EXCEPTION, GetLastError());
|
if (success) {
|
||||||
__leave;
|
ss = ERROR_SUCCESS;
|
||||||
|
resultData = pData;
|
||||||
|
resultLen = dwBufLen;
|
||||||
|
} else {
|
||||||
|
ss = lastError;
|
||||||
|
resultData = pmsArr;
|
||||||
|
resultLen = pmsLen;
|
||||||
}
|
}
|
||||||
|
env->SetIntArrayRegion(jResultStatus, 0, 1, (jint*) &ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new byte array
|
// Create new byte array
|
||||||
if ((result = env->NewByteArray(dwBufLen)) == NULL) {
|
if ((result = env->NewByteArray(resultLen)) == NULL) {
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy data from native buffer to Java buffer
|
// Copy data from native buffer to Java buffer
|
||||||
env->SetByteArrayRegion(result, 0, dwBufLen, (jbyte*) pData);
|
env->SetByteArrayRegion(result, 0, resultLen, (jbyte*) resultData);
|
||||||
}
|
}
|
||||||
__finally
|
__finally
|
||||||
{
|
{
|
||||||
@ -1980,17 +1996,22 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_encryptDecrypt
|
|||||||
/*
|
/*
|
||||||
* Class: sun_security_mscapi_CRSACipher
|
* Class: sun_security_mscapi_CRSACipher
|
||||||
* Method: cngEncryptDecrypt
|
* Method: cngEncryptDecrypt
|
||||||
* Signature: ([BIJZ)[B
|
* Signature: ([I[BIJZ)[B
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_cngEncryptDecrypt
|
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_cngEncryptDecrypt
|
||||||
(JNIEnv *env, jclass clazz, jbyteArray jData, jint jDataSize, jlong hKey,
|
(JNIEnv *env, jclass clazz, jintArray jResultStatus, jbyteArray jData, jint jDataSize, jlong hKey,
|
||||||
jboolean doEncrypt)
|
jboolean doEncrypt)
|
||||||
{
|
{
|
||||||
SECURITY_STATUS ss;
|
SECURITY_STATUS ss;
|
||||||
jbyteArray result = NULL;
|
jbyteArray result = NULL;
|
||||||
jbyte* pData = NULL;
|
jbyte* pData = NULL;
|
||||||
|
jbyte* resultData = NULL;
|
||||||
DWORD dwDataLen = jDataSize;
|
DWORD dwDataLen = jDataSize;
|
||||||
DWORD dwBufLen = env->GetArrayLength(jData);
|
DWORD dwBufLen = env->GetArrayLength(jData);
|
||||||
|
DWORD resultLen = 0;
|
||||||
|
DWORD pmsLen = 48;
|
||||||
|
jbyte pmsArr[48] = {0};
|
||||||
|
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
// Copy data from Java buffer to native buffer
|
// Copy data from Java buffer to native buffer
|
||||||
@ -2010,6 +2031,9 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_cngEncryptDecry
|
|||||||
if (ss != ERROR_SUCCESS) {
|
if (ss != ERROR_SUCCESS) {
|
||||||
ThrowException(env, KEY_EXCEPTION, ss);
|
ThrowException(env, KEY_EXCEPTION, ss);
|
||||||
__leave;
|
__leave;
|
||||||
|
} else {
|
||||||
|
resultLen = dwBufLen;
|
||||||
|
resultData = pData;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// decrypt
|
// decrypt
|
||||||
@ -2018,18 +2042,22 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_cngEncryptDecry
|
|||||||
0,
|
0,
|
||||||
(PBYTE)pData, dwBufLen,
|
(PBYTE)pData, dwBufLen,
|
||||||
&dwBufLen, NCRYPT_PAD_PKCS1_FLAG);
|
&dwBufLen, NCRYPT_PAD_PKCS1_FLAG);
|
||||||
if (ss != ERROR_SUCCESS) {
|
env->SetIntArrayRegion(jResultStatus, 0, 1, (jint*) &ss);
|
||||||
ThrowException(env, KEY_EXCEPTION, ss);
|
if (ss == ERROR_SUCCESS) {
|
||||||
__leave;
|
resultLen = dwBufLen;
|
||||||
|
resultData = pData;
|
||||||
|
} else {
|
||||||
|
resultLen = pmsLen;
|
||||||
|
resultData = pmsArr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Create new byte array
|
// Create new byte array
|
||||||
if ((result = env->NewByteArray(dwBufLen)) == NULL) {
|
if ((result = env->NewByteArray(resultLen)) == NULL) {
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy data from native buffer to Java buffer
|
// Copy data from native buffer to Java buffer
|
||||||
env->SetByteArrayRegion(result, 0, dwBufLen, (jbyte*) pData);
|
env->SetByteArrayRegion(result, 0, resultLen, (jbyte*) resultData);
|
||||||
}
|
}
|
||||||
__finally {
|
__finally {
|
||||||
if (pData) {
|
if (pData) {
|
||||||
|
Loading…
Reference in New Issue
Block a user