提交 6bf752f5 编写于 作者: V valeriep

7196382: PKCS11 provider should support 2048-bit DH

Summary: Query and enforce range checking using the values from native PKCS11 library.
Reviewed-by: xuelei
上级 ff2bca20
......@@ -58,6 +58,16 @@ extends AlgorithmParameterGeneratorSpi {
// The source of randomness
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
* and source of randomness.
......@@ -67,11 +77,11 @@ extends AlgorithmParameterGeneratorSpi {
* @param random the source of randomness
*/
protected void engineInit(int keysize, SecureRandom random) {
if ((keysize < 512) || (keysize > 2048) || (keysize % 64 != 0)) {
throw new InvalidParameterException("Keysize must be multiple "
+ "of 64, and can only range "
+ "from 512 to 2048 "
+ "(inclusive)");
// Re-uses DSA parameters and thus have the same range
try {
checkKeySize(keysize);
} catch (InvalidAlgorithmParameterException ex) {
throw new InvalidParameterException(ex.getMessage());
}
this.primeSize = keysize;
this.random = random;
......@@ -91,31 +101,29 @@ extends AlgorithmParameterGeneratorSpi {
protected void engineInit(AlgorithmParameterSpec genParamSpec,
SecureRandom random)
throws InvalidAlgorithmParameterException {
if (!(genParamSpec instanceof DHGenParameterSpec)) {
throw new InvalidAlgorithmParameterException
("Inappropriate parameter type");
}
if (!(genParamSpec instanceof DHGenParameterSpec)) {
throw new InvalidAlgorithmParameterException
("Inappropriate parameter type");
}
DHGenParameterSpec dhParamSpec = (DHGenParameterSpec)genParamSpec;
DHGenParameterSpec dhParamSpec = (DHGenParameterSpec)genParamSpec;
primeSize = dhParamSpec.getPrimeSize();
if ((primeSize<512) || (primeSize>2048) || (primeSize%64 != 0)) {
throw new InvalidAlgorithmParameterException
("Modulus size must be multiple of 64, and can only range "
+ "from 512 to 2048 (inclusive)");
}
primeSize = dhParamSpec.getPrimeSize();
exponentSize = dhParamSpec.getExponentSize();
if (exponentSize <= 0) {
throw new InvalidAlgorithmParameterException
("Exponent size must be greater than zero");
}
// Re-uses DSA parameters and thus have the same range
checkKeySize(primeSize);
// Require exponentSize < primeSize
if (exponentSize >= primeSize) {
throw new InvalidAlgorithmParameterException
("Exponent size must be less than modulus size");
}
exponentSize = dhParamSpec.getExponentSize();
if (exponentSize <= 0) {
throw new InvalidAlgorithmParameterException
("Exponent size must be greater than zero");
}
// Require exponentSize < primeSize
if (exponentSize >= primeSize) {
throw new InvalidAlgorithmParameterException
("Exponent size must be less than modulus size");
}
}
/**
......
/*
* 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.
*
* 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
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
private SecureRandom random;
P11KeyPairGenerator(Token token, String algorithm, long mechanism)
throws PKCS11Exception {
super();
this.token = token;
this.algorithm = algorithm;
this.mechanism = mechanism;
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")) {
initialize(256, null);
keySize = 256;
if ((minKeyLen == -1) || (minKeyLen < 112)) {
minKeyLen = 112;
}
if ((maxKeyLen == -1) || (maxKeyLen > 2048)) {
maxKeyLen = 2048;
}
} else {
initialize(1024, null);
// 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.algorithm = algorithm;
this.mechanism = mechanism;
this.minKeySize = minKeyLen;
this.maxKeySize = maxKeyLen;
initialize(keySize, null);
}
// see JCA spec
......@@ -94,9 +141,7 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
} catch (InvalidAlgorithmParameterException e) {
throw new InvalidParameterException(e.getMessage());
}
this.keySize = keySize;
this.params = null;
this.random = random;
if (algorithm.equals("EC")) {
params = P11ECKeyFactory.getECParameterSpec(keySize);
if (params == null) {
......@@ -105,33 +150,35 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
+ keySize + " bits");
}
}
this.keySize = keySize;
this.random = random;
}
// see JCA spec
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
throws InvalidAlgorithmParameterException {
token.ensureValid();
int tmpKeySize;
if (algorithm.equals("DH")) {
if (params instanceof DHParameterSpec == false) {
throw new InvalidAlgorithmParameterException
("DHParameterSpec required for Diffie-Hellman");
}
DHParameterSpec dhParams = (DHParameterSpec)params;
int tmpKeySize = dhParams.getP().bitLength();
checkKeySize(tmpKeySize, dhParams);
this.keySize = tmpKeySize;
this.params = dhParams;
DHParameterSpec dhParams = (DHParameterSpec) params;
tmpKeySize = dhParams.getP().bitLength();
checkKeySize(tmpKeySize, null);
// XXX sanity check params
} else if (algorithm.equals("RSA")) {
if (params instanceof RSAKeyGenParameterSpec == false) {
throw new InvalidAlgorithmParameterException
("RSAKeyGenParameterSpec required for RSA");
}
RSAKeyGenParameterSpec rsaParams = (RSAKeyGenParameterSpec)params;
int tmpKeySize = rsaParams.getKeysize();
RSAKeyGenParameterSpec rsaParams =
(RSAKeyGenParameterSpec) params;
tmpKeySize = rsaParams.getKeysize();
checkKeySize(tmpKeySize, rsaParams);
this.keySize = tmpKeySize;
this.params = null;
// override the supplied params to null
params = null;
this.rsaPublicExponent = rsaParams.getPublicExponent();
// XXX sanity check params
} else if (algorithm.equals("DSA")) {
......@@ -139,11 +186,9 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
throw new InvalidAlgorithmParameterException
("DSAParameterSpec required for DSA");
}
DSAParameterSpec dsaParams = (DSAParameterSpec)params;
int tmpKeySize = dsaParams.getP().bitLength();
checkKeySize(tmpKeySize, dsaParams);
this.keySize = tmpKeySize;
this.params = dsaParams;
DSAParameterSpec dsaParams = (DSAParameterSpec) params;
tmpKeySize = dsaParams.getP().bitLength();
checkKeySize(tmpKeySize, null);
// XXX sanity check params
} else if (algorithm.equals("EC")) {
ECParameterSpec ecParams;
......@@ -155,28 +200,42 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
("Unsupported curve: " + params);
}
} else if (params instanceof ECGenParameterSpec) {
String name = ((ECGenParameterSpec)params).getName();
String name = ((ECGenParameterSpec) params).getName();
ecParams = P11ECKeyFactory.getECParameterSpec(name);
if (ecParams == null) {
throw new InvalidAlgorithmParameterException
("Unknown curve name: " + name);
}
// override the supplied params with the derived one
params = ecParams;
} else {
throw new InvalidAlgorithmParameterException
("ECParameterSpec or ECGenParameterSpec required for EC");
}
int tmpKeySize = ecParams.getCurve().getField().getFieldSize();
checkKeySize(tmpKeySize, ecParams);
this.keySize = tmpKeySize;
this.params = ecParams;
tmpKeySize = ecParams.getCurve().getField().getFieldSize();
checkKeySize(tmpKeySize, null);
} else {
throw new ProviderException("Unknown algorithm: " + algorithm);
}
this.keySize = tmpKeySize;
this.params = params;
this.random = random;
}
private void checkKeySize(int keySize, AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException {
// NOTE: 'params' is only used for checking RSA keys currently.
private void checkKeySize(int keySize, RSAKeyGenParameterSpec params)
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 (keySize < 112) {
throw new InvalidAlgorithmParameterException
......@@ -187,41 +246,45 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
throw new InvalidAlgorithmParameterException
("Key size must be at most 2048 bit");
}
return;
} else if (algorithm.equals("RSA")) {
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) {
throw new InvalidAlgorithmParameterException
("Key size must be at least 512 bit");
}
if (algorithm.equals("DH") && (params != null)) {
// sanity check, nobody really wants keys this large
if (keySize > 64 * 1024) {
throw new InvalidAlgorithmParameterException
("Key size must be at most 65536 bit");
}
} else {
// this restriction is in the spec for DSA
// since we currently use DSA parameters for DH as well,
// it also applies to DH if no parameters are specified
if ((keySize > 1024) || ((keySize & 0x3f) != 0)) {
// RSA, DH, DSA
if (keySize < 512) {
throw new InvalidAlgorithmParameterException
("Key size must be a multiple of 64 and at most 1024 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)) {
// sanity check, nobody really wants keys this large
if (keySize > 64 * 1024) {
throw new InvalidAlgorithmParameterException
("Key size must be at most 65536 bit");
}
} else {
// this restriction is in the spec for DSA
// since we currently use DSA parameters for DH as well,
// it also applies to DH if no parameters are specified
if ((keySize != 2048) &&
((keySize > 1024) || ((keySize & 0x3f) != 0))) {
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);
}
}
}
/*
* 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());
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册