Skip to content

Commit

Permalink
the code change
Browse files Browse the repository at this point in the history
  • Loading branch information
wangweij committed Feb 14, 2025
1 parent 6ddbcc3 commit 60f7616
Show file tree
Hide file tree
Showing 10 changed files with 192 additions and 36 deletions.
13 changes: 2 additions & 11 deletions src/java.base/share/classes/sun/security/ec/ECPrivateKeyImpl.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2025, 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
Expand Down Expand Up @@ -35,8 +35,6 @@
import java.security.spec.*;
import java.util.Arrays;

import sun.security.ec.point.AffinePoint;
import sun.security.ec.point.MutablePoint;
import sun.security.util.*;
import sun.security.x509.AlgorithmId;
import sun.security.pkcs.PKCS8Key;
Expand Down Expand Up @@ -207,15 +205,8 @@ private void parseKeyBits() throws InvalidKeyException {

@Override
public PublicKey calculatePublicKey() {
ECParameterSpec ecParams = getParams();
ECOperations ops = ECOperations.forParameters(ecParams)
.orElseThrow(ProviderException::new);
MutablePoint pub = ops.multiply(ecParams.getGenerator(), getArrayS0());
AffinePoint affPub = pub.asAffine();
ECPoint w = new ECPoint(affPub.getX().asBigInteger(),
affPub.getY().asBigInteger());
try {
return new ECPublicKeyImpl(w, ecParams);
return ECUtil.sArrayToPublicKey(getArrayS0(), getParams());
} catch (InvalidKeyException e) {
throw new ProviderException(
"Unexpected error calculating public key", e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2025, 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
Expand Down Expand Up @@ -58,9 +58,9 @@ public final class ECPublicKeyImpl extends X509Key implements ECPublicKey {

/**
* Construct a key from its components. Used by the
* ECKeyFactory.
* ECKeyFactory and ECUtil.
*/
ECPublicKeyImpl(ECPoint w, ECParameterSpec params)
public ECPublicKeyImpl(ECPoint w, ECParameterSpec params)
throws InvalidKeyException {
this.w = w;
this.params = params;
Expand Down Expand Up @@ -142,4 +142,4 @@ private void readObject(ObjectInputStream stream)
throw new InvalidObjectException(
"ECPublicKeyImpl keys are not directly deserializable");
}
}
}
18 changes: 17 additions & 1 deletion src/java.base/share/classes/sun/security/util/ECUtil.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2025, 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
Expand All @@ -26,6 +26,10 @@
package sun.security.util;

import jdk.internal.access.SharedSecrets;
import sun.security.ec.ECOperations;
import sun.security.ec.ECPublicKeyImpl;
import sun.security.ec.point.AffinePoint;
import sun.security.ec.point.MutablePoint;

import java.io.IOException;
import java.math.BigInteger;
Expand Down Expand Up @@ -375,5 +379,17 @@ public static void validatePublicKey(ECPoint point, ECParameterSpec spec)
}
}

// Calculate an ECPublicKey from the private sArray component
public static ECPublicKey sArrayToPublicKey(byte[] sArray, ECParameterSpec params)
throws InvalidKeyException {
ECOperations ops = ECOperations.forParameters(params)
.orElseThrow(ProviderException::new);
MutablePoint pub = ops.multiply(params.getGenerator(), sArray);
AffinePoint affPub = pub.asAffine();
ECPoint w = new ECPoint(affPub.getX().asBigInteger(),
affPub.getY().asBigInteger());
return new ECPublicKeyImpl(w, params);
}

private ECUtil() {}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2025, 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
Expand Down Expand Up @@ -267,8 +267,14 @@ private PrivateKey generatePrivate(BigInteger s, ECParameterSpec params)
try {
session = token.getObjSession();
long keyID = token.p11.C_CreateObject(session.id(), attributes);
PublicKey pk = null;
try {
pk = ECUtil.sArrayToPublicKey(ECUtil.sArray(s, params), params);
} catch (Exception e) {
// Happens when params is not supported. Ignore it.
}
return P11Key.privateKey
(session, keyID, "EC", params.getCurve().getField().getFieldSize(), attributes);
(session, keyID, "EC", params.getCurve().getField().getFieldSize(), attributes, pk);
} finally {
token.releaseSession(session);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;

import sun.security.util.DerValue;
import sun.security.util.InternalPrivateKey;
import sun.security.util.Length;
import sun.security.util.ECUtil;
import sun.security.jca.JCAUtil;
Expand Down Expand Up @@ -399,6 +400,13 @@ static PublicKey publicKey(Session session, long keyID, String algorithm,

static PrivateKey privateKey(Session session, long keyID, String algorithm,
int keyLength, CK_ATTRIBUTE[] attrs) {
return privateKey(session, keyID, algorithm, keyLength, attrs, null);
}

// Create a PrivateKey with an optional PublicKey. The PublicKey is only
// added to EC keys at the moment.
static PrivateKey privateKey(Session session, long keyID, String algorithm,
int keyLength, CK_ATTRIBUTE[] attrs, PublicKey pk) {
attrs = getAttributes(session, keyID, attrs, new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_TOKEN),
new CK_ATTRIBUTE(CKA_SENSITIVE),
Expand All @@ -417,7 +425,7 @@ static PrivateKey privateKey(Session session, long keyID, String algorithm,
case "DH" -> P11DHPrivateKeyInternal.of(session, keyID, algorithm,
keyLength, attrs, keySensitive);
case "EC" -> P11ECPrivateKeyInternal.of(session, keyID, algorithm,
keyLength, attrs, keySensitive);
keyLength, attrs, keySensitive, pk);
default -> throw new ProviderException
("Unknown private key algorithm " + algorithm);
};
Expand Down Expand Up @@ -1201,28 +1209,31 @@ public boolean equals(Object obj) {
}
}

static class P11ECPrivateKeyInternal extends P11PrivateKey {
static class P11ECPrivateKeyInternal extends P11PrivateKey
implements InternalPrivateKey {

@Serial
private static final long serialVersionUID = 1L;

private final PublicKey pk;
protected transient ECParameterSpec params;

static P11ECPrivateKeyInternal of(Session session, long keyID,
String algorithm, int keyLength, CK_ATTRIBUTE[] attrs,
boolean keySensitive) {
boolean keySensitive, PublicKey pk) {
if (keySensitive) {
return new P11ECPrivateKeyInternal(session, keyID, algorithm,
keyLength, attrs);
keyLength, attrs, pk);
} else {
return new P11ECPrivateKey(session, keyID, algorithm,
keyLength, attrs);
keyLength, attrs, pk);
}
}

private P11ECPrivateKeyInternal(Session session, long keyID,
String algorithm, int keyLength, CK_ATTRIBUTE[] attrs) {
String algorithm, int keyLength, CK_ATTRIBUTE[] attrs, PublicKey pk) {
super(session, keyID, algorithm, keyLength, attrs);
this.pk = pk;
}

private synchronized void fetchValues() {
Expand All @@ -1245,6 +1256,11 @@ public ECParameterSpec getParams() {
fetchValues();
return params;
}

@Override
public PublicKey calculatePublicKey() {
return pk;
}
}

private static final class P11ECPrivateKey extends P11ECPrivateKeyInternal
Expand All @@ -1255,8 +1271,8 @@ private static final class P11ECPrivateKey extends P11ECPrivateKeyInternal
private transient BigInteger s; // params in P11ECPrivateKeyInternal

P11ECPrivateKey(Session session, long keyID, String algorithm,
int keyLength, CK_ATTRIBUTE[] attrs) {
super(session, keyID, algorithm, keyLength, attrs);
int keyLength, CK_ATTRIBUTE[] attrs, PublicKey pk) {
super(session, keyID, algorithm, keyLength, attrs, pk);
}

private synchronized void fetchValues() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2025, 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
Expand Down Expand Up @@ -427,7 +427,7 @@ public KeyPair generateKeyPair() {
PublicKey publicKey = P11Key.publicKey
(session, keyIDs[0], algorithm, keySize, publicKeyTemplate);
PrivateKey privateKey = P11Key.privateKey
(session, keyIDs[1], algorithm, keySize, privateKeyTemplate);
(session, keyIDs[1], algorithm, keySize, privateKeyTemplate, publicKey);
return new KeyPair(publicKey, privateKey);
} catch (PKCS11Exception e) {
throw new ProviderException(e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2025, 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
Expand Down Expand Up @@ -313,7 +313,7 @@ public synchronized Key engineGetKey(String alias, char[] password)
aliasInfo.id,
null);
if (h.type == ATTR_CLASS_PKEY) {
return loadPkey(session, h.handle);
return loadPkey(session, h.handle, aliasInfo.cert.getPublicKey());
}
} else {
THandle h = getTokenObject(session,
Expand Down Expand Up @@ -968,8 +968,8 @@ public synchronized KeyStore.Entry engineGetEntry(String alias,
throw new KeyStoreException
("expected but could not find private key");
} else {
PrivateKey pkey = loadPkey(session, h.handle);
Certificate[] chain = aliasInfo.chain;
PrivateKey pkey = loadPkey(session, h.handle, chain[0].getPublicKey());
if ((pkey != null) && (chain != null)) {
return new KeyStore.PrivateKeyEntry(pkey, chain);
} else {
Expand Down Expand Up @@ -1305,7 +1305,7 @@ private SecretKey loadSkey(Session session, long oHandle)
return P11Key.secretKey(session, oHandle, keyType, keyLength, null);
}

private PrivateKey loadPkey(Session session, long oHandle)
private PrivateKey loadPkey(Session session, long oHandle, PublicKey pk)
throws PKCS11Exception, KeyStoreException {

CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
Expand Down Expand Up @@ -1385,7 +1385,7 @@ private PrivateKey loadPkey(Session session, long oHandle)
throw new KeyStoreException("Unsupported parameters", e);
}

return P11Key.privateKey(session, oHandle, "EC", keyLength, null);
return P11Key.privateKey(session, oHandle, "EC", keyLength, null, pk);

} else {
if (debug != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2025, 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
Expand Down Expand Up @@ -795,6 +795,7 @@ protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgo,
return (switch(wrappedKeyType) {
case Cipher.PRIVATE_KEY -> P11Key.privateKey
(session, unwrappedKeyID, wrappedKeyAlgo, -1, attributes);
// in this case, there is no way to get the associated public key
case Cipher.SECRET_KEY -> P11Key.secretKey
(session, unwrappedKeyID, wrappedKeyAlgo, -1, attributes);
default -> null;
Expand Down
34 changes: 32 additions & 2 deletions test/jdk/sun/security/pkcs11/KeyStore/Basic.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2025, 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
Expand All @@ -22,7 +22,7 @@
*/

/* @test
* @bug 4938185
* @bug 4938185 8350134
* @summary KeyStore support for NSS cert/key databases
* To run manually:
* set environment variable:
Expand All @@ -33,6 +33,10 @@
* . 'list' lists the token aliases
* . 'basic' does not run with activcard,
* @library /test/lib ..
* @modules jdk.crypto.cryptoki
* java.base/sun.security.tools.keytool
* java.base/sun.security.util
* java.base/sun.security.x509
* @run testng/othervm Basic
*/

Expand Down Expand Up @@ -62,6 +66,9 @@
import org.testng.SkipException;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import sun.security.tools.keytool.CertAndKeyGen;
import sun.security.util.InternalPrivateKey;
import sun.security.x509.X500Name;


public class Basic extends PKCS11Test {
Expand Down Expand Up @@ -239,6 +246,7 @@ private static void doTest() throws Exception {
testnum = Basic.pkey(testnum);
testnum = Basic.sign(testnum);
testnum = Basic.copy(testnum);
testnum = Basic.calculatePublicKey(testnum);
} else if ("solaris".equals(token)) {
testnum = Basic.setAttribute(testnum);
testnum = Basic.pkey(testnum);
Expand Down Expand Up @@ -913,6 +921,28 @@ private static int pkey(int testnum) throws Exception {
return testnum;
}

private static int calculatePublicKey(int testnum) throws Exception {
System.out.println("check calculatePublicKey in keystore");
var kag = new CertAndKeyGen("EC", "SHA256withECDSA");
kag.generate(-1);

ks.setKeyEntry("a2", kag.getPrivateKey(), null,
new Certificate[] {kag.getSelfCertificate(new X500Name("CN=Me"), 1000)});
var sk = ks.getKey("a2", null);
if (sk instanceof InternalPrivateKey ipk) {
var pk = ipk.calculatePublicKey();
var cert = ks.getCertificate("a2");
if (!cert.getPublicKey().equals(pk)) {
throw new SecurityException("Associated public key is not correct");
}
} else {
throw new SecurityException("Not an InternalPrivateKey");
}
System.out.println("test " + testnum++ + " passed");

return testnum;
}

private static int extended(int testnum) throws Exception {

// setEntry unknown entry type
Expand Down
Loading

0 comments on commit 60f7616

Please sign in to comment.