8205445: Add RSASSA-PSS Signature support to SunMSCAPI
Reviewed-by: xuelei
This commit is contained in:
parent
5f55147841
commit
578576f523
@ -35,7 +35,7 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
|
|||||||
CFLAGS := $(CFLAGS_JDKLIB), \
|
CFLAGS := $(CFLAGS_JDKLIB), \
|
||||||
LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
|
LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
|
||||||
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||||
LIBS := crypt32.lib advapi32.lib, \
|
LIBS := crypt32.lib advapi32.lib ncrypt.lib, \
|
||||||
))
|
))
|
||||||
|
|
||||||
TARGETS += $(BUILD_LIBSUNMSCAPI)
|
TARGETS += $(BUILD_LIBSUNMSCAPI)
|
||||||
|
@ -132,7 +132,7 @@ public class RSAPSSSignature extends SignatureSpi {
|
|||||||
}
|
}
|
||||||
this.pubKey = (RSAPublicKey) isValid((RSAKey)publicKey);
|
this.pubKey = (RSAPublicKey) isValid((RSAKey)publicKey);
|
||||||
this.privKey = null;
|
this.privKey = null;
|
||||||
|
resetDigest();
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize for signing. See JCA doc
|
// initialize for signing. See JCA doc
|
||||||
@ -153,6 +153,7 @@ public class RSAPSSSignature extends SignatureSpi {
|
|||||||
this.pubKey = null;
|
this.pubKey = null;
|
||||||
this.random =
|
this.random =
|
||||||
(random == null? JCAUtil.getSecureRandom() : random);
|
(random == null? JCAUtil.getSecureRandom() : random);
|
||||||
|
resetDigest();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,6 +29,9 @@ import java.nio.ByteBuffer;
|
|||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.spec.AlgorithmParameterSpec;
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.security.spec.MGF1ParameterSpec;
|
||||||
|
import java.security.spec.PSSParameterSpec;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import sun.security.rsa.RSAKeyFactory;
|
import sun.security.rsa.RSAKeyFactory;
|
||||||
|
|
||||||
@ -45,6 +48,7 @@ import sun.security.rsa.RSAKeyFactory;
|
|||||||
* . "SHA512withRSA"
|
* . "SHA512withRSA"
|
||||||
* . "MD5withRSA"
|
* . "MD5withRSA"
|
||||||
* . "MD2withRSA"
|
* . "MD2withRSA"
|
||||||
|
* . "RSASSA-PSS"
|
||||||
*
|
*
|
||||||
* NOTE: RSA keys must be at least 512 bits long.
|
* NOTE: RSA keys must be at least 512 bits long.
|
||||||
*
|
*
|
||||||
@ -59,19 +63,19 @@ import sun.security.rsa.RSAKeyFactory;
|
|||||||
abstract class RSASignature extends java.security.SignatureSpi
|
abstract class RSASignature extends java.security.SignatureSpi
|
||||||
{
|
{
|
||||||
// message digest implementation we use
|
// message digest implementation we use
|
||||||
private final MessageDigest messageDigest;
|
protected MessageDigest messageDigest;
|
||||||
|
|
||||||
// message digest name
|
// message digest name
|
||||||
private String messageDigestAlgorithm;
|
private String messageDigestAlgorithm;
|
||||||
|
|
||||||
// flag indicating whether the digest has been reset
|
// flag indicating whether the digest has been reset
|
||||||
private boolean needsReset;
|
protected boolean needsReset;
|
||||||
|
|
||||||
// the signing key
|
// the signing key
|
||||||
private Key privateKey = null;
|
protected Key privateKey = null;
|
||||||
|
|
||||||
// the verification key
|
// the verification key
|
||||||
private Key publicKey = null;
|
protected Key publicKey = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new RSASignature. Used by Raw subclass.
|
* Constructs a new RSASignature. Used by Raw subclass.
|
||||||
@ -222,6 +226,254 @@ abstract class RSASignature extends java.security.SignatureSpi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final class PSS extends RSASignature {
|
||||||
|
|
||||||
|
private PSSParameterSpec pssParams = null;
|
||||||
|
|
||||||
|
// Workaround: Cannot import raw public key to CNG. This signature
|
||||||
|
// will be used for verification if key is not from MSCAPI.
|
||||||
|
private Signature fallbackSignature;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void engineInitSign(PrivateKey key) throws InvalidKeyException {
|
||||||
|
super.engineInitSign(key);
|
||||||
|
fallbackSignature = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void engineInitVerify(PublicKey key) throws InvalidKeyException {
|
||||||
|
// This signature accepts only RSAPublicKey
|
||||||
|
if ((key instanceof java.security.interfaces.RSAPublicKey) == false) {
|
||||||
|
throw new InvalidKeyException("Key type not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.privateKey = null;
|
||||||
|
|
||||||
|
if (key instanceof sun.security.mscapi.RSAPublicKey) {
|
||||||
|
fallbackSignature = null;
|
||||||
|
publicKey = (sun.security.mscapi.RSAPublicKey) key;
|
||||||
|
} else {
|
||||||
|
if (fallbackSignature == null) {
|
||||||
|
try {
|
||||||
|
fallbackSignature = Signature.getInstance(
|
||||||
|
"RSASSA-PSS", "SunRsaSign");
|
||||||
|
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
|
||||||
|
throw new InvalidKeyException("Invalid key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fallbackSignature.initVerify(key);
|
||||||
|
if (pssParams != null) {
|
||||||
|
try {
|
||||||
|
fallbackSignature.setParameter(pssParams);
|
||||||
|
} catch (InvalidAlgorithmParameterException e) {
|
||||||
|
throw new InvalidKeyException("Invalid params", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
publicKey = null;
|
||||||
|
}
|
||||||
|
resetDigest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void engineUpdate(byte b) throws SignatureException {
|
||||||
|
ensureInit();
|
||||||
|
if (fallbackSignature != null) {
|
||||||
|
fallbackSignature.update(b);
|
||||||
|
} else {
|
||||||
|
messageDigest.update(b);
|
||||||
|
}
|
||||||
|
needsReset = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
|
||||||
|
ensureInit();
|
||||||
|
if (fallbackSignature != null) {
|
||||||
|
fallbackSignature.update(b, off, len);
|
||||||
|
} else {
|
||||||
|
messageDigest.update(b, off, len);
|
||||||
|
}
|
||||||
|
needsReset = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void engineUpdate(ByteBuffer input) {
|
||||||
|
try {
|
||||||
|
ensureInit();
|
||||||
|
} catch (SignatureException se) {
|
||||||
|
// hack for working around API bug
|
||||||
|
throw new RuntimeException(se.getMessage());
|
||||||
|
}
|
||||||
|
if (fallbackSignature != null) {
|
||||||
|
try {
|
||||||
|
fallbackSignature.update(input);
|
||||||
|
} catch (SignatureException se) {
|
||||||
|
// hack for working around API bug
|
||||||
|
throw new RuntimeException(se.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
messageDigest.update(input);
|
||||||
|
}
|
||||||
|
needsReset = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected byte[] engineSign() throws SignatureException {
|
||||||
|
ensureInit();
|
||||||
|
byte[] hash = getDigestValue();
|
||||||
|
return signPssHash(hash, hash.length,
|
||||||
|
pssParams.getSaltLength(),
|
||||||
|
((MGF1ParameterSpec)
|
||||||
|
pssParams.getMGFParameters()).getDigestAlgorithm(),
|
||||||
|
privateKey.getHCryptProvider(), privateKey.getHCryptKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
|
||||||
|
ensureInit();
|
||||||
|
if (fallbackSignature != null) {
|
||||||
|
needsReset = false;
|
||||||
|
return fallbackSignature.verify(sigBytes);
|
||||||
|
} else {
|
||||||
|
byte[] hash = getDigestValue();
|
||||||
|
return verifyPssSignedHash(
|
||||||
|
hash, hash.length,
|
||||||
|
sigBytes, sigBytes.length,
|
||||||
|
pssParams.getSaltLength(),
|
||||||
|
((MGF1ParameterSpec)
|
||||||
|
pssParams.getMGFParameters()).getDigestAlgorithm(),
|
||||||
|
publicKey.getHCryptProvider(),
|
||||||
|
publicKey.getHCryptKey()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void engineSetParameter(AlgorithmParameterSpec params)
|
||||||
|
throws InvalidAlgorithmParameterException {
|
||||||
|
if (needsReset) {
|
||||||
|
throw new ProviderException
|
||||||
|
("Cannot set parameters during operations");
|
||||||
|
}
|
||||||
|
this.pssParams = validateSigParams(params);
|
||||||
|
if (fallbackSignature != null) {
|
||||||
|
fallbackSignature.setParameter(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AlgorithmParameters engineGetParameters() {
|
||||||
|
if (this.pssParams == null) {
|
||||||
|
throw new ProviderException("Missing required PSS parameters");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
AlgorithmParameters ap =
|
||||||
|
AlgorithmParameters.getInstance("RSASSA-PSS");
|
||||||
|
ap.init(this.pssParams);
|
||||||
|
return ap;
|
||||||
|
} catch (GeneralSecurityException gse) {
|
||||||
|
throw new ProviderException(gse.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureInit() throws SignatureException {
|
||||||
|
if (this.privateKey == null && this.publicKey == null
|
||||||
|
&& fallbackSignature == null) {
|
||||||
|
throw new SignatureException("Missing key");
|
||||||
|
}
|
||||||
|
if (this.pssParams == null) {
|
||||||
|
// Parameters are required for signature verification
|
||||||
|
throw new SignatureException
|
||||||
|
("Parameters required for RSASSA-PSS signatures");
|
||||||
|
}
|
||||||
|
if (fallbackSignature == null && messageDigest == null) {
|
||||||
|
// This could happen if initVerify(softKey), setParameter(),
|
||||||
|
// and initSign() were called. No messageDigest. Create it.
|
||||||
|
try {
|
||||||
|
messageDigest = MessageDigest
|
||||||
|
.getInstance(pssParams.getDigestAlgorithm());
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new SignatureException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the specified Signature PSS parameters.
|
||||||
|
*/
|
||||||
|
private PSSParameterSpec validateSigParams(AlgorithmParameterSpec p)
|
||||||
|
throws InvalidAlgorithmParameterException {
|
||||||
|
|
||||||
|
if (p == null) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Parameters cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(p instanceof PSSParameterSpec)) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("parameters must be type PSSParameterSpec");
|
||||||
|
}
|
||||||
|
|
||||||
|
// no need to validate again if same as current signature parameters
|
||||||
|
PSSParameterSpec params = (PSSParameterSpec) p;
|
||||||
|
if (params == this.pssParams) return params;
|
||||||
|
|
||||||
|
// now sanity check the parameter values
|
||||||
|
if (!(params.getMGFAlgorithm().equalsIgnoreCase("MGF1"))) {
|
||||||
|
throw new InvalidAlgorithmParameterException("Only supports MGF1");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Only supports TrailerFieldBC(1)");
|
||||||
|
}
|
||||||
|
|
||||||
|
AlgorithmParameterSpec algSpec = params.getMGFParameters();
|
||||||
|
if (!(algSpec instanceof MGF1ParameterSpec)) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Only support MGF1ParameterSpec");
|
||||||
|
}
|
||||||
|
|
||||||
|
MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec)algSpec;
|
||||||
|
|
||||||
|
String msgHashAlg = params.getDigestAlgorithm()
|
||||||
|
.toLowerCase(Locale.ROOT).replaceAll("-", "");
|
||||||
|
if (msgHashAlg.equals("sha")) {
|
||||||
|
msgHashAlg = "sha1";
|
||||||
|
}
|
||||||
|
String mgf1HashAlg = mgfSpec.getDigestAlgorithm()
|
||||||
|
.toLowerCase(Locale.ROOT).replaceAll("-", "");
|
||||||
|
if (mgf1HashAlg.equals("sha")) {
|
||||||
|
mgf1HashAlg = "sha1";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mgf1HashAlg.equals(msgHashAlg)) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("MGF1 hash must be the same as message hash");
|
||||||
|
}
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign hash using CNG API with HCRYPTKEY. Used by RSASSA-PSS.
|
||||||
|
*/
|
||||||
|
private native static byte[] signPssHash(byte[] hash,
|
||||||
|
int hashSize, int saltLength, String hashAlgorithm,
|
||||||
|
long hCryptProv, long nCryptKey)
|
||||||
|
throws SignatureException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify a signed hash using CNG API with HCRYPTKEY. Used by RSASSA-PSS.
|
||||||
|
* This method is not used now. See {@link #fallbackSignature}.
|
||||||
|
*/
|
||||||
|
private native static boolean verifyPssSignedHash(byte[] hash, int hashSize,
|
||||||
|
byte[] signature, int signatureSize,
|
||||||
|
int saltLength, String hashAlgorithm,
|
||||||
|
long hCryptProv, long hKey) throws SignatureException;
|
||||||
|
}
|
||||||
|
|
||||||
// initialize for signing. See JCA doc
|
// initialize for signing. See JCA doc
|
||||||
@Override
|
@Override
|
||||||
protected void engineInitVerify(PublicKey key)
|
protected void engineInitVerify(PublicKey key)
|
||||||
@ -298,7 +550,9 @@ abstract class RSASignature extends java.security.SignatureSpi
|
|||||||
*/
|
*/
|
||||||
protected void resetDigest() {
|
protected void resetDigest() {
|
||||||
if (needsReset) {
|
if (needsReset) {
|
||||||
messageDigest.reset();
|
if (messageDigest != null) {
|
||||||
|
messageDigest.reset();
|
||||||
|
}
|
||||||
needsReset = false;
|
needsReset = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2018, 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
|
||||||
@ -105,6 +105,8 @@ public final class SunMSCAPI extends Provider {
|
|||||||
return new RSASignature.MD5();
|
return new RSASignature.MD5();
|
||||||
} else if (algo.equals("MD2withRSA")) {
|
} else if (algo.equals("MD2withRSA")) {
|
||||||
return new RSASignature.MD2();
|
return new RSASignature.MD2();
|
||||||
|
} else if (algo.equals("RSASSA-PSS")) {
|
||||||
|
return new RSASignature.PSS();
|
||||||
}
|
}
|
||||||
} else if (type.equals("KeyPairGenerator")) {
|
} else if (type.equals("KeyPairGenerator")) {
|
||||||
if (algo.equals("RSA")) {
|
if (algo.equals("RSA")) {
|
||||||
@ -177,6 +179,10 @@ public final class SunMSCAPI extends Provider {
|
|||||||
"SHA512withRSA", "sun.security.mscapi.RSASignature$SHA512",
|
"SHA512withRSA", "sun.security.mscapi.RSASignature$SHA512",
|
||||||
new String[] { "1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13" },
|
new String[] { "1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13" },
|
||||||
attrs));
|
attrs));
|
||||||
|
putService(new ProviderService(p, "Signature",
|
||||||
|
"RSASSA-PSS", "sun.security.mscapi.RSASignature$PSS",
|
||||||
|
new String[] { "1.2.840.113549.1.1.10", "OID.1.2.840.113549.1.1.10" },
|
||||||
|
attrs));
|
||||||
putService(new ProviderService(p, "Signature",
|
putService(new ProviderService(p, "Signature",
|
||||||
"MD5withRSA", "sun.security.mscapi.RSASignature$MD5",
|
"MD5withRSA", "sun.security.mscapi.RSASignature$MD5",
|
||||||
null, attrs));
|
null, attrs));
|
||||||
|
@ -57,6 +57,18 @@
|
|||||||
#define SIGNATURE_EXCEPTION "java/security/SignatureException"
|
#define SIGNATURE_EXCEPTION "java/security/SignatureException"
|
||||||
#define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError"
|
#define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError"
|
||||||
|
|
||||||
|
#define SS_CHECK(Status) \
|
||||||
|
if (Status != ERROR_SUCCESS) { \
|
||||||
|
ThrowException(env, SIGNATURE_EXCEPTION, Status); \
|
||||||
|
__leave; \
|
||||||
|
}
|
||||||
|
|
||||||
|
//#define PP(fmt, ...) \
|
||||||
|
// fprintf(stdout, "SSPI (%ld): ", __LINE__); \
|
||||||
|
// fprintf(stdout, fmt, ##__VA_ARGS__); \
|
||||||
|
// fprintf(stdout, "\n"); \
|
||||||
|
// fflush(stdout)
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -64,6 +76,18 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
DEF_STATIC_JNI_OnLoad
|
DEF_STATIC_JNI_OnLoad
|
||||||
|
|
||||||
|
//void dump(LPSTR title, PBYTE data, DWORD len)
|
||||||
|
//{
|
||||||
|
// printf("==== %s ====\n", title);
|
||||||
|
// for (DWORD i = 0; i < len; i++) {
|
||||||
|
// if (i != 0 && i % 16 == 0) {
|
||||||
|
// printf("\n");
|
||||||
|
// }
|
||||||
|
// printf("%02X ", *(data + i) & 0xff);
|
||||||
|
// }
|
||||||
|
// printf("\n");
|
||||||
|
//}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Throws an arbitrary Java exception with the given message.
|
* Throws an arbitrary Java exception with the given message.
|
||||||
*/
|
*/
|
||||||
@ -146,6 +170,37 @@ ALG_ID MapHashAlgorithm(JNIEnv *env, jstring jHashAlgorithm) {
|
|||||||
return algId;
|
return algId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maps the name of a hash algorithm to a CNG Algorithm Identifier.
|
||||||
|
*/
|
||||||
|
LPCWSTR MapHashIdentifier(JNIEnv *env, jstring jHashAlgorithm) {
|
||||||
|
|
||||||
|
const char* pszHashAlgorithm = NULL;
|
||||||
|
LPCWSTR id = NULL;
|
||||||
|
|
||||||
|
if ((pszHashAlgorithm = env->GetStringUTFChars(jHashAlgorithm, NULL))
|
||||||
|
== NULL) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((strcmp("SHA", pszHashAlgorithm) == 0) ||
|
||||||
|
(strcmp("SHA1", pszHashAlgorithm) == 0) ||
|
||||||
|
(strcmp("SHA-1", pszHashAlgorithm) == 0)) {
|
||||||
|
|
||||||
|
id = BCRYPT_SHA1_ALGORITHM;
|
||||||
|
} else if (strcmp("SHA-256", pszHashAlgorithm) == 0) {
|
||||||
|
id = BCRYPT_SHA256_ALGORITHM;
|
||||||
|
} else if (strcmp("SHA-384", pszHashAlgorithm) == 0) {
|
||||||
|
id = BCRYPT_SHA384_ALGORITHM;
|
||||||
|
} else if (strcmp("SHA-512", pszHashAlgorithm) == 0) {
|
||||||
|
id = BCRYPT_SHA512_ALGORITHM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pszHashAlgorithm)
|
||||||
|
env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns a certificate chain context given a certificate context and key
|
* Returns a certificate chain context given a certificate context and key
|
||||||
@ -561,7 +616,6 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_Key_cleanUp
|
|||||||
::CryptReleaseContext((HCRYPTPROV) hCryptProv, NULL);
|
::CryptReleaseContext((HCRYPTPROV) hCryptProv, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: sun_security_mscapi_RSASignature
|
* Class: sun_security_mscapi_RSASignature
|
||||||
* Method: signHash
|
* Method: signHash
|
||||||
@ -692,6 +746,94 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSASignature_signHash
|
|||||||
return jSignedHash;
|
return jSignedHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: sun_security_mscapi_RSASignature_PSS
|
||||||
|
* Method: signPssHash
|
||||||
|
* Signature: ([BIILjava/lang/String;JJ)[B
|
||||||
|
*/
|
||||||
|
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSASignature_00024PSS_signPssHash
|
||||||
|
(JNIEnv *env, jclass clazz, jbyteArray jHash,
|
||||||
|
jint jHashSize, jint saltLen, jstring jHashAlgorithm, jlong hCryptProv,
|
||||||
|
jlong hCryptKey)
|
||||||
|
{
|
||||||
|
jbyteArray jSignedHash = NULL;
|
||||||
|
|
||||||
|
jbyte* pHashBuffer = NULL;
|
||||||
|
jbyte* pSignedHashBuffer = NULL;
|
||||||
|
NCRYPT_KEY_HANDLE hk = NULL;
|
||||||
|
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
SS_CHECK(::NCryptTranslateHandle(
|
||||||
|
NULL,
|
||||||
|
&hk,
|
||||||
|
hCryptProv,
|
||||||
|
hCryptKey,
|
||||||
|
NULL,
|
||||||
|
0));
|
||||||
|
|
||||||
|
// Copy hash from Java to native buffer
|
||||||
|
pHashBuffer = new (env) jbyte[jHashSize];
|
||||||
|
if (pHashBuffer == NULL) {
|
||||||
|
__leave;
|
||||||
|
}
|
||||||
|
env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
|
||||||
|
|
||||||
|
BCRYPT_PSS_PADDING_INFO pssInfo;
|
||||||
|
pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
|
||||||
|
pssInfo.cbSalt = saltLen;
|
||||||
|
|
||||||
|
if (pssInfo.pszAlgId == NULL) {
|
||||||
|
ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
|
||||||
|
"Unrecognised hash algorithm");
|
||||||
|
__leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD dwBufLen = 0;
|
||||||
|
SS_CHECK(::NCryptSignHash(
|
||||||
|
hk,
|
||||||
|
&pssInfo,
|
||||||
|
(BYTE*)pHashBuffer, jHashSize,
|
||||||
|
NULL, 0, &dwBufLen,
|
||||||
|
BCRYPT_PAD_PSS
|
||||||
|
));
|
||||||
|
|
||||||
|
pSignedHashBuffer = new (env) jbyte[dwBufLen];
|
||||||
|
if (pSignedHashBuffer == NULL) {
|
||||||
|
__leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
SS_CHECK(::NCryptSignHash(
|
||||||
|
hk,
|
||||||
|
&pssInfo,
|
||||||
|
(BYTE*)pHashBuffer, jHashSize,
|
||||||
|
(BYTE*)pSignedHashBuffer, dwBufLen, &dwBufLen,
|
||||||
|
BCRYPT_PAD_PSS
|
||||||
|
));
|
||||||
|
|
||||||
|
// Create new byte array
|
||||||
|
jbyteArray temp = env->NewByteArray(dwBufLen);
|
||||||
|
|
||||||
|
// Copy data from native buffer
|
||||||
|
env->SetByteArrayRegion(temp, 0, dwBufLen, pSignedHashBuffer);
|
||||||
|
|
||||||
|
jSignedHash = temp;
|
||||||
|
}
|
||||||
|
__finally
|
||||||
|
{
|
||||||
|
if (pSignedHashBuffer)
|
||||||
|
delete [] pSignedHashBuffer;
|
||||||
|
|
||||||
|
if (pHashBuffer)
|
||||||
|
delete [] pHashBuffer;
|
||||||
|
|
||||||
|
if (hk != NULL)
|
||||||
|
::NCryptFreeObject(hk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return jSignedHash;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: sun_security_mscapi_RSASignature
|
* Class: sun_security_mscapi_RSASignature
|
||||||
* Method: verifySignedHash
|
* Method: verifySignedHash
|
||||||
@ -797,6 +939,85 @@ JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_RSASignature_verifySignedHas
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: sun_security_mscapi_RSASignature_PSS
|
||||||
|
* Method: verifyPssSignedHash
|
||||||
|
* Signature: ([BI[BIILjava/lang/String;JJ)Z
|
||||||
|
*/
|
||||||
|
JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_RSASignature_00024PSS_verifyPssSignedHash
|
||||||
|
(JNIEnv *env, jclass clazz,
|
||||||
|
jbyteArray jHash, jint jHashSize,
|
||||||
|
jbyteArray jSignedHash, jint jSignedHashSize,
|
||||||
|
jint saltLen, jstring jHashAlgorithm,
|
||||||
|
jlong hCryptProv, jlong hKey)
|
||||||
|
{
|
||||||
|
jbyte* pHashBuffer = NULL;
|
||||||
|
jbyte* pSignedHashBuffer = NULL;
|
||||||
|
jboolean result = JNI_FALSE;
|
||||||
|
NCRYPT_KEY_HANDLE hk = NULL;
|
||||||
|
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
SS_CHECK(::NCryptTranslateHandle(
|
||||||
|
NULL,
|
||||||
|
&hk,
|
||||||
|
hCryptProv,
|
||||||
|
hKey,
|
||||||
|
NULL,
|
||||||
|
0));
|
||||||
|
|
||||||
|
// Copy hash and signedHash from Java to native buffer
|
||||||
|
pHashBuffer = new (env) jbyte[jHashSize];
|
||||||
|
if (pHashBuffer == NULL) {
|
||||||
|
__leave;
|
||||||
|
}
|
||||||
|
env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
|
||||||
|
|
||||||
|
pSignedHashBuffer = new (env) jbyte[jSignedHashSize];
|
||||||
|
if (pSignedHashBuffer == NULL) {
|
||||||
|
__leave;
|
||||||
|
}
|
||||||
|
env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,
|
||||||
|
pSignedHashBuffer);
|
||||||
|
|
||||||
|
BCRYPT_PSS_PADDING_INFO pssInfo;
|
||||||
|
pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
|
||||||
|
pssInfo.cbSalt = saltLen;
|
||||||
|
|
||||||
|
if (pssInfo.pszAlgId == NULL) {
|
||||||
|
ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
|
||||||
|
"Unrecognised hash algorithm");
|
||||||
|
__leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For RSA, the hash encryption algorithm is normally the same as the
|
||||||
|
// public key algorithm, so AT_SIGNATURE is used.
|
||||||
|
|
||||||
|
// Verify the signature
|
||||||
|
if (::NCryptVerifySignature(hk, &pssInfo,
|
||||||
|
(BYTE *) pHashBuffer, jHashSize,
|
||||||
|
(BYTE *) pSignedHashBuffer, jSignedHashSize,
|
||||||
|
NCRYPT_PAD_PSS_FLAG) == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
result = JNI_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__finally
|
||||||
|
{
|
||||||
|
if (pSignedHashBuffer)
|
||||||
|
delete [] pSignedHashBuffer;
|
||||||
|
|
||||||
|
if (pHashBuffer)
|
||||||
|
delete [] pHashBuffer;
|
||||||
|
|
||||||
|
if (hk != NULL)
|
||||||
|
::NCryptFreeObject(hk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: sun_security_mscapi_RSAKeyPairGenerator
|
* Class: sun_security_mscapi_RSAKeyPairGenerator
|
||||||
* Method: generateRSAKeyPair
|
* Method: generateRSAKeyPair
|
||||||
|
171
test/jdk/sun/security/mscapi/InteropWithSunRsaSign.java
Normal file
171
test/jdk/sun/security/mscapi/InteropWithSunRsaSign.java
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 8205445
|
||||||
|
* @summary Interop test between SunMSCAPI and SunRsaSign on RSASSA-PSS
|
||||||
|
* @requires os.family == "windows"
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.KeyPairGenerator;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.security.Signature;
|
||||||
|
import java.security.spec.MGF1ParameterSpec;
|
||||||
|
import java.security.spec.PSSParameterSpec;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class InteropWithSunRsaSign {
|
||||||
|
|
||||||
|
private static final SecureRandom NOT_SECURE_RANDOM = new SecureRandom() {
|
||||||
|
Random r = new Random();
|
||||||
|
@Override
|
||||||
|
public void nextBytes(byte[] bytes) {
|
||||||
|
r.nextBytes(bytes);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static boolean allResult = true;
|
||||||
|
private static byte[] msg = "hello".getBytes();
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
matrix(new PSSParameterSpec(
|
||||||
|
"SHA-1",
|
||||||
|
"MGF1",
|
||||||
|
MGF1ParameterSpec.SHA1,
|
||||||
|
20,
|
||||||
|
PSSParameterSpec.TRAILER_FIELD_BC));
|
||||||
|
|
||||||
|
matrix(new PSSParameterSpec(
|
||||||
|
"SHA-256",
|
||||||
|
"MGF1",
|
||||||
|
MGF1ParameterSpec.SHA256,
|
||||||
|
32,
|
||||||
|
PSSParameterSpec.TRAILER_FIELD_BC));
|
||||||
|
|
||||||
|
matrix(new PSSParameterSpec(
|
||||||
|
"SHA-384",
|
||||||
|
"MGF1",
|
||||||
|
MGF1ParameterSpec.SHA384,
|
||||||
|
48,
|
||||||
|
PSSParameterSpec.TRAILER_FIELD_BC));
|
||||||
|
|
||||||
|
matrix(new PSSParameterSpec(
|
||||||
|
"SHA-512",
|
||||||
|
"MGF1",
|
||||||
|
MGF1ParameterSpec.SHA512,
|
||||||
|
64,
|
||||||
|
PSSParameterSpec.TRAILER_FIELD_BC));
|
||||||
|
|
||||||
|
// non-typical salt length
|
||||||
|
matrix(new PSSParameterSpec(
|
||||||
|
"SHA-1",
|
||||||
|
"MGF1",
|
||||||
|
MGF1ParameterSpec.SHA1,
|
||||||
|
17,
|
||||||
|
PSSParameterSpec.TRAILER_FIELD_BC));
|
||||||
|
|
||||||
|
if (!allResult) {
|
||||||
|
throw new Exception("Failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void matrix(PSSParameterSpec pss) throws Exception {
|
||||||
|
|
||||||
|
System.out.printf("\n%10s%20s%20s%20s %s\n", pss.getDigestAlgorithm(),
|
||||||
|
"KeyPairGenerator", "signer", "verifier", "result");
|
||||||
|
System.out.printf("%10s%20s%20s%20s %s\n",
|
||||||
|
"-------", "----------------", "------", "--------", "------");
|
||||||
|
|
||||||
|
// KeyPairGenerator chooses SPI when getInstance() is called.
|
||||||
|
String[] provsForKPG = {"SunRsaSign", "SunMSCAPI"};
|
||||||
|
|
||||||
|
// "-" means no preferred provider. In this case, SPI is chosen
|
||||||
|
// when initSign/initVerify is called. Worth testing.
|
||||||
|
String[] provsForSignature = {"SunRsaSign", "SunMSCAPI", "-"};
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
for (String pg : provsForKPG) {
|
||||||
|
for (String ps : provsForSignature) {
|
||||||
|
for (String pv : provsForSignature) {
|
||||||
|
System.out.printf("%10d%20s%20s%20s ", ++pos, pg, ps, pv);
|
||||||
|
try {
|
||||||
|
boolean result = test(pg, ps, pv, pss);
|
||||||
|
System.out.println(result);
|
||||||
|
if (!result) {
|
||||||
|
allResult = false;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (pg.equals("-") || pg.equals(ps)) {
|
||||||
|
// When Signature provider is automatically
|
||||||
|
// chosen or the same with KeyPairGenerator,
|
||||||
|
// this is an error.
|
||||||
|
allResult = false;
|
||||||
|
System.out.println("X " + e.getMessage());
|
||||||
|
} else {
|
||||||
|
// Known restriction: SunRsaSign and SunMSCAPI can't
|
||||||
|
// use each other's private key for signing.
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean test(String pg, String ps, String pv, PSSParameterSpec pss)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
KeyPairGenerator kpg = pg.length() == 1
|
||||||
|
? KeyPairGenerator.getInstance("RSA")
|
||||||
|
:KeyPairGenerator.getInstance("RSA", pg);
|
||||||
|
kpg.initialize(
|
||||||
|
pss.getDigestAlgorithm().equals("SHA-512") ? 2048: 1024,
|
||||||
|
NOT_SECURE_RANDOM);
|
||||||
|
KeyPair kp = kpg.generateKeyPair();
|
||||||
|
PrivateKey pr = kp.getPrivate();
|
||||||
|
PublicKey pu = kp.getPublic();
|
||||||
|
|
||||||
|
Signature s = ps.length() == 1
|
||||||
|
? Signature.getInstance("RSASSA-PSS")
|
||||||
|
: Signature.getInstance("RSASSA-PSS", ps);
|
||||||
|
s.initSign(pr);
|
||||||
|
s.setParameter(pss);
|
||||||
|
s.update(msg);
|
||||||
|
byte[] sig = s.sign();
|
||||||
|
|
||||||
|
Signature s2 = pv.length() == 1
|
||||||
|
? Signature.getInstance("RSASSA-PSS")
|
||||||
|
: Signature.getInstance("RSASSA-PSS", pv);
|
||||||
|
s2.initVerify(pu);
|
||||||
|
s2.setParameter(pss);
|
||||||
|
s2.update(msg);
|
||||||
|
|
||||||
|
return s2.verify(sig);
|
||||||
|
}
|
||||||
|
}
|
69
test/jdk/sun/security/rsa/pss/InitAgain.java
Normal file
69
test/jdk/sun/security/rsa/pss/InitAgain.java
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 8205445
|
||||||
|
* @summary Make sure old state is cleared when init is called again
|
||||||
|
*/
|
||||||
|
public class InitAgain {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
byte[] msg = "hello".getBytes();
|
||||||
|
|
||||||
|
Signature s1 = Signature.getInstance("RSASSA-PSS");
|
||||||
|
Signature s2 = Signature.getInstance("RSASSA-PSS");
|
||||||
|
|
||||||
|
s1.setParameter(PSSParameterSpec.DEFAULT);
|
||||||
|
s2.setParameter(PSSParameterSpec.DEFAULT);
|
||||||
|
|
||||||
|
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
|
||||||
|
kpg.initialize(1024);
|
||||||
|
KeyPair kp = kpg.generateKeyPair();
|
||||||
|
|
||||||
|
s1.initSign(kp.getPrivate());
|
||||||
|
s1.update(msg);
|
||||||
|
s1.initSign(kp.getPrivate());
|
||||||
|
s1.update(msg);
|
||||||
|
// Data digested in s1:
|
||||||
|
// Before this fix, msg | msg
|
||||||
|
// After this fix, msg
|
||||||
|
|
||||||
|
s2.initVerify(kp.getPublic());
|
||||||
|
s2.update(msg);
|
||||||
|
s2.initVerify(kp.getPublic());
|
||||||
|
s2.update(msg);
|
||||||
|
s2.initVerify(kp.getPublic());
|
||||||
|
s2.update(msg);
|
||||||
|
// Data digested in s2:
|
||||||
|
// Before this fix, msg | msg | msg
|
||||||
|
// After this fix, msg
|
||||||
|
|
||||||
|
if (!s2.verify(s1.sign())) {
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user