8132082: Let OracleUcrypto accept RSAPrivateKey

Reviewed-by: xuelei, valeriep, coffeys
This commit is contained in:
Valerie Peng 2015-09-04 15:28:01 +03:00 committed by Ivan Gerasimov
parent 33994176ee
commit a8cbc27bce
7 changed files with 216 additions and 78 deletions

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -39,6 +39,7 @@ SUNWprivate_1.1 {
Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal;
Java_com_oracle_security_ucrypto_NativeKey_nativeFree;
Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit;
Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit;
Java_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit;
Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
@ -56,6 +57,7 @@ SUNWprivate_1.1 {
JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeFinal;
JavaCritical_com_oracle_security_ucrypto_NativeKey_nativeFree;
JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit;
JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit;
JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit;
JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,19 +31,9 @@ import java.util.concurrent.ConcurrentSkipListSet;
import java.lang.ref.*;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Key;
import java.security.PublicKey;
import java.security.PrivateKey;
import java.security.KeyFactorySpi;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
/**
* Wrapper class for native keys needed for using ucrypto APIs.
@ -87,6 +77,41 @@ abstract class NativeKey implements Key {
return b;
}
static final class RSAPrivate extends NativeKey implements RSAPrivateKey {
private static final long serialVersionUID = 1622705588904302831L;
private final RSAPrivateKeySpec keySpec;
private final long keyId;
RSAPrivate(KeySpec keySpec) throws InvalidKeySpecException {
super(2);
long pKey = 0L;
if (keySpec instanceof RSAPrivateKeySpec) {
RSAPrivateKeySpec ks = (RSAPrivateKeySpec) keySpec;
BigInteger mod = ks.getModulus();
BigInteger privateExp = ks.getPrivateExponent();
pKey = nativeInit(NativeKey.getMagnitude(mod),
NativeKey.getMagnitude(privateExp));
} else {
throw new InvalidKeySpecException("Only supports RSAPrivateKeySpec");
}
if (pKey == 0L) {
throw new UcryptoException("Error constructing RSA PrivateKey");
}
// track native resource clean up
new KeyRef(this, pKey);
this.keySpec = (RSAPrivateKeySpec) keySpec;
this.keyId = pKey;
}
long value() { return keyId; }
public BigInteger getModulus() { return keySpec.getModulus(); };
public BigInteger getPrivateExponent() { return keySpec.getPrivateExponent(); };
private native static long nativeInit(byte[] mod, byte[] privExp);
}
static final class RSAPrivateCrt extends NativeKey implements RSAPrivateCrtKey {
private static final long serialVersionUID = 6812507588904302831L;
@ -119,7 +144,7 @@ abstract class NativeKey implements Key {
throw new InvalidKeySpecException("Only supports RSAPrivateCrtKeySpec");
}
if (pKey == 0L) {
throw new UcryptoException("Error constructing RSA PrivateKey");
throw new UcryptoException("Error constructing RSA PrivateCrtKey");
}
// track native resource clean up
new KeyRef(this, pKey);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,9 +37,11 @@ import java.security.Key;
import java.security.PublicKey;
import java.security.PrivateKey;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.interfaces.RSAKey;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.KeyFactory;
@ -205,8 +207,8 @@ public class NativeRSACipher extends CipherSpi {
// Make sure the proper opmode uses the proper key
if (doEncrypt && (!(newKey instanceof RSAPublicKey))) {
throw new InvalidKeyException("RSAPublicKey required for encryption");
} else if (!doEncrypt && (!(newKey instanceof RSAPrivateCrtKey))) {
throw new InvalidKeyException("RSAPrivateCrtKey required for decryption");
} else if (!doEncrypt && (!(newKey instanceof RSAPrivateKey))) {
throw new InvalidKeyException("RSAPrivateKey required for decryption");
}
NativeKey nativeKey = null;
@ -223,17 +225,26 @@ public class NativeRSACipher extends CipherSpi {
throw new InvalidKeyException(ikse);
}
} else {
RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) newKey;
try {
nativeKey = (NativeKey) keyFactory.engineGeneratePrivate
(new RSAPrivateCrtKeySpec(privateKey.getModulus(),
privateKey.getPublicExponent(),
privateKey.getPrivateExponent(),
privateKey.getPrimeP(),
privateKey.getPrimeQ(),
privateKey.getPrimeExponentP(),
privateKey.getPrimeExponentQ(),
privateKey.getCrtCoefficient()));
if (newKey instanceof RSAPrivateCrtKey) {
RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) newKey;
nativeKey = (NativeKey) keyFactory.engineGeneratePrivate
(new RSAPrivateCrtKeySpec(privateKey.getModulus(),
privateKey.getPublicExponent(),
privateKey.getPrivateExponent(),
privateKey.getPrimeP(),
privateKey.getPrimeQ(),
privateKey.getPrimeExponentP(),
privateKey.getPrimeExponentQ(),
privateKey.getCrtCoefficient()));
} else if (newKey instanceof RSAPrivateKey) {
RSAPrivateKey privateKey = (RSAPrivateKey) newKey;
nativeKey = (NativeKey) keyFactory.engineGeneratePrivate
(new RSAPrivateKeySpec(privateKey.getModulus(),
privateKey.getPrivateExponent()));
} else {
throw new InvalidKeyException("Unsupported type of RSAPrivateKey");
}
} catch (InvalidKeySpecException ikse) {
throw new InvalidKeyException(ikse);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -38,16 +38,11 @@ import java.security.PublicKey;
import java.security.PrivateKey;
import java.security.KeyFactorySpi;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.*;
/**
* Ucrypto-private KeyFactory class for generating native keys
* needed for using ucrypto APIs. Given that it's not used
* externally, it only needs to support RSAPrivateCrtKeySpec
* and RSAPublicKeySpec objects.
* needed for using ucrypto APIs.
*
* @since 1.9
*/
@ -56,7 +51,13 @@ public final class NativeRSAKeyFactory extends KeyFactorySpi {
@Override
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
throws InvalidKeySpecException {
return new NativeKey.RSAPrivateCrt(keySpec);
if (keySpec instanceof RSAPrivateCrtKeySpec) {
return new NativeKey.RSAPrivateCrt(keySpec);
} else if (keySpec instanceof RSAPrivateKeySpec) {
return new NativeKey.RSAPrivate(keySpec);
} else {
throw new InvalidKeySpecException("Unsupported key spec");
}
}
@Override

View File

@ -43,9 +43,8 @@ import java.security.PublicKey;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.*;
import sun.nio.ch.DirectBuffer;
import java.nio.ByteBuffer;
@ -192,25 +191,31 @@ class NativeRSASignature extends SignatureSpi {
int newSigLength = sigLength;
// Need to check RSA key length whenever a new private key is set
if (privateKey != key) {
if (privateKey instanceof RSAPrivateCrtKey) {
RSAPrivateCrtKey rsaPrivKey = (RSAPrivateCrtKey) privateKey;
BigInteger mod = rsaPrivKey.getModulus();
newSigLength = checkRSAKeyLength(mod);
try {
if (!(privateKey instanceof RSAPrivateKey)) {
throw new InvalidKeyException("RSAPrivateKey required");
}
RSAPrivateKey rsaPrivKey = (RSAPrivateKey) privateKey;
BigInteger mod = rsaPrivKey.getModulus();
newSigLength = checkRSAKeyLength(mod);
BigInteger pe = rsaPrivKey.getPrivateExponent();
try {
if (rsaPrivKey instanceof RSAPrivateCrtKey) {
RSAPrivateCrtKey rsaPrivCrtKey = (RSAPrivateCrtKey) rsaPrivKey;
newKey = (NativeKey) keyFactory.engineGeneratePrivate
(new RSAPrivateCrtKeySpec(mod,
rsaPrivKey.getPublicExponent(),
rsaPrivKey.getPrivateExponent(),
rsaPrivKey.getPrimeP(),
rsaPrivKey.getPrimeQ(),
rsaPrivKey.getPrimeExponentP(),
rsaPrivKey.getPrimeExponentQ(),
rsaPrivKey.getCrtCoefficient()));
} catch (InvalidKeySpecException ikse) {
throw new InvalidKeyException(ikse);
rsaPrivCrtKey.getPublicExponent(),
pe,
rsaPrivCrtKey.getPrimeP(),
rsaPrivCrtKey.getPrimeQ(),
rsaPrivCrtKey.getPrimeExponentP(),
rsaPrivCrtKey.getPrimeExponentQ(),
rsaPrivCrtKey.getCrtCoefficient()));
} else {
newKey = (NativeKey) keyFactory.engineGeneratePrivate
(new RSAPrivateKeySpec(mod, pe));
}
} else {
throw new InvalidKeyException("RSAPrivateCrtKey required");
} catch (InvalidKeySpecException ikse) {
throw new InvalidKeyException(ikse);
}
}
init(true, newKey, newSigLength);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -696,6 +696,86 @@ JNIEXPORT void JNICALL Java_com_oracle_security_ucrypto_NativeKey_nativeFree
JavaCritical_com_oracle_security_ucrypto_NativeKey_nativeFree(id, numOfComponents);
}
/*
* Class: com_oracle_security_ucrypto_NativeKey_RSAPrivate
* Method: nativeInit
* Signature: ([B[B)J
*/
jlong JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit
(int modLen, jbyte* jMod, int privLen, jbyte* jPriv) {
unsigned char *mod, *priv;
crypto_object_attribute_t* pKey = NULL;
pKey = calloc(2, sizeof(crypto_object_attribute_t));
if (pKey == NULL) {
return 0L;
}
mod = priv = NULL;
mod = malloc(modLen);
priv = malloc(privLen);
if (mod == NULL || priv == NULL) {
free(pKey);
free(mod);
free(priv);
return 0L;
} else {
memcpy(mod, jMod, modLen);
memcpy(priv, jPriv, privLen);
}
// NOTE: numOfComponents should be 2
pKey[0].oa_type = SUN_CKA_MODULUS;
pKey[0].oa_value = (char*) mod;
pKey[0].oa_value_len = (size_t) modLen;
pKey[1].oa_type = SUN_CKA_PRIVATE_EXPONENT;
pKey[1].oa_value = (char*) priv;
pKey[1].oa_value_len = (size_t) privLen;
return (jlong) pKey;
}
JNIEXPORT jlong JNICALL
Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit
(JNIEnv *env, jclass jCls, jbyteArray jMod, jbyteArray jPriv) {
int modLen, privLen;
jbyte *bufMod, *bufPriv;
crypto_object_attribute_t* pKey = NULL;
bufMod = bufPriv = NULL;
modLen = (*env)->GetArrayLength(env, jMod);
bufMod = getBytes(env, jMod, 0, modLen);
if ((*env)->ExceptionCheck(env)) goto cleanup;
privLen = (*env)->GetArrayLength(env, jPriv);
bufPriv = getBytes(env, jPriv, 0, privLen);
if ((*env)->ExceptionCheck(env)) goto cleanup;
// proceed if no error; otherwise free allocated memory
pKey = calloc(2, sizeof(crypto_object_attribute_t));
if (pKey == NULL) {
throwOutOfMemoryError(env, NULL);
goto cleanup;
}
// NOTE: numOfComponents should be 2
pKey[0].oa_type = SUN_CKA_MODULUS;
pKey[0].oa_value = (char*) bufMod;
pKey[0].oa_value_len = (size_t) modLen;
pKey[1].oa_type = SUN_CKA_PRIVATE_EXPONENT;
pKey[1].oa_value = (char*) bufPriv;
pKey[1].oa_value_len = (size_t) privLen;
return (jlong) pKey;
cleanup:
free(bufMod);
free(bufPriv);
return 0L;
}
/*
* Class: com_oracle_security_ucrypto_NativeKey_RSAPrivateCrt
* Method: nativeInit

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,7 +23,7 @@
/**
* @test
* @bug 8029849
* @bug 8029849 8132082
* @summary Make sure signing via encrypt and verifying via decrypt are not
* supported by OracleUcrypto provider.
* @author Anthony Scarpino
@ -31,12 +31,10 @@
*/
import java.util.Random;
import java.security.KeyPairGenerator;
import java.security.KeyPair;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.RSAPrivateKeySpec;
import javax.crypto.Cipher;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
public class CipherSignNotSupported extends UcryptoTest {
@ -69,27 +67,43 @@ public class CipherSignNotSupported extends UcryptoTest {
c.init(Cipher.ENCRYPT_MODE, kp.getPublic());
ct = c.doFinal(pt);
// Decryption
c.init(Cipher.DECRYPT_MODE, kp.getPrivate());
c.doFinal(ct);
// Sign
try {
c.init(Cipher.ENCRYPT_MODE, kp.getPrivate());
ct = c.doFinal(pt);
throw new RuntimeException("Encrypt operation should have failed.");
} catch (InvalidKeyException e) {
if (e.getMessage().compareTo("RSAPublicKey required for " +
"encryption") != 0) {
System.out.println("Wrong exception thrown.");
throw e;
PrivateKey[] privKeys = new PrivateKey[2];
privKeys[0] = kp.getPrivate();
if (privKeys[0] instanceof RSAPrivateCrtKey) {
RSAPrivateCrtKey k = (RSAPrivateCrtKey) privKeys[0];
KeyFactory kf = KeyFactory.getInstance("RSA");
privKeys[1] = kf.generatePrivate
(new RSAPrivateKeySpec(k.getModulus(), k.getPrivateExponent()));
} else {
privKeys = new PrivateKey[] {privKeys[0]};
}
for (PrivateKey pk : privKeys) {
System.out.println("Testing " + pk);
c.init(Cipher.DECRYPT_MODE, pk);
c.doFinal(ct);
// Sign
try {
c.init(Cipher.ENCRYPT_MODE, pk);
ct = c.doFinal(pt);
throw new RuntimeException("Encrypt operation should have failed.");
} catch (InvalidKeyException e) {
if (e.getMessage().compareTo("RSAPublicKey required for " +
"encryption") != 0) {
System.out.println("Wrong exception thrown.");
throw e;
}
}
}
// Verify
try {
c.init(Cipher.DECRYPT_MODE, kp.getPublic());
c.doFinal(ct);
throw new RuntimeException("Decrypt operation should have failed.");
} catch (InvalidKeyException e) {
if (e.getMessage().compareTo("RSAPrivateCrtKey required for " +
if (e.getMessage().compareTo("RSAPrivateKey required for " +
"decryption") != 0) {
System.out.println("Wrong exception thrown.");
throw e;