7196382: PKCS11 provider should support 2048-bit DH
Query and enforce range checking using the values from native PKCS11 library. Reviewed-by: xuelei
This commit is contained in:
parent
31fdd1b27c
commit
2f4af22f17
@ -58,6 +58,16 @@ extends AlgorithmParameterGeneratorSpi {
|
|||||||
// The source of randomness
|
// The source of randomness
|
||||||
private SecureRandom random = null;
|
private SecureRandom random = null;
|
||||||
|
|
||||||
|
private static void checkKeySize(int keysize)
|
||||||
|
throws InvalidAlgorithmParameterException {
|
||||||
|
if ((keysize != 2048) &&
|
||||||
|
((keysize < 512) || (keysize > 1024) || (keysize % 64 != 0))) {
|
||||||
|
throw new InvalidAlgorithmParameterException(
|
||||||
|
"Keysize must be multiple of 64 ranging from "
|
||||||
|
+ "512 to 1024 (inclusive), or 2048");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes this parameter generator for a certain keysize
|
* Initializes this parameter generator for a certain keysize
|
||||||
* and source of randomness.
|
* and source of randomness.
|
||||||
@ -67,11 +77,11 @@ extends AlgorithmParameterGeneratorSpi {
|
|||||||
* @param random the source of randomness
|
* @param random the source of randomness
|
||||||
*/
|
*/
|
||||||
protected void engineInit(int keysize, SecureRandom random) {
|
protected void engineInit(int keysize, SecureRandom random) {
|
||||||
if ((keysize < 512) || (keysize > 2048) || (keysize % 64 != 0)) {
|
// Re-uses DSA parameters and thus have the same range
|
||||||
throw new InvalidParameterException("Keysize must be multiple "
|
try {
|
||||||
+ "of 64, and can only range "
|
checkKeySize(keysize);
|
||||||
+ "from 512 to 2048 "
|
} catch (InvalidAlgorithmParameterException ex) {
|
||||||
+ "(inclusive)");
|
throw new InvalidParameterException(ex.getMessage());
|
||||||
}
|
}
|
||||||
this.primeSize = keysize;
|
this.primeSize = keysize;
|
||||||
this.random = random;
|
this.random = random;
|
||||||
@ -99,11 +109,9 @@ extends AlgorithmParameterGeneratorSpi {
|
|||||||
DHGenParameterSpec dhParamSpec = (DHGenParameterSpec)genParamSpec;
|
DHGenParameterSpec dhParamSpec = (DHGenParameterSpec)genParamSpec;
|
||||||
|
|
||||||
primeSize = dhParamSpec.getPrimeSize();
|
primeSize = dhParamSpec.getPrimeSize();
|
||||||
if ((primeSize<512) || (primeSize>2048) || (primeSize%64 != 0)) {
|
|
||||||
throw new InvalidAlgorithmParameterException
|
// Re-uses DSA parameters and thus have the same range
|
||||||
("Modulus size must be multiple of 64, and can only range "
|
checkKeySize(primeSize);
|
||||||
+ "from 512 to 2048 (inclusive)");
|
|
||||||
}
|
|
||||||
|
|
||||||
exponentSize = dhParamSpec.getExponentSize();
|
exponentSize = dhParamSpec.getExponentSize();
|
||||||
if (exponentSize <= 0) {
|
if (exponentSize <= 0) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, 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
|
||||||
@ -70,20 +70,67 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
|||||||
// for RSA, selected or default value of public exponent, always valid
|
// for RSA, selected or default value of public exponent, always valid
|
||||||
private BigInteger rsaPublicExponent = RSAKeyGenParameterSpec.F4;
|
private BigInteger rsaPublicExponent = RSAKeyGenParameterSpec.F4;
|
||||||
|
|
||||||
|
// the supported keysize range of the native PKCS11 library
|
||||||
|
// if the value cannot be retrieved or unspecified, -1 is used.
|
||||||
|
private final int minKeySize;
|
||||||
|
private final int maxKeySize;
|
||||||
|
|
||||||
// SecureRandom instance, if specified in init
|
// SecureRandom instance, if specified in init
|
||||||
private SecureRandom random;
|
private SecureRandom random;
|
||||||
|
|
||||||
P11KeyPairGenerator(Token token, String algorithm, long mechanism)
|
P11KeyPairGenerator(Token token, String algorithm, long mechanism)
|
||||||
throws PKCS11Exception {
|
throws PKCS11Exception {
|
||||||
super();
|
super();
|
||||||
|
int minKeyLen = -1;
|
||||||
|
int maxKeyLen = -1;
|
||||||
|
try {
|
||||||
|
CK_MECHANISM_INFO mechInfo = token.getMechanismInfo(mechanism);
|
||||||
|
if (mechInfo != null) {
|
||||||
|
minKeyLen = (int) mechInfo.ulMinKeySize;
|
||||||
|
maxKeyLen = (int) mechInfo.ulMaxKeySize;
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception p11e) {
|
||||||
|
// Should never happen
|
||||||
|
throw new ProviderException
|
||||||
|
("Unexpected error while getting mechanism info", p11e);
|
||||||
|
}
|
||||||
|
// set default key sizes and apply our own algorithm-specific limits
|
||||||
|
// override lower limit to disallow unsecure keys being generated
|
||||||
|
// override upper limit to deter DOS attack
|
||||||
|
if (algorithm.equals("EC")) {
|
||||||
|
keySize = 256;
|
||||||
|
if ((minKeyLen == -1) || (minKeyLen < 112)) {
|
||||||
|
minKeyLen = 112;
|
||||||
|
}
|
||||||
|
if ((maxKeyLen == -1) || (maxKeyLen > 2048)) {
|
||||||
|
maxKeyLen = 2048;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// RSA, DH, and DSA
|
||||||
|
keySize = 1024;
|
||||||
|
if ((minKeyLen == -1) || (minKeyLen < 512)) {
|
||||||
|
minKeyLen = 512;
|
||||||
|
}
|
||||||
|
if (algorithm.equals("RSA")) {
|
||||||
|
if ((maxKeyLen == -1) || (maxKeyLen > 64 * 1024)) {
|
||||||
|
maxKeyLen = 64 * 1024;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto-adjust default keysize in case it's out-of-range
|
||||||
|
if ((minKeyLen != -1) && (keySize < minKeyLen)) {
|
||||||
|
keySize = minKeyLen;
|
||||||
|
}
|
||||||
|
if ((maxKeyLen != -1) && (keySize > maxKeyLen)) {
|
||||||
|
keySize = maxKeyLen;
|
||||||
|
}
|
||||||
this.token = token;
|
this.token = token;
|
||||||
this.algorithm = algorithm;
|
this.algorithm = algorithm;
|
||||||
this.mechanism = mechanism;
|
this.mechanism = mechanism;
|
||||||
if (algorithm.equals("EC")) {
|
this.minKeySize = minKeyLen;
|
||||||
initialize(256, null);
|
this.maxKeySize = maxKeyLen;
|
||||||
} else {
|
initialize(keySize, null);
|
||||||
initialize(1024, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCA spec
|
// see JCA spec
|
||||||
@ -94,9 +141,7 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
|||||||
} catch (InvalidAlgorithmParameterException e) {
|
} catch (InvalidAlgorithmParameterException e) {
|
||||||
throw new InvalidParameterException(e.getMessage());
|
throw new InvalidParameterException(e.getMessage());
|
||||||
}
|
}
|
||||||
this.keySize = keySize;
|
|
||||||
this.params = null;
|
this.params = null;
|
||||||
this.random = random;
|
|
||||||
if (algorithm.equals("EC")) {
|
if (algorithm.equals("EC")) {
|
||||||
params = P11ECKeyFactory.getECParameterSpec(keySize);
|
params = P11ECKeyFactory.getECParameterSpec(keySize);
|
||||||
if (params == null) {
|
if (params == null) {
|
||||||
@ -105,33 +150,35 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
|||||||
+ keySize + " bits");
|
+ keySize + " bits");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.keySize = keySize;
|
||||||
|
this.random = random;
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCA spec
|
// see JCA spec
|
||||||
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
|
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
|
||||||
throws InvalidAlgorithmParameterException {
|
throws InvalidAlgorithmParameterException {
|
||||||
token.ensureValid();
|
token.ensureValid();
|
||||||
|
int tmpKeySize;
|
||||||
if (algorithm.equals("DH")) {
|
if (algorithm.equals("DH")) {
|
||||||
if (params instanceof DHParameterSpec == false) {
|
if (params instanceof DHParameterSpec == false) {
|
||||||
throw new InvalidAlgorithmParameterException
|
throw new InvalidAlgorithmParameterException
|
||||||
("DHParameterSpec required for Diffie-Hellman");
|
("DHParameterSpec required for Diffie-Hellman");
|
||||||
}
|
}
|
||||||
DHParameterSpec dhParams = (DHParameterSpec)params;
|
DHParameterSpec dhParams = (DHParameterSpec) params;
|
||||||
int tmpKeySize = dhParams.getP().bitLength();
|
tmpKeySize = dhParams.getP().bitLength();
|
||||||
checkKeySize(tmpKeySize, dhParams);
|
checkKeySize(tmpKeySize, null);
|
||||||
this.keySize = tmpKeySize;
|
|
||||||
this.params = dhParams;
|
|
||||||
// XXX sanity check params
|
// XXX sanity check params
|
||||||
} else if (algorithm.equals("RSA")) {
|
} else if (algorithm.equals("RSA")) {
|
||||||
if (params instanceof RSAKeyGenParameterSpec == false) {
|
if (params instanceof RSAKeyGenParameterSpec == false) {
|
||||||
throw new InvalidAlgorithmParameterException
|
throw new InvalidAlgorithmParameterException
|
||||||
("RSAKeyGenParameterSpec required for RSA");
|
("RSAKeyGenParameterSpec required for RSA");
|
||||||
}
|
}
|
||||||
RSAKeyGenParameterSpec rsaParams = (RSAKeyGenParameterSpec)params;
|
RSAKeyGenParameterSpec rsaParams =
|
||||||
int tmpKeySize = rsaParams.getKeysize();
|
(RSAKeyGenParameterSpec) params;
|
||||||
|
tmpKeySize = rsaParams.getKeysize();
|
||||||
checkKeySize(tmpKeySize, rsaParams);
|
checkKeySize(tmpKeySize, rsaParams);
|
||||||
this.keySize = tmpKeySize;
|
// override the supplied params to null
|
||||||
this.params = null;
|
params = null;
|
||||||
this.rsaPublicExponent = rsaParams.getPublicExponent();
|
this.rsaPublicExponent = rsaParams.getPublicExponent();
|
||||||
// XXX sanity check params
|
// XXX sanity check params
|
||||||
} else if (algorithm.equals("DSA")) {
|
} else if (algorithm.equals("DSA")) {
|
||||||
@ -139,11 +186,9 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
|||||||
throw new InvalidAlgorithmParameterException
|
throw new InvalidAlgorithmParameterException
|
||||||
("DSAParameterSpec required for DSA");
|
("DSAParameterSpec required for DSA");
|
||||||
}
|
}
|
||||||
DSAParameterSpec dsaParams = (DSAParameterSpec)params;
|
DSAParameterSpec dsaParams = (DSAParameterSpec) params;
|
||||||
int tmpKeySize = dsaParams.getP().bitLength();
|
tmpKeySize = dsaParams.getP().bitLength();
|
||||||
checkKeySize(tmpKeySize, dsaParams);
|
checkKeySize(tmpKeySize, null);
|
||||||
this.keySize = tmpKeySize;
|
|
||||||
this.params = dsaParams;
|
|
||||||
// XXX sanity check params
|
// XXX sanity check params
|
||||||
} else if (algorithm.equals("EC")) {
|
} else if (algorithm.equals("EC")) {
|
||||||
ECParameterSpec ecParams;
|
ECParameterSpec ecParams;
|
||||||
@ -155,28 +200,42 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
|||||||
("Unsupported curve: " + params);
|
("Unsupported curve: " + params);
|
||||||
}
|
}
|
||||||
} else if (params instanceof ECGenParameterSpec) {
|
} else if (params instanceof ECGenParameterSpec) {
|
||||||
String name = ((ECGenParameterSpec)params).getName();
|
String name = ((ECGenParameterSpec) params).getName();
|
||||||
ecParams = P11ECKeyFactory.getECParameterSpec(name);
|
ecParams = P11ECKeyFactory.getECParameterSpec(name);
|
||||||
if (ecParams == null) {
|
if (ecParams == null) {
|
||||||
throw new InvalidAlgorithmParameterException
|
throw new InvalidAlgorithmParameterException
|
||||||
("Unknown curve name: " + name);
|
("Unknown curve name: " + name);
|
||||||
}
|
}
|
||||||
|
// override the supplied params with the derived one
|
||||||
|
params = ecParams;
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidAlgorithmParameterException
|
throw new InvalidAlgorithmParameterException
|
||||||
("ECParameterSpec or ECGenParameterSpec required for EC");
|
("ECParameterSpec or ECGenParameterSpec required for EC");
|
||||||
}
|
}
|
||||||
int tmpKeySize = ecParams.getCurve().getField().getFieldSize();
|
tmpKeySize = ecParams.getCurve().getField().getFieldSize();
|
||||||
checkKeySize(tmpKeySize, ecParams);
|
checkKeySize(tmpKeySize, null);
|
||||||
this.keySize = tmpKeySize;
|
|
||||||
this.params = ecParams;
|
|
||||||
} else {
|
} else {
|
||||||
throw new ProviderException("Unknown algorithm: " + algorithm);
|
throw new ProviderException("Unknown algorithm: " + algorithm);
|
||||||
}
|
}
|
||||||
|
this.keySize = tmpKeySize;
|
||||||
|
this.params = params;
|
||||||
this.random = random;
|
this.random = random;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkKeySize(int keySize, AlgorithmParameterSpec params)
|
// NOTE: 'params' is only used for checking RSA keys currently.
|
||||||
|
private void checkKeySize(int keySize, RSAKeyGenParameterSpec params)
|
||||||
throws InvalidAlgorithmParameterException {
|
throws InvalidAlgorithmParameterException {
|
||||||
|
// check native range first
|
||||||
|
if ((minKeySize != -1) && (keySize < minKeySize)) {
|
||||||
|
throw new InvalidAlgorithmParameterException(algorithm +
|
||||||
|
" key must be at least " + minKeySize + " bits");
|
||||||
|
}
|
||||||
|
if ((maxKeySize != -1) && (keySize > maxKeySize)) {
|
||||||
|
throw new InvalidAlgorithmParameterException(algorithm +
|
||||||
|
" key must be at most " + maxKeySize + " bits");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check our own algorithm-specific limits also
|
||||||
if (algorithm.equals("EC")) {
|
if (algorithm.equals("EC")) {
|
||||||
if (keySize < 112) {
|
if (keySize < 112) {
|
||||||
throw new InvalidAlgorithmParameterException
|
throw new InvalidAlgorithmParameterException
|
||||||
@ -187,28 +246,28 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
|||||||
throw new InvalidAlgorithmParameterException
|
throw new InvalidAlgorithmParameterException
|
||||||
("Key size must be at most 2048 bit");
|
("Key size must be at most 2048 bit");
|
||||||
}
|
}
|
||||||
return;
|
} else {
|
||||||
} else if (algorithm.equals("RSA")) {
|
// RSA, DH, DSA
|
||||||
BigInteger tmpExponent = rsaPublicExponent;
|
|
||||||
if (params != null) {
|
|
||||||
// Already tested for instanceof RSAKeyGenParameterSpec above
|
|
||||||
tmpExponent =
|
|
||||||
((RSAKeyGenParameterSpec)params).getPublicExponent();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
// This provider supports 64K or less.
|
|
||||||
RSAKeyFactory.checkKeyLengths(keySize, tmpExponent,
|
|
||||||
512, 64 * 1024);
|
|
||||||
} catch (InvalidKeyException e) {
|
|
||||||
throw new InvalidAlgorithmParameterException(e.getMessage());
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keySize < 512) {
|
if (keySize < 512) {
|
||||||
throw new InvalidAlgorithmParameterException
|
throw new InvalidAlgorithmParameterException
|
||||||
("Key size must be at least 512 bit");
|
("Key size must be at least 512 bit");
|
||||||
}
|
}
|
||||||
|
if (algorithm.equals("RSA")) {
|
||||||
|
BigInteger tmpExponent = rsaPublicExponent;
|
||||||
|
if (params != null) {
|
||||||
|
tmpExponent = params.getPublicExponent();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Reuse the checking in SunRsaSign provider.
|
||||||
|
// If maxKeySize is -1, then replace it with
|
||||||
|
// Integer.MAX_VALUE to indicate no limit.
|
||||||
|
RSAKeyFactory.checkKeyLengths(keySize, tmpExponent,
|
||||||
|
minKeySize,
|
||||||
|
(maxKeySize==-1? Integer.MAX_VALUE:maxKeySize));
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new InvalidAlgorithmParameterException(e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (algorithm.equals("DH") && (params != null)) {
|
if (algorithm.equals("DH") && (params != null)) {
|
||||||
// sanity check, nobody really wants keys this large
|
// sanity check, nobody really wants keys this large
|
||||||
if (keySize > 64 * 1024) {
|
if (keySize > 64 * 1024) {
|
||||||
@ -219,9 +278,13 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
|||||||
// this restriction is in the spec for DSA
|
// this restriction is in the spec for DSA
|
||||||
// since we currently use DSA parameters for DH as well,
|
// since we currently use DSA parameters for DH as well,
|
||||||
// it also applies to DH if no parameters are specified
|
// it also applies to DH if no parameters are specified
|
||||||
if ((keySize > 1024) || ((keySize & 0x3f) != 0)) {
|
if ((keySize != 2048) &&
|
||||||
throw new InvalidAlgorithmParameterException
|
((keySize > 1024) || ((keySize & 0x3f) != 0))) {
|
||||||
("Key size must be a multiple of 64 and at most 1024 bit");
|
throw new InvalidAlgorithmParameterException(algorithm +
|
||||||
|
" key must be multiples of 64 if less than 1024 bits" +
|
||||||
|
", or 2048 bits");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -325,5 +388,4 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
|||||||
token.releaseSession(session);
|
token.releaseSession(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 7196382
|
||||||
|
* @summary Ensure that 2048-bit DH key pairs can be generated
|
||||||
|
* @author Valerie Peng
|
||||||
|
* @library ..
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
|
||||||
|
import javax.crypto.*;
|
||||||
|
|
||||||
|
public class TestDH2048 extends PKCS11Test {
|
||||||
|
|
||||||
|
private static void checkUnsupportedKeySize(KeyPairGenerator kpg, int ks)
|
||||||
|
throws Exception {
|
||||||
|
try {
|
||||||
|
kpg.initialize(ks);
|
||||||
|
throw new Exception("Expected IPE not thrown for " + ks);
|
||||||
|
} catch (InvalidParameterException ipe) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void main(Provider p) throws Exception {
|
||||||
|
if (p.getService("KeyPairGenerator", "DH") == null) {
|
||||||
|
System.out.println("KPG for DH not supported, skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", p);
|
||||||
|
kpg.initialize(2048);
|
||||||
|
KeyPair kp1 = kpg.generateKeyPair();
|
||||||
|
checkUnsupportedKeySize(kpg, 1536);
|
||||||
|
checkUnsupportedKeySize(kpg, 2176);
|
||||||
|
checkUnsupportedKeySize(kpg, 3072);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
main(new TestDH2048());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user