--- a/src/java.base/share/classes/sun/security/util/ECUtil.java Thu Dec 13 17:28:19 2018 +0800
+++ b/src/java.base/share/classes/sun/security/util/ECUtil.java Thu Dec 13 17:28:30 2018 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -26,17 +26,11 @@
package sun.security.util;
import java.io.IOException;
-
import java.math.BigInteger;
-
import java.security.*;
-
import java.security.interfaces.*;
-
import java.security.spec.*;
-
import java.util.Arrays;
-
import sun.security.x509.X509Key;
public class ECUtil {
@@ -227,5 +221,64 @@
return nameSpec.getName();
}
+ // Convert the concatenation R and S in into their DER encoding
+ public static byte[] encodeSignature(byte[] signature) throws SignatureException {
+
+ try {
+
+ int n = signature.length >> 1;
+ byte[] bytes = new byte[n];
+ System.arraycopy(signature, 0, bytes, 0, n);
+ BigInteger r = new BigInteger(1, bytes);
+ System.arraycopy(signature, n, bytes, 0, n);
+ BigInteger s = new BigInteger(1, bytes);
+
+ DerOutputStream out = new DerOutputStream(signature.length + 10);
+ out.putInteger(r);
+ out.putInteger(s);
+ DerValue result =
+ new DerValue(DerValue.tag_Sequence, out.toByteArray());
+
+ return result.toByteArray();
+
+ } catch (Exception e) {
+ throw new SignatureException("Could not encode signature", e);
+ }
+ }
+
+ // Convert the DER encoding of R and S into a concatenation of R and S
+ public static byte[] decodeSignature(byte[] sig) throws SignatureException {
+
+ try {
+ // Enforce strict DER checking for signatures
+ DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
+ DerValue[] values = in.getSequence(2);
+
+ // check number of components in the read sequence
+ // and trailing data
+ if ((values.length != 2) || (in.available() != 0)) {
+ throw new IOException("Invalid encoding for signature");
+ }
+
+ BigInteger r = values[0].getPositiveBigInteger();
+ BigInteger s = values[1].getPositiveBigInteger();
+
+ // trim leading zeroes
+ byte[] rBytes = trimZeroes(r.toByteArray());
+ byte[] sBytes = trimZeroes(s.toByteArray());
+ int k = Math.max(rBytes.length, sBytes.length);
+ // r and s each occupy half the array
+ byte[] result = new byte[k << 1];
+ System.arraycopy(rBytes, 0, result, k - rBytes.length,
+ rBytes.length);
+ System.arraycopy(sBytes, 0, result, result.length - sBytes.length,
+ sBytes.length);
+ return result;
+
+ } catch (Exception e) {
+ throw new SignatureException("Invalid encoding for signature", e);
+ }
+ }
+
private ECUtil() {}
}
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java Thu Dec 13 17:28:19 2018 +0800
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java Thu Dec 13 17:28:30 2018 +0800
@@ -25,9 +25,7 @@
package sun.security.ec;
-import java.io.IOException;
import java.nio.ByteBuffer;
-import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.*;
@@ -453,7 +451,7 @@
if (p1363Format) {
return sig;
} else {
- return encodeSignature(sig);
+ return ECUtil.encodeSignature(sig);
}
}
@@ -476,7 +474,7 @@
if (p1363Format) {
sig = signature;
} else {
- sig = decodeSignature(signature);
+ sig = ECUtil.decodeSignature(signature);
}
try {
@@ -515,79 +513,6 @@
return null;
}
- // Convert the concatenation of R and S into their DER encoding
- private byte[] encodeSignature(byte[] signature) throws SignatureException {
-
- try {
-
- int n = signature.length >> 1;
- byte[] bytes = new byte[n];
- System.arraycopy(signature, 0, bytes, 0, n);
- BigInteger r = new BigInteger(1, bytes);
- System.arraycopy(signature, n, bytes, 0, n);
- BigInteger s = new BigInteger(1, bytes);
-
- DerOutputStream out = new DerOutputStream(signature.length + 10);
- out.putInteger(r);
- out.putInteger(s);
- DerValue result =
- new DerValue(DerValue.tag_Sequence, out.toByteArray());
-
- return result.toByteArray();
-
- } catch (Exception e) {
- throw new SignatureException("Could not encode signature", e);
- }
- }
-
- // Convert the DER encoding of R and S into a concatenation of R and S
- private byte[] decodeSignature(byte[] sig) throws SignatureException {
-
- try {
- // Enforce strict DER checking for signatures
- DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
- DerValue[] values = in.getSequence(2);
-
- // check number of components in the read sequence
- // and trailing data
- if ((values.length != 2) || (in.available() != 0)) {
- throw new IOException("Invalid encoding for signature");
- }
-
- BigInteger r = values[0].getPositiveBigInteger();
- BigInteger s = values[1].getPositiveBigInteger();
-
- // trim leading zeroes
- byte[] rBytes = trimZeroes(r.toByteArray());
- byte[] sBytes = trimZeroes(s.toByteArray());
- int k = Math.max(rBytes.length, sBytes.length);
- // r and s each occupy half the array
- byte[] result = new byte[k << 1];
- System.arraycopy(rBytes, 0, result, k - rBytes.length,
- rBytes.length);
- System.arraycopy(sBytes, 0, result, result.length - sBytes.length,
- sBytes.length);
- return result;
-
- } catch (Exception e) {
- throw new SignatureException("Invalid encoding for signature", e);
- }
- }
-
- // trim leading (most significant) zeroes from the result
- private static byte[] trimZeroes(byte[] b) {
- int i = 0;
- while ((i < b.length - 1) && (b[i] == 0)) {
- i++;
- }
- if (i == 0) {
- return b;
- }
- byte[] t = new byte[b.length - i];
- System.arraycopy(b, i, t, 0, t.length);
- return t;
- }
-
/**
* Signs the digest using the private key.
*
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKey.java Thu Dec 13 17:28:19 2018 +0800
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKey.java Thu Dec 13 17:28:30 2018 +0800
@@ -25,9 +25,13 @@
package sun.security.mscapi;
+import sun.security.util.KeyUtil;
import sun.security.util.Length;
+import java.math.BigInteger;
import java.security.Key;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
/**
* The handle for a key using the Microsoft Crypto API.
@@ -100,4 +104,51 @@
protected native static String getContainerName(long hCryptProv);
protected native static String getKeyType(long hCryptKey);
+
+ // This java method generates EC BLOBs for public key or private key.
+ // See https://docs.microsoft.com/en-us/windows/desktop/api/bcrypt/ns-bcrypt-_bcrypt_ecckey_blob
+ static byte[] generateECBlob(Key k) {
+
+ int keyBitLength = KeyUtil.getKeySize(k);
+ int keyLen = (keyBitLength + 7) / 8;
+ boolean isPrivate = k instanceof ECPrivateKey;
+
+ byte[] keyBlob = new byte[8 + keyLen * (isPrivate ? 3 : 2)];
+ keyBlob[0] = 'E';
+ keyBlob[1] = 'C';
+ keyBlob[2] = 'S';
+ if (isPrivate) {
+ keyBlob[3] = (byte) (keyBitLength == 256 ? '2'
+ : (keyBitLength == 384 ? '4' : '6'));
+ } else {
+ keyBlob[3] = (byte) (keyBitLength == 256 ? '1'
+ : (keyBitLength == 384 ? '3' : '5'));
+ }
+ BigInteger x;
+ BigInteger y;
+ // Fill the array in reverse order (s -> y -> x -> len) in case
+ // one BigInteger encoding has an extra 0 at the beginning
+ if (isPrivate) {
+ // We can keep X and Y zero and it still works
+ ECPrivateKey prk = (ECPrivateKey)k;
+ BigInteger s = prk.getS();
+ byte[] bs = s.toByteArray();
+ System.arraycopy(
+ bs, 0,
+ keyBlob, 8 + keyLen + keyLen + keyLen - bs.length,
+ bs.length);
+ } else {
+ ECPublicKey puk = (ECPublicKey)k;
+ x = puk.getW().getAffineX();
+ y = puk.getW().getAffineY();
+ byte[] by = y.toByteArray();
+ System.arraycopy(by, 0, keyBlob, 8 + keyLen + keyLen - by.length,
+ by.length);
+ byte[] bx = x.toByteArray();
+ System.arraycopy(bx, 0, keyBlob, 8 + keyLen - bx.length, bx.length);
+ }
+ keyBlob[4] = (byte) keyLen;
+ keyBlob[5] = keyBlob[6] = keyBlob[7] = 0;
+ return keyBlob;
+ }
}
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKeyStore.java Thu Dec 13 17:28:19 2018 +0800
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKeyStore.java Thu Dec 13 17:28:30 2018 +0800
@@ -759,12 +759,12 @@
}
/**
- * Generates RSA key and certificate chain from the private key handle,
+ * Generates key and certificate chain from the private key handle,
* collection of certificates and stores the result into key entries.
* <p>
* This method is called by native codes in security.cpp.
*/
- private void generateRSAKeyAndCertificateChain(String alias,
+ private void generateKeyAndCertificateChain(boolean isRSA, String alias,
long hCryptProv, long hCryptKey, int keyLength,
Collection<? extends Certificate> certCollection) {
try {
@@ -777,7 +777,7 @@
certChain[i] = (X509Certificate) iter.next();
}
storeWithUniqueAlias(alias, new KeyEntry(alias,
- CPrivateKey.of("RSA", hCryptProv, hCryptKey, keyLength),
+ CPrivateKey.of(isRSA ? "RSA" : "EC", hCryptProv, hCryptKey, keyLength),
certChain));
} catch (Throwable e) {
// Ignore the exception and skip this entry
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPublicKey.java Thu Dec 13 17:28:19 2018 +0800
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPublicKey.java Thu Dec 13 17:28:30 2018 +0800
@@ -26,14 +26,22 @@
package sun.security.mscapi;
import java.math.BigInteger;
+import java.security.AlgorithmParameters;
import java.security.KeyException;
+import java.security.KeyFactory;
import java.security.KeyRep;
import java.security.ProviderException;
import java.security.PublicKey;
+import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+import java.security.spec.ECPublicKeySpec;
+import java.util.Arrays;
import sun.security.rsa.RSAUtil.KeyType;
import sun.security.rsa.RSAPublicKeyImpl;
+import sun.security.util.ECKeySizeParameterSpec;
/**
* The handle for an RSA public key using the Microsoft Crypto API.
@@ -44,9 +52,69 @@
private static final long serialVersionUID = -2289561342425825391L;
- protected byte[] publicKeyBlob = null;
protected byte[] encoding = null;
+ public static class CECPublicKey extends CPublicKey implements ECPublicKey {
+
+ private ECPoint w = null;
+ private static final long serialVersionUID = 12L;
+
+ CECPublicKey(long hCryptProv, int keyLength) {
+ super("EC", hCryptProv, 0, keyLength);
+ }
+
+ @Override
+ public ECPoint getW() {
+ if (w == null) {
+ // See CKey::generateECBlob.
+ try {
+ byte[] blob = getPublicKeyBlob(
+ handles.hCryptProv, handles.hCryptKey);
+ int len = blob[8] & 0xff;
+ byte[] x = Arrays.copyOfRange(blob, 8, 8 + len);
+ byte[] y = Arrays.copyOfRange(blob, 8 + len, 8 + len + len);
+ w = new ECPoint(new BigInteger(1, x), new BigInteger(1, y));
+ } catch (KeyException e) {
+ throw new ProviderException(e);
+ }
+ }
+ return w;
+ }
+
+ @Override
+ public byte[] getEncoded() {
+ if (encoding == null) {
+ try {
+ encoding = KeyFactory.getInstance("EC").generatePublic(
+ new ECPublicKeySpec(getW(), getParams()))
+ .getEncoded();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ return encoding;
+ }
+
+ @Override
+ public ECParameterSpec getParams() {
+ try {
+ AlgorithmParameters ap = AlgorithmParameters.getInstance("EC");
+ ap.init(new ECKeySizeParameterSpec(keyLength));
+ return ap.getParameterSpec(ECParameterSpec.class);
+ } catch (Exception e) {
+ throw new ProviderException(e);
+ }
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(algorithm + "PublicKey [size=").append(keyLength)
+ .append("]\n ECPoint: ").append(getW())
+ .append("\n params: ").append(getParams());
+ return sb.toString();
+ }
+ }
+
public static class CRSAPublicKey extends CPublicKey implements RSAPublicKey {
private BigInteger modulus = null;
@@ -71,7 +139,8 @@
public BigInteger getPublicExponent() {
if (exponent == null) {
try {
- publicKeyBlob = getPublicKeyBlob(handles.hCryptKey);
+ byte[] publicKeyBlob = getPublicKeyBlob(
+ handles.hCryptProv, handles.hCryptKey);
exponent = new BigInteger(1, getExponent(publicKeyBlob));
} catch (KeyException e) {
throw new ProviderException(e);
@@ -84,7 +153,8 @@
public BigInteger getModulus() {
if (modulus == null) {
try {
- publicKeyBlob = getPublicKeyBlob(handles.hCryptKey);
+ byte[] publicKeyBlob = getPublicKeyBlob(
+ handles.hCryptProv, handles.hCryptKey);
modulus = new BigInteger(1, getModulus(publicKeyBlob));
} catch (KeyException e) {
throw new ProviderException(e);
@@ -111,16 +181,20 @@
private native byte[] getModulus(byte[] keyBlob) throws KeyException;
}
- public static CPublicKey of(String alg, long hCryptProv, long hCryptKey, int keyLength) {
+ public static CPublicKey of(
+ String alg, long hCryptProv, long hCryptKey, int keyLength) {
switch (alg) {
case "RSA":
return new CRSAPublicKey(hCryptProv, hCryptKey, keyLength);
+ case "EC":
+ return new CECPublicKey(hCryptProv, keyLength);
default:
throw new AssertionError("Unsupported algorithm: " + alg);
}
}
- protected CPublicKey(String alg, long hCryptProv, long hCryptKey, int keyLength) {
+ protected CPublicKey(
+ String alg, long hCryptProv, long hCryptKey, int keyLength) {
super(alg, hCryptProv, hCryptKey, keyLength);
}
@@ -136,7 +210,7 @@
getEncoded());
}
- // Returns the Microsoft CryptoAPI representation of the key.
- native byte[] getPublicKeyBlob(long hCryptKey) throws KeyException;
-
+ // Returns the CAPI or CNG representation of the key.
+ native byte[] getPublicKeyBlob(long hCryptProv, long hCryptKey)
+ throws KeyException;
}
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CSignature.java Thu Dec 13 17:28:19 2018 +0800
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CSignature.java Thu Dec 13 17:28:30 2018 +0800
@@ -27,6 +27,7 @@
import java.nio.ByteBuffer;
import java.security.*;
+import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.AlgorithmParameterSpec;
import java.math.BigInteger;
@@ -35,10 +36,11 @@
import java.util.Locale;
import sun.security.rsa.RSAKeyFactory;
+import sun.security.util.ECUtil;
+import sun.security.util.KeyUtil;
/**
- * Signature implementation. Supports RSA signing using PKCS#1 v1.5 padding
- * and RSASSA-PSS signing.
+ * Signature implementation.
*
* Objects should be instantiated by calling Signature.getInstance() using the
* following algorithm names:
@@ -51,6 +53,11 @@
* . "MD5withRSA"
* . "MD2withRSA"
* . "RSASSA-PSS"
+ * . "SHA1withECDSA"
+ * . "SHA224withECDSA"
+ * . "SHA256withECDSA"
+ * . "SHA384withECDSA"
+ * . "SHA512withECDSA"
*
* NOTE: RSA keys must be at least 512 bits long.
*
@@ -112,7 +119,8 @@
@Override
protected void engineInitSign(PrivateKey key) throws InvalidKeyException {
- if ((key instanceof CPrivateKey) == false) {
+ if ((key instanceof CPrivateKey) == false
+ || !key.getAlgorithm().equalsIgnoreCase("RSA")) {
throw new InvalidKeyException("Key type not supported");
}
privateKey = (CPrivateKey) key;
@@ -197,7 +205,6 @@
boolean noHashOID = this instanceof NONEwithRSA;
// Sign hash using MS Crypto APIs
-
byte[] result = signHash(noHashOID, hash, hash.length,
messageDigestAlgorithm, privateKey.getHCryptProvider(),
privateKey.getHCryptKey());
@@ -364,6 +371,106 @@
}
}
+ public static final class SHA1withECDSA extends ECDSA {
+ public SHA1withECDSA() {
+ super("SHA-1");
+ }
+ }
+
+ public static final class SHA224withECDSA extends ECDSA {
+ public SHA224withECDSA() {
+ super("SHA-224");
+ }
+ }
+
+ public static final class SHA256withECDSA extends ECDSA {
+ public SHA256withECDSA() {
+ super("SHA-256");
+ }
+ }
+
+ public static final class SHA384withECDSA extends ECDSA {
+ public SHA384withECDSA() {
+ super("SHA-384");
+ }
+ }
+
+ public static final class SHA512withECDSA extends ECDSA {
+ public SHA512withECDSA() {
+ super("SHA-512");
+ }
+ }
+
+ static class ECDSA extends CSignature {
+
+ public ECDSA(String messageDigestAlgorithm) {
+ super("EC", messageDigestAlgorithm);
+ }
+
+ // initialize for signing. See JCA doc
+ @Override
+ protected void engineInitSign(PrivateKey key) throws InvalidKeyException {
+ if ((key instanceof CPrivateKey) == false
+ || !key.getAlgorithm().equalsIgnoreCase("EC")) {
+ throw new InvalidKeyException("Key type not supported");
+ }
+ privateKey = (CPrivateKey) key;
+
+ this.publicKey = null;
+ resetDigest();
+ }
+
+ // initialize for signing. See JCA doc
+ @Override
+ protected void engineInitVerify(PublicKey key) throws InvalidKeyException {
+ // This signature accepts only ECPublicKey
+ if ((key instanceof ECPublicKey) == false) {
+ throw new InvalidKeyException("Key type not supported");
+ }
+
+
+ if ((key instanceof CPublicKey) == false) {
+ try {
+ publicKey = importECPublicKey("EC",
+ CKey.generateECBlob(key),
+ KeyUtil.getKeySize(key));
+ } catch (KeyStoreException e) {
+ throw new InvalidKeyException(e);
+ }
+ } else {
+ publicKey = (CPublicKey) key;
+ }
+
+ this.privateKey = null;
+ resetDigest();
+ }
+
+ @Override
+ protected byte[] engineSign() throws SignatureException {
+ byte[] hash = getDigestValue();
+ byte[] raw = signCngHash(0, hash, hash.length,
+ 0,
+ null,
+ privateKey.getHCryptProvider(), 0);
+ return ECUtil.encodeSignature(raw);
+ }
+
+ @Override
+ protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+ byte[] hash = getDigestValue();
+ sigBytes = ECUtil.decodeSignature(sigBytes);
+ return verifyCngSignedHash(
+ 0,
+ hash, hash.length,
+ sigBytes, sigBytes.length,
+ 0,
+ null,
+ publicKey.getHCryptProvider(),
+ 0
+ );
+ }
+ }
+
public static final class PSS extends RSA {
private PSSParameterSpec pssParams = null;
@@ -463,7 +570,7 @@
protected byte[] engineSign() throws SignatureException {
ensureInit();
byte[] hash = getDigestValue();
- return signCngHash(hash, hash.length,
+ return signCngHash(2, hash, hash.length,
pssParams.getSaltLength(),
((MGF1ParameterSpec)
pssParams.getMGFParameters()).getDigestAlgorithm(),
@@ -479,7 +586,7 @@
} else {
byte[] hash = getDigestValue();
return verifyCngSignedHash(
- hash, hash.length,
+ 2, hash, hash.length,
sigBytes, sigBytes.length,
pssParams.getSaltLength(),
((MGF1ParameterSpec)
@@ -599,19 +706,22 @@
}
/**
- * Sign hash using CNG API with HCRYPTKEY. Used by RSASSA-PSS.
+ * Sign hash using CNG API with HCRYPTKEY.
+ * @param type 0 no padding, 1, pkcs1, 2, pss
*/
native static byte[] signCngHash(
- byte[] hash, int hashSize, int saltLength, String hashAlgorithm,
+ int type, 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 PSS#fallbackSignature}.
+ * Verify a signed hash using CNG API with HCRYPTKEY.
+ * @param type 0 no padding, 1, pkcs1, 2, pss
*/
private native static boolean verifyCngSignedHash(
- byte[] hash, int hashSize, byte[] signature, int signatureSize,
+ int type, byte[] hash, int hashSize,
+ byte[] signature, int signatureSize,
int saltLength, String hashAlgorithm,
long hCryptProv, long hKey) throws SignatureException;
@@ -804,4 +914,7 @@
// used by CRSACipher
static native CPublicKey importPublicKey(
String alg, byte[] keyBlob, int keySize) throws KeyStoreException;
+
+ static native CPublicKey importECPublicKey(
+ String alg, byte[] keyBlob, int keySize) throws KeyStoreException;
}
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java Thu Dec 13 17:28:19 2018 +0800
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java Thu Dec 13 17:28:30 2018 +0800
@@ -106,6 +106,16 @@
return new CSignature.MD2withRSA();
} else if (algo.equals("RSASSA-PSS")) {
return new CSignature.PSS();
+ } else if (algo.equals("SHA1withECDSA")) {
+ return new CSignature.SHA1withECDSA();
+ } else if (algo.equals("SHA224withECDSA")) {
+ return new CSignature.SHA224withECDSA();
+ } else if (algo.equals("SHA256withECDSA")) {
+ return new CSignature.SHA256withECDSA();
+ } else if (algo.equals("SHA384withECDSA")) {
+ return new CSignature.SHA384withECDSA();
+ } else if (algo.equals("SHA512withECDSA")) {
+ return new CSignature.SHA512withECDSA();
}
} else if (type.equals("KeyPairGenerator")) {
if (algo.equals("RSA")) {
@@ -188,7 +198,26 @@
putService(new ProviderService(p, "Signature",
"MD2withRSA", "sun.security.mscapi.CSignature$MD2withRSA",
null, attrs));
-
+ putService(new ProviderService(p, "Signature",
+ "SHA1withECDSA", "sun.security.mscapi.CSignature$SHA1withECDSA",
+ new String[] { "1.2.840.10045.4.1", "OID.1.2.840.10045.4.1" },
+ attrs));
+ putService(new ProviderService(p, "Signature",
+ "SHA224withECDSA", "sun.security.mscapi.CSignature$SHA224withECDSA",
+ new String[] { "1.2.840.10045.4.3.1", "OID.1.2.840.10045.4.3.1"},
+ attrs));
+ putService(new ProviderService(p, "Signature",
+ "SHA256withECDSA", "sun.security.mscapi.CSignature$SHA256withECDSA",
+ new String[] { "1.2.840.10045.4.3.2", "OID.1.2.840.10045.4.3.2"},
+ attrs));
+ putService(new ProviderService(p, "Signature",
+ "SHA384withECDSA", "sun.security.mscapi.CSignature$SHA384withECDSA",
+ new String[] { "1.2.840.10045.4.3.3", "OID.1.2.840.10045.4.3.3"},
+ attrs));
+ putService(new ProviderService(p, "Signature",
+ "SHA512withECDSA", "sun.security.mscapi.CSignature$SHA512withECDSA",
+ new String[] { "1.2.840.10045.4.3.4", "OID.1.2.840.10045.4.3.4"},
+ attrs));
/*
* Key Pair Generator engines
*/
--- a/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp Thu Dec 13 17:28:19 2018 +0800
+++ b/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp Thu Dec 13 17:28:30 2018 +0800
@@ -65,44 +65,53 @@
__leave; \
}
-//#define PP(fmt, ...) \
-// fprintf(stdout, "MSCAPI (%ld): ", __LINE__); \
-// fprintf(stdout, fmt, ##__VA_ARGS__); \
-// fprintf(stdout, "\n"); \
-// fflush(stdout)
+#define PP(fmt, ...) \
+ if (trace) { \
+ fprintf(stdout, "MSCAPI (%ld): ", __LINE__); \
+ fprintf(stdout, fmt, ##__VA_ARGS__); \
+ fprintf(stdout, "\n"); \
+ fflush(stdout); \
+ }
extern "C" {
+char* trace = getenv("CAPI_TRACE");
+
/*
* Declare library specific JNI_Onload entry if static build
*/
DEF_STATIC_JNI_OnLoad
-//void dump(LPSTR title, PBYTE data, DWORD len)
-//{
-// printf("==== %s ====\n", title);
-// for (DWORD i = 0; i < len; i+=16) {
-// printf("%04x: ", i);
-// for (int j = 0; j < 16; j++) {
-// if (j == 8) {
-// printf(" ");
-// }
-// if (i + j < len) {
-// printf("%02X ", *(data + i + j) & 0xff);
-// } else {
-// printf(" ");
-// }
-// }
-// for (int j = 0; j < 16; j++) {
-// if (i + j < len) {
-// int k = *(data + i + j) & 0xff;
-// if (k < 32 || k > 127) printf(".");
-// else printf("%c", (char)k);
-// }
-// }
-// printf("\n");
-// }
-//}
+void showProperty(NCRYPT_HANDLE hKey);
+
+void dump(LPSTR title, PBYTE data, DWORD len)
+{
+ if (trace) {
+ printf("==== %s ====\n", title);
+ for (DWORD i = 0; i < len; i+=16) {
+ printf("%04x: ", i);
+ for (int j = 0; j < 16; j++) {
+ if (j == 8) {
+ printf(" ");
+ }
+ if (i + j < len) {
+ printf("%02X ", *(data + i + j) & 0xff);
+ } else {
+ printf(" ");
+ }
+ }
+ for (int j = 0; j < 16; j++) {
+ if (i + j < len) {
+ int k = *(data + i + j) & 0xff;
+ if (k < 32 || k > 127) printf(".");
+ else printf("%c", (char)k);
+ }
+ }
+ printf("\n");
+ }
+ fflush(stdout);
+ }
+}
/*
* Throws an arbitrary Java exception with the given message.
@@ -445,10 +454,10 @@
}
// Determine method ID to generate RSA certificate chain
- jmethodID mGenRSAKeyAndCertChain = env->GetMethodID(clazzOfThis,
- "generateRSAKeyAndCertificateChain",
- "(Ljava/lang/String;JJILjava/util/Collection;)V");
- if (mGenRSAKeyAndCertChain == NULL) {
+ jmethodID mGenKeyAndCertChain = env->GetMethodID(clazzOfThis,
+ "generateKeyAndCertificateChain",
+ "(ZLjava/lang/String;JJILjava/util/Collection;)V");
+ if (mGenKeyAndCertChain == NULL) {
__leave;
}
@@ -457,6 +466,7 @@
// NULL to retrieve the first certificate in the store.
while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext))
{
+ PP("--------------------------");
// Check if private key available - client authentication certificate
// must have private key available.
HCRYPTPROV hCryptProv = NULL;
@@ -467,10 +477,12 @@
DWORD dwPublicKeyLength = 0;
// First, probe it silently
- if (::CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_SILENT_FLAG, NULL,
+ if (::CryptAcquireCertificatePrivateKey(pCertContext,
+ CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG | CRYPT_ACQUIRE_SILENT_FLAG, NULL,
&hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE
&& GetLastError() != NTE_SILENT_CONTEXT)
{
+ PP("bHasNoPrivateKey = TRUE!");
bHasNoPrivateKey = TRUE;
}
else
@@ -481,27 +493,32 @@
}
// Second, acquire the key normally (not silently)
- if (::CryptAcquireCertificatePrivateKey(pCertContext, 0, NULL,
+ if (::CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL,
&hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE)
{
+ PP("bHasNoPrivateKey = TRUE!!");
bHasNoPrivateKey = TRUE;
}
else
{
- // Private key is available
- BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey); //deprecated
+ if ((dwKeySpec & CERT_NCRYPT_KEY_SPEC) == CERT_NCRYPT_KEY_SPEC) {
+ PP("CNG %I64d", hCryptProv);
+ } else {
+ // Private key is available
+ BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey); //deprecated
- // Skip certificate if cannot find private key
- if (bGetUserKey == FALSE) {
- if (bCallerFreeProv)
- ::CryptReleaseContext(hCryptProv, NULL); // deprecated
- continue;
+ // Skip certificate if cannot find private key
+ if (bGetUserKey == FALSE) {
+ if (bCallerFreeProv)
+ ::CryptReleaseContext(hCryptProv, NULL); // deprecated
+ continue;
+ }
+
+ // Set cipher mode to ECB
+ DWORD dwCipherMode = CRYPT_MODE_ECB;
+ ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL); //deprecated
+ PP("CAPI %I64d %I64d", hCryptProv, hUserKey);
}
-
- // Set cipher mode to ECB
- DWORD dwCipherMode = CRYPT_MODE_ECB;
- ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL); //deprecated
-
// If the private key is present in smart card, we may not be able to
// determine the key length by using the private key handle. However,
// since public/private key pairs must have the same length, we could
@@ -573,6 +590,7 @@
env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList);
}
+ PP("%s: %s", pszNameString, pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
if (bHasNoPrivateKey)
{
// Generate certificate chain and store into cert chain
@@ -583,19 +601,40 @@
}
else
{
- // Determine key type: RSA or DSA
- DWORD dwData = CALG_RSA_KEYX;
- DWORD dwSize = sizeof(DWORD);
- ::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData, //deprecated
- &dwSize, NULL);
- if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)
- {
- // Generate RSA certificate chain and store into cert
- // chain collection
- env->CallVoidMethod(obj, mGenRSAKeyAndCertChain,
- env->NewStringUTF(pszNameString),
- (jlong) hCryptProv, (jlong) hUserKey,
- dwPublicKeyLength, jArrayList);
+ if (hUserKey) {
+ // Only accept RSA for CAPI
+ DWORD dwData = CALG_RSA_KEYX;
+ DWORD dwSize = sizeof(DWORD);
+ ::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData, //deprecated
+ &dwSize, NULL);
+ if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)
+ {
+ // Generate RSA certificate chain and store into cert
+ // chain collection
+ env->CallVoidMethod(obj, mGenKeyAndCertChain,
+ 1,
+ env->NewStringUTF(pszNameString),
+ (jlong) hCryptProv, (jlong) hUserKey,
+ dwPublicKeyLength, jArrayList);
+ }
+ } else {
+ // Only accept EC for CNG
+ BYTE buffer[32];
+ DWORD len = 0;
+ if (::NCryptGetProperty(
+ hCryptProv, NCRYPT_ALGORITHM_PROPERTY,
+ (PBYTE)buffer, 32, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {
+ if (buffer[0] == 'E' && buffer[2] == 'C'
+ && (dwPublicKeyLength == 256
+ || dwPublicKeyLength == 384
+ || dwPublicKeyLength == 521)) {
+ env->CallVoidMethod(obj, mGenKeyAndCertChain,
+ 0,
+ env->NewStringUTF(pszNameString),
+ (jlong) hCryptProv, 0,
+ dwPublicKeyLength, jArrayList);
+ }
+ }
}
}
}
@@ -603,6 +642,8 @@
// Free cert chain
if (pCertChainContext)
::CertFreeCertificateChain(pCertChainContext);
+ } else {
+ PP("GetCertificateChain failed %d", GetLastError());
}
}
}
@@ -768,10 +809,10 @@
/*
* Class: sun_security_mscapi_CSignature
* Method: signCngHash
- * Signature: ([BIILjava/lang/String;JJ)[B
+ * Signature: (I[BIILjava/lang/String;JJ)[B
*/
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signCngHash
- (JNIEnv *env, jclass clazz, jbyteArray jHash,
+ (JNIEnv *env, jclass clazz, jint type, jbyteArray jHash,
jint jHashSize, jint saltLen, jstring jHashAlgorithm, jlong hCryptProv,
jlong hCryptKey)
{
@@ -783,13 +824,17 @@
__try
{
- SS_CHECK(::NCryptTranslateHandle(
+ if (hCryptKey == 0) {
+ hk = (NCRYPT_KEY_HANDLE)hCryptProv;
+ } else {
+ SS_CHECK(::NCryptTranslateHandle(
NULL,
&hk,
hCryptProv,
hCryptKey,
NULL,
0));
+ }
// Copy hash from Java to native buffer
pHashBuffer = new (env) jbyte[jHashSize];
@@ -798,43 +843,66 @@
}
env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
- BCRYPT_PSS_PADDING_INFO pssInfo;
- pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
- pssInfo.cbSalt = saltLen;
+ VOID* param;
+ DWORD dwFlags;
- if (pssInfo.pszAlgId == NULL) {
- ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
- "Unrecognised hash algorithm");
- __leave;
+ switch (type) {
+ case 0:
+ param = NULL;
+ dwFlags = 0;
+ break;
+ case 1:
+ BCRYPT_PKCS1_PADDING_INFO pkcs1Info;
+ pkcs1Info.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
+ if (pkcs1Info.pszAlgId == NULL) {
+ ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
+ "Unrecognised hash algorithm");
+ __leave;
+ }
+ param = &pkcs1Info;
+ dwFlags = BCRYPT_PAD_PKCS1;
+ break;
+ case 2:
+ 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;
+ }
+ param = &pssInfo;
+ dwFlags = BCRYPT_PAD_PSS;
+ break;
}
- DWORD dwBufLen = 0;
+ DWORD jSignedHashSize = 0;
SS_CHECK(::NCryptSignHash(
hk,
- &pssInfo,
+ param,
(BYTE*)pHashBuffer, jHashSize,
- NULL, 0, &dwBufLen,
- BCRYPT_PAD_PSS
+ NULL, 0, &jSignedHashSize,
+ dwFlags
));
- pSignedHashBuffer = new (env) jbyte[dwBufLen];
+ pSignedHashBuffer = new (env) jbyte[jSignedHashSize];
if (pSignedHashBuffer == NULL) {
__leave;
}
SS_CHECK(::NCryptSignHash(
hk,
- &pssInfo,
+ param,
(BYTE*)pHashBuffer, jHashSize,
- (BYTE*)pSignedHashBuffer, dwBufLen, &dwBufLen,
- BCRYPT_PAD_PSS
+ (BYTE*)pSignedHashBuffer, jSignedHashSize, &jSignedHashSize,
+ dwFlags
));
// Create new byte array
- jbyteArray temp = env->NewByteArray(dwBufLen);
+ jbyteArray temp = env->NewByteArray(jSignedHashSize);
// Copy data from native buffer
- env->SetByteArrayRegion(temp, 0, dwBufLen, pSignedHashBuffer);
+ env->SetByteArrayRegion(temp, 0, jSignedHashSize, pSignedHashBuffer);
jSignedHash = temp;
}
@@ -846,7 +914,7 @@
if (pHashBuffer)
delete [] pHashBuffer;
- if (hk != NULL)
+ if (hCryptKey != 0 && hk != NULL)
::NCryptFreeObject(hk);
}
@@ -961,10 +1029,10 @@
/*
* Class: sun_security_mscapi_CSignature
* Method: verifyCngSignedHash
- * Signature: ([BI[BIILjava/lang/String;JJ)Z
+ * Signature: (I[BI[BIILjava/lang/String;JJ)Z
*/
JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifyCngSignedHash
- (JNIEnv *env, jclass clazz,
+ (JNIEnv *env, jclass clazz, jint type,
jbyteArray jHash, jint jHashSize,
jbyteArray jSignedHash, jint jSignedHashSize,
jint saltLen, jstring jHashAlgorithm,
@@ -977,13 +1045,17 @@
__try
{
- SS_CHECK(::NCryptTranslateHandle(
+ if (hCryptKey == 0) {
+ hk = (NCRYPT_KEY_HANDLE)hCryptProv;
+ } else {
+ SS_CHECK(::NCryptTranslateHandle(
NULL,
&hk,
hCryptProv,
hCryptKey,
NULL,
0));
+ }
// Copy hash and signedHash from Java to native buffer
pHashBuffer = new (env) jbyte[jHashSize];
@@ -999,19 +1071,43 @@
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;
+ VOID* param;
+ DWORD dwFlags;
+
+ switch (type) {
+ case 0:
+ param = NULL;
+ dwFlags = 0;
+ break;
+ case 1:
+ BCRYPT_PKCS1_PADDING_INFO pkcs1Info;
+ pkcs1Info.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
+ if (pkcs1Info.pszAlgId == NULL) {
+ ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
+ "Unrecognised hash algorithm");
+ __leave;
+ }
+ param = &pkcs1Info;
+ dwFlags = NCRYPT_PAD_PKCS1_FLAG;
+ break;
+ case 2:
+ 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;
+ }
+ param = &pssInfo;
+ dwFlags = NCRYPT_PAD_PSS_FLAG;
+ break;
}
- if (::NCryptVerifySignature(hk, &pssInfo,
+ if (::NCryptVerifySignature(hk, param,
(BYTE *) pHashBuffer, jHashSize,
(BYTE *) pSignedHashBuffer, jSignedHashSize,
- NCRYPT_PAD_PSS_FLAG) == ERROR_SUCCESS)
+ dwFlags) == ERROR_SUCCESS)
{
result = JNI_TRUE;
}
@@ -1025,13 +1121,108 @@
if (pHashBuffer)
delete [] pHashBuffer;
- if (hk != NULL)
+ if (hCryptKey != 0 && hk != NULL)
::NCryptFreeObject(hk);
}
return result;
}
+#define DUMP_PROP(p) \
+ if (::NCryptGetProperty(hKey, p, (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) { \
+ sprintf(header, "%s %ls", #p, p); \
+ dump(header, buffer, len); \
+ }
+
+#define EXPORT_BLOB(p) \
+ desc.cBuffers = 0; \
+ if (::NCryptExportKey(hKey, NULL, p, &desc, (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) { \
+ sprintf(header, "%s %ls (%ld)", #p, p, desc.cBuffers); \
+ dump(header, buffer, len); \
+ for (int i = 0; i < (int)desc.cBuffers; i++) { \
+ sprintf(header, "desc %ld", desc.pBuffers[i].BufferType); \
+ dump(header, (PBYTE)desc.pBuffers[i].pvBuffer, desc.pBuffers[i].cbBuffer); \
+ } \
+ }
+
+void showProperty(NCRYPT_HANDLE hKey) {
+ char header[100];
+ BYTE buffer[8192];
+ DWORD len = 9;
+ NCryptBufferDesc desc;
+ DUMP_PROP(NCRYPT_ALGORITHM_GROUP_PROPERTY);
+ DUMP_PROP(NCRYPT_ALGORITHM_PROPERTY);
+ DUMP_PROP(NCRYPT_ASSOCIATED_ECDH_KEY);
+ DUMP_PROP(NCRYPT_BLOCK_LENGTH_PROPERTY);
+ DUMP_PROP(NCRYPT_CERTIFICATE_PROPERTY);
+ DUMP_PROP(NCRYPT_DH_PARAMETERS_PROPERTY);
+ DUMP_PROP(NCRYPT_EXPORT_POLICY_PROPERTY);
+ DUMP_PROP(NCRYPT_IMPL_TYPE_PROPERTY);
+ DUMP_PROP(NCRYPT_KEY_TYPE_PROPERTY);
+ DUMP_PROP(NCRYPT_KEY_USAGE_PROPERTY);
+ DUMP_PROP(NCRYPT_LAST_MODIFIED_PROPERTY);
+ DUMP_PROP(NCRYPT_LENGTH_PROPERTY);
+ DUMP_PROP(NCRYPT_LENGTHS_PROPERTY);
+ DUMP_PROP(NCRYPT_MAX_NAME_LENGTH_PROPERTY);
+ DUMP_PROP(NCRYPT_NAME_PROPERTY);
+ DUMP_PROP(NCRYPT_PIN_PROMPT_PROPERTY);
+ DUMP_PROP(NCRYPT_PIN_PROPERTY);
+ DUMP_PROP(NCRYPT_PROVIDER_HANDLE_PROPERTY);
+ DUMP_PROP(NCRYPT_READER_PROPERTY);
+ DUMP_PROP(NCRYPT_ROOT_CERTSTORE_PROPERTY);
+ DUMP_PROP(NCRYPT_SCARD_PIN_ID);
+ DUMP_PROP(NCRYPT_SCARD_PIN_INFO);
+ DUMP_PROP(NCRYPT_SECURE_PIN_PROPERTY);
+ DUMP_PROP(NCRYPT_SECURITY_DESCR_PROPERTY);
+ DUMP_PROP(NCRYPT_SECURITY_DESCR_SUPPORT_PROPERTY);
+ DUMP_PROP(NCRYPT_SMARTCARD_GUID_PROPERTY);
+ DUMP_PROP(NCRYPT_UI_POLICY_PROPERTY);
+ DUMP_PROP(NCRYPT_UNIQUE_NAME_PROPERTY);
+ DUMP_PROP(NCRYPT_USE_CONTEXT_PROPERTY);
+ DUMP_PROP(NCRYPT_USE_COUNT_ENABLED_PROPERTY);
+ DUMP_PROP(NCRYPT_USE_COUNT_PROPERTY);
+ DUMP_PROP(NCRYPT_USER_CERTSTORE_PROPERTY);
+ DUMP_PROP(NCRYPT_VERSION_PROPERTY);
+ DUMP_PROP(NCRYPT_WINDOW_HANDLE_PROPERTY);
+
+ EXPORT_BLOB(BCRYPT_DH_PRIVATE_BLOB);
+ EXPORT_BLOB(BCRYPT_DH_PUBLIC_BLOB);
+ EXPORT_BLOB(BCRYPT_DSA_PRIVATE_BLOB);
+ EXPORT_BLOB(BCRYPT_DSA_PUBLIC_BLOB);
+ EXPORT_BLOB(BCRYPT_ECCPRIVATE_BLOB);
+ EXPORT_BLOB(BCRYPT_ECCPUBLIC_BLOB);
+ EXPORT_BLOB(BCRYPT_PUBLIC_KEY_BLOB);
+ EXPORT_BLOB(BCRYPT_PRIVATE_KEY_BLOB);
+ EXPORT_BLOB(BCRYPT_RSAFULLPRIVATE_BLOB);
+ EXPORT_BLOB(BCRYPT_RSAPRIVATE_BLOB);
+ EXPORT_BLOB(BCRYPT_RSAPUBLIC_BLOB);
+ EXPORT_BLOB(LEGACY_DH_PRIVATE_BLOB);
+ EXPORT_BLOB(LEGACY_DH_PUBLIC_BLOB);
+ EXPORT_BLOB(LEGACY_DSA_PRIVATE_BLOB);
+ EXPORT_BLOB(LEGACY_DSA_PUBLIC_BLOB);
+ EXPORT_BLOB(LEGACY_RSAPRIVATE_BLOB);
+ EXPORT_BLOB(LEGACY_RSAPUBLIC_BLOB);
+ EXPORT_BLOB(NCRYPT_CIPHER_KEY_BLOB);
+ EXPORT_BLOB(NCRYPT_OPAQUETRANSPORT_BLOB);
+ EXPORT_BLOB(NCRYPT_PKCS7_ENVELOPE_BLOB);
+ //EXPORT_BLOB(NCRYPTBUFFER_CERT_BLOB);
+ //EXPORT_BLOB(NCRYPT_PKCS8_PRIVATE_KEY_BLOB);
+ BCryptBuffer bb;
+ bb.BufferType = NCRYPTBUFFER_PKCS_SECRET;
+ bb.cbBuffer = 18;
+ bb.pvBuffer = L"changeit";
+ BCryptBufferDesc bbd;
+ bbd.ulVersion = 0;
+ bbd.cBuffers = 1;
+ bbd.pBuffers = &bb;
+ if(::NCryptExportKey(hKey, NULL, NCRYPT_PKCS8_PRIVATE_KEY_BLOB, NULL,
+ (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {
+ sprintf(header, "NCRYPT_PKCS8_PRIVATE_KEY_BLOB %ls", NCRYPT_PKCS8_PRIVATE_KEY_BLOB);
+ dump(header, buffer, len);
+ }
+ EXPORT_BLOB(NCRYPT_PROTECTED_KEY_BLOB);
+}
+
/*
* Class: sun_security_mscapi_CKeyPairGenerator_RSA
* Method: generateCKeyPair
@@ -1673,10 +1864,10 @@
/*
* Class: sun_security_mscapi_CPublicKey
* Method: getPublicKeyBlob
- * Signature: (J)[B
+ * Signature: (JJ)[B
*/
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_getPublicKeyBlob
- (JNIEnv *env, jobject clazz, jlong hCryptKey) {
+ (JNIEnv *env, jobject clazz, jlong hCryptProv, jlong hCryptKey) {
jbyteArray blob = NULL;
DWORD dwBlobLen;
@@ -1686,11 +1877,17 @@
{
// Determine the size of the blob
- if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, NULL, //deprecated
- &dwBlobLen)) {
+ if (hCryptKey == 0) {
+ SS_CHECK(::NCryptExportKey(
+ hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,
+ NULL, NULL, 0, &dwBlobLen, NCRYPT_SILENT_FLAG));
+ } else {
+ if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, NULL, //deprecated
+ &dwBlobLen)) {
- ThrowException(env, KEY_EXCEPTION, GetLastError());
- __leave;
+ ThrowException(env, KEY_EXCEPTION, GetLastError());
+ __leave;
+ }
}
pbKeyBlob = new (env) BYTE[dwBlobLen];
@@ -1699,11 +1896,17 @@
}
// Generate key blob
- if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, //deprecated
- pbKeyBlob, &dwBlobLen)) {
+ if (hCryptKey == 0) {
+ SS_CHECK(::NCryptExportKey(
+ hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,
+ NULL, pbKeyBlob, dwBlobLen, &dwBlobLen, NCRYPT_SILENT_FLAG));
+ } else {
+ if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, //deprecated
+ pbKeyBlob, &dwBlobLen)) {
- ThrowException(env, KEY_EXCEPTION, GetLastError());
- __leave;
+ ThrowException(env, KEY_EXCEPTION, GetLastError());
+ __leave;
+ }
}
// Create new byte array
@@ -2177,6 +2380,66 @@
/*
* Class: sun_security_mscapi_CSignature
+ * Method: importECPublicKey
+ * Signature: (Ljava/lang/String;[BI)Lsun/security/mscapi/CPublicKey;
+ */
+JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CSignature_importECPublicKey
+ (JNIEnv *env, jclass clazz, jstring alg, jbyteArray keyBlob, jint keySize)
+{
+ BCRYPT_ALG_HANDLE hSignAlg = NULL;
+ NCRYPT_KEY_HANDLE hTmpKey = NULL;
+ DWORD dwBlobLen;
+ BYTE * pbKeyBlob = NULL;
+ jobject publicKey = NULL;
+
+ __try
+ {
+ dwBlobLen = env->GetArrayLength(keyBlob);
+ if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))
+ == NULL) {
+ __leave;
+ }
+ dump("NCryptImportKey", pbKeyBlob, dwBlobLen);
+ NCRYPT_PROV_HANDLE hProv;
+ SS_CHECK(NCryptOpenStorageProvider(
+ &hProv, L"Microsoft Software Key Storage Provider", 0 ));
+ SS_CHECK(NCryptImportKey(
+ hProv,
+ NULL,
+ BCRYPT_ECCPUBLIC_BLOB,
+ NULL,
+ &hTmpKey,
+ pbKeyBlob,
+ dwBlobLen,
+ 0));
+ NCryptFreeObject( hProv );
+ // Get the method ID for the CPublicKey constructor
+ jclass clazzCPublicKey =
+ env->FindClass("sun/security/mscapi/CPublicKey");
+ if (clazzCPublicKey == NULL) {
+ __leave;
+ }
+
+ jmethodID mNewCPublicKey =
+ env->GetStaticMethodID(clazzCPublicKey, "of",
+ "(Ljava/lang/String;JJI)Lsun/security/mscapi/CPublicKey;");
+ if (mNewCPublicKey == NULL) {
+ __leave;
+ }
+
+ // Create a new public key
+ publicKey = env->CallStaticObjectMethod(clazzCPublicKey, mNewCPublicKey,
+ alg, (jlong) hTmpKey, (jlong) 0, keySize);
+ }
+ __finally
+ {
+ }
+
+ return publicKey;
+}
+
+/*
+ * Class: sun_security_mscapi_CSignature
* Method: importPublicKey
* Signature: (Ljava/lang/String;[BI)Lsun/security/mscapi/CPublicKey;
*/