8213010: Supporting keys created with certmgr.exe
Reviewed-by: valeriep
This commit is contained in:
parent
dcb88767a7
commit
a438a0766c
@ -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.
|
* 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
|
||||||
@ -26,17 +26,11 @@
|
|||||||
package sun.security.util;
|
package sun.security.util;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
|
|
||||||
import java.security.interfaces.*;
|
import java.security.interfaces.*;
|
||||||
|
|
||||||
import java.security.spec.*;
|
import java.security.spec.*;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import sun.security.x509.X509Key;
|
import sun.security.x509.X509Key;
|
||||||
|
|
||||||
public class ECUtil {
|
public class ECUtil {
|
||||||
@ -227,5 +221,64 @@ public class ECUtil {
|
|||||||
return nameSpec.getName();
|
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() {}
|
private ECUtil() {}
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,7 @@
|
|||||||
|
|
||||||
package sun.security.ec;
|
package sun.security.ec;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.interfaces.*;
|
import java.security.interfaces.*;
|
||||||
@ -453,7 +451,7 @@ abstract class ECDSASignature extends SignatureSpi {
|
|||||||
if (p1363Format) {
|
if (p1363Format) {
|
||||||
return sig;
|
return sig;
|
||||||
} else {
|
} else {
|
||||||
return encodeSignature(sig);
|
return ECUtil.encodeSignature(sig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,7 +474,7 @@ abstract class ECDSASignature extends SignatureSpi {
|
|||||||
if (p1363Format) {
|
if (p1363Format) {
|
||||||
sig = signature;
|
sig = signature;
|
||||||
} else {
|
} else {
|
||||||
sig = decodeSignature(signature);
|
sig = ECUtil.decodeSignature(signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -515,79 +513,6 @@ abstract class ECDSASignature extends SignatureSpi {
|
|||||||
return null;
|
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.
|
* Signs the digest using the private key.
|
||||||
*
|
*
|
||||||
|
@ -25,9 +25,13 @@
|
|||||||
|
|
||||||
package sun.security.mscapi;
|
package sun.security.mscapi;
|
||||||
|
|
||||||
|
import sun.security.util.KeyUtil;
|
||||||
import sun.security.util.Length;
|
import sun.security.util.Length;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
|
import java.security.interfaces.ECPrivateKey;
|
||||||
|
import java.security.interfaces.ECPublicKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The handle for a key using the Microsoft Crypto API.
|
* The handle for a key using the Microsoft Crypto API.
|
||||||
@ -100,4 +104,51 @@ abstract class CKey implements Key, Length {
|
|||||||
protected native static String getContainerName(long hCryptProv);
|
protected native static String getContainerName(long hCryptProv);
|
||||||
|
|
||||||
protected native static String getKeyType(long hCryptKey);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -759,12 +759,12 @@ abstract class CKeyStore extends KeyStoreSpi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
* collection of certificates and stores the result into key entries.
|
||||||
* <p>
|
* <p>
|
||||||
* This method is called by native codes in security.cpp.
|
* 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,
|
long hCryptProv, long hCryptKey, int keyLength,
|
||||||
Collection<? extends Certificate> certCollection) {
|
Collection<? extends Certificate> certCollection) {
|
||||||
try {
|
try {
|
||||||
@ -777,7 +777,7 @@ abstract class CKeyStore extends KeyStoreSpi {
|
|||||||
certChain[i] = (X509Certificate) iter.next();
|
certChain[i] = (X509Certificate) iter.next();
|
||||||
}
|
}
|
||||||
storeWithUniqueAlias(alias, new KeyEntry(alias,
|
storeWithUniqueAlias(alias, new KeyEntry(alias,
|
||||||
CPrivateKey.of("RSA", hCryptProv, hCryptKey, keyLength),
|
CPrivateKey.of(isRSA ? "RSA" : "EC", hCryptProv, hCryptKey, keyLength),
|
||||||
certChain));
|
certChain));
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
// Ignore the exception and skip this entry
|
// Ignore the exception and skip this entry
|
||||||
|
@ -26,14 +26,22 @@
|
|||||||
package sun.security.mscapi;
|
package sun.security.mscapi;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.security.AlgorithmParameters;
|
||||||
import java.security.KeyException;
|
import java.security.KeyException;
|
||||||
|
import java.security.KeyFactory;
|
||||||
import java.security.KeyRep;
|
import java.security.KeyRep;
|
||||||
import java.security.ProviderException;
|
import java.security.ProviderException;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
|
import java.security.interfaces.ECPublicKey;
|
||||||
import java.security.interfaces.RSAPublicKey;
|
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.RSAUtil.KeyType;
|
||||||
import sun.security.rsa.RSAPublicKeyImpl;
|
import sun.security.rsa.RSAPublicKeyImpl;
|
||||||
|
import sun.security.util.ECKeySizeParameterSpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The handle for an RSA public key using the Microsoft Crypto API.
|
* The handle for an RSA public key using the Microsoft Crypto API.
|
||||||
@ -44,9 +52,69 @@ public abstract class CPublicKey extends CKey implements PublicKey {
|
|||||||
|
|
||||||
private static final long serialVersionUID = -2289561342425825391L;
|
private static final long serialVersionUID = -2289561342425825391L;
|
||||||
|
|
||||||
protected byte[] publicKeyBlob = null;
|
|
||||||
protected byte[] encoding = 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 {
|
public static class CRSAPublicKey extends CPublicKey implements RSAPublicKey {
|
||||||
|
|
||||||
private BigInteger modulus = null;
|
private BigInteger modulus = null;
|
||||||
@ -71,7 +139,8 @@ public abstract class CPublicKey extends CKey implements PublicKey {
|
|||||||
public BigInteger getPublicExponent() {
|
public BigInteger getPublicExponent() {
|
||||||
if (exponent == null) {
|
if (exponent == null) {
|
||||||
try {
|
try {
|
||||||
publicKeyBlob = getPublicKeyBlob(handles.hCryptKey);
|
byte[] publicKeyBlob = getPublicKeyBlob(
|
||||||
|
handles.hCryptProv, handles.hCryptKey);
|
||||||
exponent = new BigInteger(1, getExponent(publicKeyBlob));
|
exponent = new BigInteger(1, getExponent(publicKeyBlob));
|
||||||
} catch (KeyException e) {
|
} catch (KeyException e) {
|
||||||
throw new ProviderException(e);
|
throw new ProviderException(e);
|
||||||
@ -84,7 +153,8 @@ public abstract class CPublicKey extends CKey implements PublicKey {
|
|||||||
public BigInteger getModulus() {
|
public BigInteger getModulus() {
|
||||||
if (modulus == null) {
|
if (modulus == null) {
|
||||||
try {
|
try {
|
||||||
publicKeyBlob = getPublicKeyBlob(handles.hCryptKey);
|
byte[] publicKeyBlob = getPublicKeyBlob(
|
||||||
|
handles.hCryptProv, handles.hCryptKey);
|
||||||
modulus = new BigInteger(1, getModulus(publicKeyBlob));
|
modulus = new BigInteger(1, getModulus(publicKeyBlob));
|
||||||
} catch (KeyException e) {
|
} catch (KeyException e) {
|
||||||
throw new ProviderException(e);
|
throw new ProviderException(e);
|
||||||
@ -111,16 +181,20 @@ public abstract class CPublicKey extends CKey implements PublicKey {
|
|||||||
private native byte[] getModulus(byte[] keyBlob) throws KeyException;
|
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) {
|
switch (alg) {
|
||||||
case "RSA":
|
case "RSA":
|
||||||
return new CRSAPublicKey(hCryptProv, hCryptKey, keyLength);
|
return new CRSAPublicKey(hCryptProv, hCryptKey, keyLength);
|
||||||
|
case "EC":
|
||||||
|
return new CECPublicKey(hCryptProv, keyLength);
|
||||||
default:
|
default:
|
||||||
throw new AssertionError("Unsupported algorithm: " + alg);
|
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);
|
super(alg, hCryptProv, hCryptKey, keyLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +210,7 @@ public abstract class CPublicKey extends CKey implements PublicKey {
|
|||||||
getEncoded());
|
getEncoded());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the Microsoft CryptoAPI representation of the key.
|
// Returns the CAPI or CNG representation of the key.
|
||||||
native byte[] getPublicKeyBlob(long hCryptKey) throws KeyException;
|
native byte[] getPublicKeyBlob(long hCryptProv, long hCryptKey)
|
||||||
|
throws KeyException;
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ package sun.security.mscapi;
|
|||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
|
import java.security.interfaces.ECPublicKey;
|
||||||
import java.security.interfaces.RSAPublicKey;
|
import java.security.interfaces.RSAPublicKey;
|
||||||
import java.security.spec.AlgorithmParameterSpec;
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
@ -35,10 +36,11 @@ import java.security.spec.PSSParameterSpec;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import sun.security.rsa.RSAKeyFactory;
|
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
|
* Signature implementation.
|
||||||
* and RSASSA-PSS signing.
|
|
||||||
*
|
*
|
||||||
* Objects should be instantiated by calling Signature.getInstance() using the
|
* Objects should be instantiated by calling Signature.getInstance() using the
|
||||||
* following algorithm names:
|
* following algorithm names:
|
||||||
@ -51,6 +53,11 @@ import sun.security.rsa.RSAKeyFactory;
|
|||||||
* . "MD5withRSA"
|
* . "MD5withRSA"
|
||||||
* . "MD2withRSA"
|
* . "MD2withRSA"
|
||||||
* . "RSASSA-PSS"
|
* . "RSASSA-PSS"
|
||||||
|
* . "SHA1withECDSA"
|
||||||
|
* . "SHA224withECDSA"
|
||||||
|
* . "SHA256withECDSA"
|
||||||
|
* . "SHA384withECDSA"
|
||||||
|
* . "SHA512withECDSA"
|
||||||
*
|
*
|
||||||
* NOTE: RSA keys must be at least 512 bits long.
|
* NOTE: RSA keys must be at least 512 bits long.
|
||||||
*
|
*
|
||||||
@ -112,7 +119,8 @@ abstract class CSignature extends SignatureSpi {
|
|||||||
@Override
|
@Override
|
||||||
protected void engineInitSign(PrivateKey key) throws InvalidKeyException {
|
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");
|
throw new InvalidKeyException("Key type not supported");
|
||||||
}
|
}
|
||||||
privateKey = (CPrivateKey) key;
|
privateKey = (CPrivateKey) key;
|
||||||
@ -197,7 +205,6 @@ abstract class CSignature extends SignatureSpi {
|
|||||||
boolean noHashOID = this instanceof NONEwithRSA;
|
boolean noHashOID = this instanceof NONEwithRSA;
|
||||||
|
|
||||||
// Sign hash using MS Crypto APIs
|
// Sign hash using MS Crypto APIs
|
||||||
|
|
||||||
byte[] result = signHash(noHashOID, hash, hash.length,
|
byte[] result = signHash(noHashOID, hash, hash.length,
|
||||||
messageDigestAlgorithm, privateKey.getHCryptProvider(),
|
messageDigestAlgorithm, privateKey.getHCryptProvider(),
|
||||||
privateKey.getHCryptKey());
|
privateKey.getHCryptKey());
|
||||||
@ -364,6 +371,106 @@ abstract class CSignature extends SignatureSpi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
public static final class PSS extends RSA {
|
||||||
|
|
||||||
private PSSParameterSpec pssParams = null;
|
private PSSParameterSpec pssParams = null;
|
||||||
@ -463,7 +570,7 @@ abstract class CSignature extends SignatureSpi {
|
|||||||
protected byte[] engineSign() throws SignatureException {
|
protected byte[] engineSign() throws SignatureException {
|
||||||
ensureInit();
|
ensureInit();
|
||||||
byte[] hash = getDigestValue();
|
byte[] hash = getDigestValue();
|
||||||
return signCngHash(hash, hash.length,
|
return signCngHash(2, hash, hash.length,
|
||||||
pssParams.getSaltLength(),
|
pssParams.getSaltLength(),
|
||||||
((MGF1ParameterSpec)
|
((MGF1ParameterSpec)
|
||||||
pssParams.getMGFParameters()).getDigestAlgorithm(),
|
pssParams.getMGFParameters()).getDigestAlgorithm(),
|
||||||
@ -479,7 +586,7 @@ abstract class CSignature extends SignatureSpi {
|
|||||||
} else {
|
} else {
|
||||||
byte[] hash = getDigestValue();
|
byte[] hash = getDigestValue();
|
||||||
return verifyCngSignedHash(
|
return verifyCngSignedHash(
|
||||||
hash, hash.length,
|
2, hash, hash.length,
|
||||||
sigBytes, sigBytes.length,
|
sigBytes, sigBytes.length,
|
||||||
pssParams.getSaltLength(),
|
pssParams.getSaltLength(),
|
||||||
((MGF1ParameterSpec)
|
((MGF1ParameterSpec)
|
||||||
@ -599,19 +706,22 @@ abstract class CSignature extends SignatureSpi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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(
|
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)
|
long hCryptProv, long nCryptKey)
|
||||||
throws SignatureException;
|
throws SignatureException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify a signed hash using CNG API with HCRYPTKEY. Used by RSASSA-PSS.
|
* Verify a signed hash using CNG API with HCRYPTKEY.
|
||||||
* This method is not used now. See {@link PSS#fallbackSignature}.
|
* @param type 0 no padding, 1, pkcs1, 2, pss
|
||||||
*/
|
*/
|
||||||
private native static boolean verifyCngSignedHash(
|
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,
|
int saltLength, String hashAlgorithm,
|
||||||
long hCryptProv, long hKey) throws SignatureException;
|
long hCryptProv, long hKey) throws SignatureException;
|
||||||
|
|
||||||
@ -804,4 +914,7 @@ abstract class CSignature extends SignatureSpi {
|
|||||||
// used by CRSACipher
|
// used by CRSACipher
|
||||||
static native CPublicKey importPublicKey(
|
static native CPublicKey importPublicKey(
|
||||||
String alg, byte[] keyBlob, int keySize) throws KeyStoreException;
|
String alg, byte[] keyBlob, int keySize) throws KeyStoreException;
|
||||||
|
|
||||||
|
static native CPublicKey importECPublicKey(
|
||||||
|
String alg, byte[] keyBlob, int keySize) throws KeyStoreException;
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,16 @@ public final class SunMSCAPI extends Provider {
|
|||||||
return new CSignature.MD2withRSA();
|
return new CSignature.MD2withRSA();
|
||||||
} else if (algo.equals("RSASSA-PSS")) {
|
} else if (algo.equals("RSASSA-PSS")) {
|
||||||
return new CSignature.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")) {
|
} else if (type.equals("KeyPairGenerator")) {
|
||||||
if (algo.equals("RSA")) {
|
if (algo.equals("RSA")) {
|
||||||
@ -188,7 +198,26 @@ public final class SunMSCAPI extends Provider {
|
|||||||
putService(new ProviderService(p, "Signature",
|
putService(new ProviderService(p, "Signature",
|
||||||
"MD2withRSA", "sun.security.mscapi.CSignature$MD2withRSA",
|
"MD2withRSA", "sun.security.mscapi.CSignature$MD2withRSA",
|
||||||
null, attrs));
|
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
|
* Key Pair Generator engines
|
||||||
*/
|
*/
|
||||||
|
@ -65,44 +65,53 @@
|
|||||||
__leave; \
|
__leave; \
|
||||||
}
|
}
|
||||||
|
|
||||||
//#define PP(fmt, ...) \
|
#define PP(fmt, ...) \
|
||||||
// fprintf(stdout, "MSCAPI (%ld): ", __LINE__); \
|
if (trace) { \
|
||||||
// fprintf(stdout, fmt, ##__VA_ARGS__); \
|
fprintf(stdout, "MSCAPI (%ld): ", __LINE__); \
|
||||||
// fprintf(stdout, "\n"); \
|
fprintf(stdout, fmt, ##__VA_ARGS__); \
|
||||||
// fflush(stdout)
|
fprintf(stdout, "\n"); \
|
||||||
|
fflush(stdout); \
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
char* trace = getenv("CAPI_TRACE");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Declare library specific JNI_Onload entry if static build
|
* Declare library specific JNI_Onload entry if static build
|
||||||
*/
|
*/
|
||||||
DEF_STATIC_JNI_OnLoad
|
DEF_STATIC_JNI_OnLoad
|
||||||
|
|
||||||
//void dump(LPSTR title, PBYTE data, DWORD len)
|
void showProperty(NCRYPT_HANDLE hKey);
|
||||||
//{
|
|
||||||
// printf("==== %s ====\n", title);
|
void dump(LPSTR title, PBYTE data, DWORD len)
|
||||||
// for (DWORD i = 0; i < len; i+=16) {
|
{
|
||||||
// printf("%04x: ", i);
|
if (trace) {
|
||||||
// for (int j = 0; j < 16; j++) {
|
printf("==== %s ====\n", title);
|
||||||
// if (j == 8) {
|
for (DWORD i = 0; i < len; i+=16) {
|
||||||
// printf(" ");
|
printf("%04x: ", i);
|
||||||
// }
|
for (int j = 0; j < 16; j++) {
|
||||||
// if (i + j < len) {
|
if (j == 8) {
|
||||||
// printf("%02X ", *(data + i + j) & 0xff);
|
printf(" ");
|
||||||
// } else {
|
}
|
||||||
// printf(" ");
|
if (i + j < len) {
|
||||||
// }
|
printf("%02X ", *(data + i + j) & 0xff);
|
||||||
// }
|
} else {
|
||||||
// for (int j = 0; j < 16; j++) {
|
printf(" ");
|
||||||
// if (i + j < len) {
|
}
|
||||||
// int k = *(data + i + j) & 0xff;
|
}
|
||||||
// if (k < 32 || k > 127) printf(".");
|
for (int j = 0; j < 16; j++) {
|
||||||
// else printf("%c", (char)k);
|
if (i + j < len) {
|
||||||
// }
|
int k = *(data + i + j) & 0xff;
|
||||||
// }
|
if (k < 32 || k > 127) printf(".");
|
||||||
// printf("\n");
|
else printf("%c", (char)k);
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Throws an arbitrary Java exception with the given message.
|
* Throws an arbitrary Java exception with the given message.
|
||||||
@ -445,10 +454,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateC
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Determine method ID to generate RSA certificate chain
|
// Determine method ID to generate RSA certificate chain
|
||||||
jmethodID mGenRSAKeyAndCertChain = env->GetMethodID(clazzOfThis,
|
jmethodID mGenKeyAndCertChain = env->GetMethodID(clazzOfThis,
|
||||||
"generateRSAKeyAndCertificateChain",
|
"generateKeyAndCertificateChain",
|
||||||
"(Ljava/lang/String;JJILjava/util/Collection;)V");
|
"(ZLjava/lang/String;JJILjava/util/Collection;)V");
|
||||||
if (mGenRSAKeyAndCertChain == NULL) {
|
if (mGenKeyAndCertChain == NULL) {
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,6 +466,7 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateC
|
|||||||
// NULL to retrieve the first certificate in the store.
|
// NULL to retrieve the first certificate in the store.
|
||||||
while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext))
|
while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext))
|
||||||
{
|
{
|
||||||
|
PP("--------------------------");
|
||||||
// Check if private key available - client authentication certificate
|
// Check if private key available - client authentication certificate
|
||||||
// must have private key available.
|
// must have private key available.
|
||||||
HCRYPTPROV hCryptProv = NULL;
|
HCRYPTPROV hCryptProv = NULL;
|
||||||
@ -467,10 +477,12 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateC
|
|||||||
DWORD dwPublicKeyLength = 0;
|
DWORD dwPublicKeyLength = 0;
|
||||||
|
|
||||||
// First, probe it silently
|
// 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
|
&hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE
|
||||||
&& GetLastError() != NTE_SILENT_CONTEXT)
|
&& GetLastError() != NTE_SILENT_CONTEXT)
|
||||||
{
|
{
|
||||||
|
PP("bHasNoPrivateKey = TRUE!");
|
||||||
bHasNoPrivateKey = TRUE;
|
bHasNoPrivateKey = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -481,27 +493,32 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateC
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Second, acquire the key normally (not silently)
|
// 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)
|
&hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE)
|
||||||
{
|
{
|
||||||
|
PP("bHasNoPrivateKey = TRUE!!");
|
||||||
bHasNoPrivateKey = TRUE;
|
bHasNoPrivateKey = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Private key is available
|
if ((dwKeySpec & CERT_NCRYPT_KEY_SPEC) == CERT_NCRYPT_KEY_SPEC) {
|
||||||
BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey); //deprecated
|
PP("CNG %I64d", hCryptProv);
|
||||||
|
} else {
|
||||||
|
// Private key is available
|
||||||
|
BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey); //deprecated
|
||||||
|
|
||||||
// Skip certificate if cannot find private key
|
// Skip certificate if cannot find private key
|
||||||
if (bGetUserKey == FALSE) {
|
if (bGetUserKey == FALSE) {
|
||||||
if (bCallerFreeProv)
|
if (bCallerFreeProv)
|
||||||
::CryptReleaseContext(hCryptProv, NULL); // deprecated
|
::CryptReleaseContext(hCryptProv, NULL); // deprecated
|
||||||
continue;
|
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
|
// 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,
|
// determine the key length by using the private key handle. However,
|
||||||
// since public/private key pairs must have the same length, we could
|
// since public/private key pairs must have the same length, we could
|
||||||
@ -573,6 +590,7 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateC
|
|||||||
env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList);
|
env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PP("%s: %s", pszNameString, pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
|
||||||
if (bHasNoPrivateKey)
|
if (bHasNoPrivateKey)
|
||||||
{
|
{
|
||||||
// Generate certificate chain and store into cert chain
|
// Generate certificate chain and store into cert chain
|
||||||
@ -583,19 +601,40 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateC
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Determine key type: RSA or DSA
|
if (hUserKey) {
|
||||||
DWORD dwData = CALG_RSA_KEYX;
|
// Only accept RSA for CAPI
|
||||||
DWORD dwSize = sizeof(DWORD);
|
DWORD dwData = CALG_RSA_KEYX;
|
||||||
::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData, //deprecated
|
DWORD dwSize = sizeof(DWORD);
|
||||||
&dwSize, NULL);
|
::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData, //deprecated
|
||||||
if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)
|
&dwSize, NULL);
|
||||||
{
|
if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)
|
||||||
// Generate RSA certificate chain and store into cert
|
{
|
||||||
// chain collection
|
// Generate RSA certificate chain and store into cert
|
||||||
env->CallVoidMethod(obj, mGenRSAKeyAndCertChain,
|
// chain collection
|
||||||
env->NewStringUTF(pszNameString),
|
env->CallVoidMethod(obj, mGenKeyAndCertChain,
|
||||||
(jlong) hCryptProv, (jlong) hUserKey,
|
1,
|
||||||
dwPublicKeyLength, jArrayList);
|
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 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateC
|
|||||||
// Free cert chain
|
// Free cert chain
|
||||||
if (pCertChainContext)
|
if (pCertChainContext)
|
||||||
::CertFreeCertificateChain(pCertChainContext);
|
::CertFreeCertificateChain(pCertChainContext);
|
||||||
|
} else {
|
||||||
|
PP("GetCertificateChain failed %d", GetLastError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -768,10 +809,10 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signHash
|
|||||||
/*
|
/*
|
||||||
* Class: sun_security_mscapi_CSignature
|
* Class: sun_security_mscapi_CSignature
|
||||||
* Method: signCngHash
|
* Method: signCngHash
|
||||||
* Signature: ([BIILjava/lang/String;JJ)[B
|
* Signature: (I[BIILjava/lang/String;JJ)[B
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signCngHash
|
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,
|
jint jHashSize, jint saltLen, jstring jHashAlgorithm, jlong hCryptProv,
|
||||||
jlong hCryptKey)
|
jlong hCryptKey)
|
||||||
{
|
{
|
||||||
@ -783,13 +824,17 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signCngHash
|
|||||||
|
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
SS_CHECK(::NCryptTranslateHandle(
|
if (hCryptKey == 0) {
|
||||||
|
hk = (NCRYPT_KEY_HANDLE)hCryptProv;
|
||||||
|
} else {
|
||||||
|
SS_CHECK(::NCryptTranslateHandle(
|
||||||
NULL,
|
NULL,
|
||||||
&hk,
|
&hk,
|
||||||
hCryptProv,
|
hCryptProv,
|
||||||
hCryptKey,
|
hCryptKey,
|
||||||
NULL,
|
NULL,
|
||||||
0));
|
0));
|
||||||
|
}
|
||||||
|
|
||||||
// Copy hash from Java to native buffer
|
// Copy hash from Java to native buffer
|
||||||
pHashBuffer = new (env) jbyte[jHashSize];
|
pHashBuffer = new (env) jbyte[jHashSize];
|
||||||
@ -798,43 +843,66 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signCngHash
|
|||||||
}
|
}
|
||||||
env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
|
env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
|
||||||
|
|
||||||
BCRYPT_PSS_PADDING_INFO pssInfo;
|
VOID* param;
|
||||||
pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
|
DWORD dwFlags;
|
||||||
pssInfo.cbSalt = saltLen;
|
|
||||||
|
|
||||||
if (pssInfo.pszAlgId == NULL) {
|
switch (type) {
|
||||||
ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
|
case 0:
|
||||||
"Unrecognised hash algorithm");
|
param = NULL;
|
||||||
__leave;
|
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(
|
SS_CHECK(::NCryptSignHash(
|
||||||
hk,
|
hk,
|
||||||
&pssInfo,
|
param,
|
||||||
(BYTE*)pHashBuffer, jHashSize,
|
(BYTE*)pHashBuffer, jHashSize,
|
||||||
NULL, 0, &dwBufLen,
|
NULL, 0, &jSignedHashSize,
|
||||||
BCRYPT_PAD_PSS
|
dwFlags
|
||||||
));
|
));
|
||||||
|
|
||||||
pSignedHashBuffer = new (env) jbyte[dwBufLen];
|
pSignedHashBuffer = new (env) jbyte[jSignedHashSize];
|
||||||
if (pSignedHashBuffer == NULL) {
|
if (pSignedHashBuffer == NULL) {
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
SS_CHECK(::NCryptSignHash(
|
SS_CHECK(::NCryptSignHash(
|
||||||
hk,
|
hk,
|
||||||
&pssInfo,
|
param,
|
||||||
(BYTE*)pHashBuffer, jHashSize,
|
(BYTE*)pHashBuffer, jHashSize,
|
||||||
(BYTE*)pSignedHashBuffer, dwBufLen, &dwBufLen,
|
(BYTE*)pSignedHashBuffer, jSignedHashSize, &jSignedHashSize,
|
||||||
BCRYPT_PAD_PSS
|
dwFlags
|
||||||
));
|
));
|
||||||
|
|
||||||
// Create new byte array
|
// Create new byte array
|
||||||
jbyteArray temp = env->NewByteArray(dwBufLen);
|
jbyteArray temp = env->NewByteArray(jSignedHashSize);
|
||||||
|
|
||||||
// Copy data from native buffer
|
// Copy data from native buffer
|
||||||
env->SetByteArrayRegion(temp, 0, dwBufLen, pSignedHashBuffer);
|
env->SetByteArrayRegion(temp, 0, jSignedHashSize, pSignedHashBuffer);
|
||||||
|
|
||||||
jSignedHash = temp;
|
jSignedHash = temp;
|
||||||
}
|
}
|
||||||
@ -846,7 +914,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signCngHash
|
|||||||
if (pHashBuffer)
|
if (pHashBuffer)
|
||||||
delete [] pHashBuffer;
|
delete [] pHashBuffer;
|
||||||
|
|
||||||
if (hk != NULL)
|
if (hCryptKey != 0 && hk != NULL)
|
||||||
::NCryptFreeObject(hk);
|
::NCryptFreeObject(hk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -961,10 +1029,10 @@ JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifySignedHash
|
|||||||
/*
|
/*
|
||||||
* Class: sun_security_mscapi_CSignature
|
* Class: sun_security_mscapi_CSignature
|
||||||
* Method: verifyCngSignedHash
|
* 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
|
JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifyCngSignedHash
|
||||||
(JNIEnv *env, jclass clazz,
|
(JNIEnv *env, jclass clazz, jint type,
|
||||||
jbyteArray jHash, jint jHashSize,
|
jbyteArray jHash, jint jHashSize,
|
||||||
jbyteArray jSignedHash, jint jSignedHashSize,
|
jbyteArray jSignedHash, jint jSignedHashSize,
|
||||||
jint saltLen, jstring jHashAlgorithm,
|
jint saltLen, jstring jHashAlgorithm,
|
||||||
@ -977,13 +1045,17 @@ JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifyCngSignedHa
|
|||||||
|
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
SS_CHECK(::NCryptTranslateHandle(
|
if (hCryptKey == 0) {
|
||||||
|
hk = (NCRYPT_KEY_HANDLE)hCryptProv;
|
||||||
|
} else {
|
||||||
|
SS_CHECK(::NCryptTranslateHandle(
|
||||||
NULL,
|
NULL,
|
||||||
&hk,
|
&hk,
|
||||||
hCryptProv,
|
hCryptProv,
|
||||||
hCryptKey,
|
hCryptKey,
|
||||||
NULL,
|
NULL,
|
||||||
0));
|
0));
|
||||||
|
}
|
||||||
|
|
||||||
// Copy hash and signedHash from Java to native buffer
|
// Copy hash and signedHash from Java to native buffer
|
||||||
pHashBuffer = new (env) jbyte[jHashSize];
|
pHashBuffer = new (env) jbyte[jHashSize];
|
||||||
@ -999,19 +1071,43 @@ JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifyCngSignedHa
|
|||||||
env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,
|
env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,
|
||||||
pSignedHashBuffer);
|
pSignedHashBuffer);
|
||||||
|
|
||||||
BCRYPT_PSS_PADDING_INFO pssInfo;
|
VOID* param;
|
||||||
pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
|
DWORD dwFlags;
|
||||||
pssInfo.cbSalt = saltLen;
|
|
||||||
if (pssInfo.pszAlgId == NULL) {
|
switch (type) {
|
||||||
ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
|
case 0:
|
||||||
"Unrecognised hash algorithm");
|
param = NULL;
|
||||||
__leave;
|
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 *) pHashBuffer, jHashSize,
|
||||||
(BYTE *) pSignedHashBuffer, jSignedHashSize,
|
(BYTE *) pSignedHashBuffer, jSignedHashSize,
|
||||||
NCRYPT_PAD_PSS_FLAG) == ERROR_SUCCESS)
|
dwFlags) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
result = JNI_TRUE;
|
result = JNI_TRUE;
|
||||||
}
|
}
|
||||||
@ -1025,13 +1121,108 @@ JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifyCngSignedHa
|
|||||||
if (pHashBuffer)
|
if (pHashBuffer)
|
||||||
delete [] pHashBuffer;
|
delete [] pHashBuffer;
|
||||||
|
|
||||||
if (hk != NULL)
|
if (hCryptKey != 0 && hk != NULL)
|
||||||
::NCryptFreeObject(hk);
|
::NCryptFreeObject(hk);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
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
|
* Class: sun_security_mscapi_CKeyPairGenerator_RSA
|
||||||
* Method: generateCKeyPair
|
* Method: generateCKeyPair
|
||||||
@ -1673,10 +1864,10 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_encryptDecrypt
|
|||||||
/*
|
/*
|
||||||
* Class: sun_security_mscapi_CPublicKey
|
* Class: sun_security_mscapi_CPublicKey
|
||||||
* Method: getPublicKeyBlob
|
* Method: getPublicKeyBlob
|
||||||
* Signature: (J)[B
|
* Signature: (JJ)[B
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_getPublicKeyBlob
|
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;
|
jbyteArray blob = NULL;
|
||||||
DWORD dwBlobLen;
|
DWORD dwBlobLen;
|
||||||
@ -1686,11 +1877,17 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_getPublicKeyBlo
|
|||||||
{
|
{
|
||||||
|
|
||||||
// Determine the size of the blob
|
// Determine the size of the blob
|
||||||
if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, NULL, //deprecated
|
if (hCryptKey == 0) {
|
||||||
&dwBlobLen)) {
|
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());
|
ThrowException(env, KEY_EXCEPTION, GetLastError());
|
||||||
__leave;
|
__leave;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pbKeyBlob = new (env) BYTE[dwBlobLen];
|
pbKeyBlob = new (env) BYTE[dwBlobLen];
|
||||||
@ -1699,11 +1896,17 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_getPublicKeyBlo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate key blob
|
// Generate key blob
|
||||||
if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, //deprecated
|
if (hCryptKey == 0) {
|
||||||
pbKeyBlob, &dwBlobLen)) {
|
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());
|
ThrowException(env, KEY_EXCEPTION, GetLastError());
|
||||||
__leave;
|
__leave;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new byte array
|
// Create new byte array
|
||||||
@ -2175,6 +2378,66 @@ JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CKeyStore_storePrivateKey
|
|||||||
return privateKey;
|
return privateKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* Class: sun_security_mscapi_CSignature
|
||||||
* Method: importPublicKey
|
* Method: importPublicKey
|
||||||
|
Loading…
x
Reference in New Issue
Block a user